基础数据结构:栈、队列——Python实现

基础数据结构:栈、队列——Python实现

上一节我们重点介绍了数据结构的顺序与链式存储结构,那么这次我们来实现一下队列这两种最基础的线性逻辑结构。

对栈和队列最简单的描述,也是它们最核心的性质,就是:

  • 栈 —— 后进先出
  • 队列 —— 先进先出

一个简单的比喻就是:
像是将书一本本依次平摞在一个箱子里,后放入箱子的将先被拿出。
队列就如排队,先来排队的人先被接待。

这是逻辑上的两种数据结构,对应我们前面所讲的顺序表链表两种存储结构,我们在编程实现数据结构时又可以通过继承以上两种表,派生出顺序栈、顺序队列、链式栈、链式队列。或者单独实现栈和队列的基类,通过多重继承(c++\Python)或者组合(Java)两两结合得出以上四种数据结构。


使用Python的list实现顺序栈和顺序队列十分简单,我们只需要继承上一节中的顺序表,再添加一个出栈或出队列的函数即可:

# 基类:顺序表
class List:

    def __init__(self):
        self.list = []

    def __str__(self):
        return str(self.list)

    def put(self, item):
        self.list.append(item)

    def size(self):
        return len(self.list)

    def isEmpty(self):
        return self.list == []

# 子类:顺序栈
class ListStack(List):

    def pop(self):
        if self.isEmpty():
            return None
        else:
            return self.list.pop(-1)


# 子类:顺序队列
class ListQueue(List):

    def dequeue(self):
        if self.isEmpty():
            return None
        else:
            return self.list.pop(0)

使用了Python基本数据结构list中的方法append和pop来实现入和出的操作,我们只需要改变pop方法的index参数便可实现出栈和出队列的逻辑。

#测试
s=ListStack()
q=ListQueue()
for i in range(0,10):
    s.put(i)
    q.put(i)
print("Stack:",s)
print("Queue:",q)
for i in range(0,5):
    print("Stack pop:",s.pop())
    print("Queue dequeue:",q.dequeue())
print("Stack:",s)
print("Queue:",q)
#输出
Stack: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Queue: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Stack pop: 9
Queue dequeue: 0
Stack pop: 8
Queue dequeue: 1
Stack pop: 7
Queue dequeue: 2
Stack pop: 6
Queue dequeue: 3
Stack pop: 5
Queue dequeue: 4
Stack: [0, 1, 2, 3, 4]
Queue: [5, 6, 7, 8, 9]

继承链表基类,得到链式栈和链式队列:
上一篇提到了我们可以增加rear字段方便尾部插入,但是在删除时我们需要将rear向前移动一位,为了避免遍历全表,我们就需要双向链表,在node结构中增加last来指向前一个结点。但其实将链表首位相接构成双向循环链表的话,我们就不需要rear而是用head.last来查到尾结点。

以下双向循环列表基类的内部方法做了一点点修改,设计思路跟上面的顺序方法相比有所改变:

# 双向循环链表
class DoubleLoopLinked:

    class __Node:
        item = None
        next = None
        last = None

        def __init__(self, item, n, l):
            self.item = item
            self.next = n
            self.last = l

    def __init__(self):
        self.__head = self.__Node(None, None, None)
        self.__size = 0

    def __str__(self):
        p = self.__head.next
        l = []
        while p != self.__head:
            l.append(p.item)
            p = p.next
        return str(l)

    #Python只有公有和私有两种类型的成员,实际上并没有保护成员
    #这里将基类的插入删除操作定义为模拟的保护性方法(函数名前加单下划线def _function(self))
    #只允许派生类内使用,而不能在外部(如主函数里)访问
    #但事实上只是模拟,经测试,pycharm虽然有提示为protected member,但实际上类外部依然可以访问
    # 尾插法
    def _insertToTail(self, item):
        if self.isEmpty():
            node = self.__Node(item, self.__head, self.__head)
            self.__head.next = node
            self.__head.last = node
        else:
            node = self.__Node(item, self.__head, self.__head.last)
            self.__head.last.next = node
            self.__head.last = node
        self.__size += 1

    # 头插法
    def _insertToHead(self, item):
        if self.isEmpty():
            node = self.__Node(item, self.__head, self.__head)
            self.__head.next = node
            self.__head.last = node
        else:
            node = self.__Node(item, self.__head.next, self.__head)
            self.__head.next.last = node
            self.__head.next = node
        self.__size += 1

    # 删除头结点
    def _popHead(self):
        if self.isEmpty():
            return None
        else:
            node = self.__head.next
            self.__head.next = node.next
            node.next.last = self.__head
            self.__size -= 1
            it = node.item
            del node
            return it

    # 删除尾结点
    def _popTail(self):
        if self.isEmpty():
            return None
        else:
            node = self.__head.last
            self.__head.last = node.last
            node.last.next = self.__head
            self.__size -= 1
            it = node.item
            del node
            return it

    def size(self):
        return self.__size

    def isEmpty(self):
        return self.__size == 0

我们在实现栈和队列时,只需要使用基类提供的方法:

# 子类:链式栈
class LinkedStack(DoubleLoopLinked):

    def push(self,item):
        self._insertToTail(item)

    def pop(self):
        return self._popTail()


# 子类:链式队列
class LinkedQueue(DoubleLoopLinked):

    def enqueue(self,item):
        self._insertToTail(item)

    def dequeue(self):
        return self._popHead()

测试结果与顺序存储方式相同。

你可能感兴趣的:(数据结构)