基本数据结构

基本的数据结构参考第一章导论,下面是四种基本的线性数据结构。

1. 栈

1.1 栈的概念及应用

python中的线性结构 python线性数据结构_python中的线性结构

  • 排序原则LIFO(后入先出)
  • 网页的返回机制,其URL结构为栈,Word的撤销按钮均使用了栈的结构

【Python实现】

class Stack:
    def __init__(self):
        self.items = []
        
    def isEmpty(self):
        return self.items == []
    
    def push(self, item):
        self.items.append(item)
        
    def pop(self):
        return self.items.pop()
    
    def peek(self):
        return self.items[len(self.items)-1]
    
    def size(self):
        return len(self.items)

【栈的应用】

def parChecker(parString):
    s = Stack()
    balance = True
    for i in parString:
        if i == "(":
            s.push(i)
        else:
            if s.isEmpty():
                balance = False
            else:
                s.pop()
    if s.isEmpty() and balance:
        return True
    else:
        return False

python中的线性结构 python线性数据结构_python中的线性结构_02

def parChecker(parString):
    s = Stack()
    balance = True
    opens = '{[('
    closers = '}])'
    for i in parString:
        if i in "{[(":
            s.push(i)
        else:
            if s.isEmpty():
                balance = False
            else:
                top = s.pop()
                if opens.index(top) != closers.index(i):
                    balance = False
    if s.isEmpty() and balance:
        return True
    else:
        return False

python中的线性结构 python线性数据结构_python中的线性结构_03

def divideBy2(number):
    s = Stack()
    binString = ""
    while number > 0:
        i = number % 2
        s.push(i)
        number = number // 2
    while not s.isEmpty():
        binString += str(s.pop())
    return binString

1.2 表达式转换

  1. 全括号表达式转换为后序,向后移动运算符

python中的线性结构 python线性数据结构_链表_04

  1. 全括号表达式转换为前序,向前移动运算符

python中的线性结构 python线性数据结构_python中的线性结构_05

  1. 从中序到后序的通用转换法
import string
def infixToPostfix(infixExpr):
    prec = {"*":3, "/":3, "+":2, "-":2, "(":1}
    postString = ""
    opstack = Stack()
    for i in infixExpr:
        if i in string.ascii_uppercase:
            postString += i
        elif i == "(":
            opstack.push(i)
        elif i == ")":
            a = opstack.pop()
            while a != "(":
                postString += a
                a = opstack.pop()
        else:
            while (not opstack.isEmpty()) and (prec[opstack.peek()] >= prec[i]):
                postString += opstack.pop()
            opstack.push(i)       
    while not opstack.isEmpty():
        postString += opstack.pop()
    
    return postString

2. 队列

  • 队列是有序集合,添加操作发生在尾部,移除操作发生在头部。新元素从尾部进入队列,然后一直向前移动到头部,直到成为下一个被移除的元素。
  • 与栈相反,队列是FIFO(先进先出)

python中的线性结构 python线性数据结构_数据结构_06

【Python实现】

class Queue:
    def __init__(self):
        self.items = []
    def isEmpty(self):
        return self.items == []
    def enqueue(self, item):
        self.items.insert(0, item)
    def dequeue(self):
        return self.items.pop()
    def size(self):
        return len(self.items)
def JosephusProblem(nameList,number):
   queue = Queue()
   for i in nameList:
       queue.enqueue(i)
   while queue.size() > 1:
       for i in range(number):
           queue.enqueue(queue.dequeue())
       queue.dequeue()
   return queue.dequeue()

python中的线性结构 python线性数据结构_Stack_07

3. 双端队列

  • 双端队列是与队列类似的有序集合。它有一前,一后两端,元素在其中保持自己的位置。
  • 新元素既可以被添加到前端,也可以被添加到后端。
  • 已有的元素也能从任意一端移除。

python中的线性结构 python线性数据结构_数据结构_08

【Python实现】

class Deque:
    def __init__(self):
        self.items = []
    def isEmpty(self):
        return self.items == []
    def addFront(self, item):
        self.items.insert(0, item)
    def addRear(self, item):
        self.items.append(item)
    def removeFront(self):
        return self.items.pop(0)
    def removeRear(self):
        return self.items.pop()
    def size(self):
        return len(self.items)
def palchecker(aString):
    chardeque = Deque()
    
    for ch in aString:
        chardeque.addRear(ch)
    stillEqual = True
    while chardeque.size() > 1 and stillEqual:
        first = chardeque.removeFront()
        last = chardeque.removeRear()
        if first != last:
            stillEqual = False
            
    return stillEqual

python中的线性结构 python线性数据结构_数据结构_09

4. 链表

  • 与前面的顺序表不同,链表是无序结构,连接了内存中的不相连的内存数据。
  • 链表中包含两块信息,一块存放数据,另一块指向下一块数据的地址,形成链式结构

4.1 链表的实现

【节点实现】

class Node:
    def __init__(self, initdata):
        self.data = initdata
        self.next = None
  • 无序列表是基于节点集合来构建的,每一个节点都通过显式的引用指向下一个节点;
  • 重要的一点,列表类并不包含任何节点对象,而只有指向整个链表结构中第一个节点的引用。

python中的线性结构 python线性数据结构_Stack_10

  • isEmpty() 判断链表是否为空
  • add() 从头部插入元素
  • append() 从尾部插入元素
  • insert() 指定元素位置插入元素
  • remove() 从链表中移除元素(移除第一个查到的相同元素)
  • length() 返回链表的长度
  • search() 查找链表中是否存在某元素
  • travel() 遍历打印链表
class SingleLinkList:
    def __init__(self):
        self.head = None

    def isEmpty(self):
        return self.head == None

    def add(self, item):
        """头插法"""
        temp = Node(item)
        temp.next = self.head
        self.head = temp

    def append(self, item):
        """尾插法"""
        node = Node(item)
        if self.isEmpty():
            self.head = node
        else:
            current = self.head
            while current.next != None:
                current = current.next
            current.next = node

    def insert(self, pos, item):
        """
        :param pos: 要插入的位置
        :param item: 插入的元素
        :return: None
        """
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            pre = self.head
            count = 0
            while count < pos - 1:
                count += 1
                pre = pre.next
            node = Node(item)
            node.next = pre.next
            pre.next = node

    def remove(self, item):
        current = self.head
        pre = None
        found = False
        while not found:
            if current.data == item:
                found = True
            else:
                pre = current
                current = current.next
        if pre == None:
            self.head = current.next
        else:
            pre.next = current.next

    def length(self):
        current = self.head
        count = 0
        while current != None:
            count += 1
            current = current.next
        return count

    def search(self, item):
        current = self.head
        while current != None:
            if current.data == item:
                return True
            else:
                current = current.next
        return False

    def travel(self):
        current = self.head
        while current != None:
            print(current.data)
            current = current.next


if __name__ == "__main__":
    sll = SingleLinkList()
    print(sll.isEmpty())
    print(sll.length())
    sll.insert(0, 100)
    sll.add(100)
    sll.travel()
    sll.remove(100)
    print("===========")
    sll.travel()
    print(sll.isEmpty())

4.2 链表与顺序表

链表失去了顺序表随机读取的优点,同时链表由于附加有地址信息,相应的空间消耗也会增大,但是对于一个较大的数据,链表能够灵活的调用不连续的内存空间,使用相对灵活。

操作

链表

顺寻表

访问元素

\(O(n)\)

\(O(1)\)

头部插入

\(O(1)\)

\(O(n)\)

尾部插入

\(O(n)\)

\(O(1)\)

中间插入

\(O(n)\)

\(O(n)\)