python数据结构——用链表实现栈、队列、循环队列、双向队列

这篇博客介绍了如何使用Python实现链表数据结构,包括栈、队列、循环队列和双向队列。首先回顾了链表的基本概念,然后详细阐述了每个结构的实现原理,特别提到了在实现双向队列时利用了双向链表的特性。文章提供了具体的代码示例来帮助理解。

前言

先复习一下几种数据结构吧。
链表,就是一个个结点,用指针的方式来连接起来,因为py的语言特点,我们只需要将next赋值为下一个对象的变量名即可。(变量名本身就可以理解成一个指针索引)
如果链表还有问题,看这里

队列和栈,前两天用list实现了一个,在这里,也有讲解。
一个是first in first out,另一个是first in last out。

双向队列,就是两端都能插入删除的队列,这个的实现需要双向链表。
循环队列,之前是list实现的,这里我们用一次node,结构基于循环链表。
双向链表和循环链表在这里,都是讲过的,不再赘述。

实现链表

没有链表,我们都做不了。

链表的本质上就是一个个的结点么, 所以这里我先给出了结点的定义。

class _Node():
	"""lightweight,nonpublic class for storing linked node"""
	__slots__ = '_element','_next'
	def __init__(self,element,next):
		self._element = element
		self._next = next

他那个__slots__对象,貌似是能节省一个dict,正常直接创建两个变量也是一样的。

我们将这个类放在整体的大类中就可以了。

栈:

class LinkedStack():
    # 使用链表实现栈,链表第一项为栈顶,没有头节点
    class _Node():
        """lightweight,nonpublic class for storing linked node"""
        __slots__ = '_element','_next'
        def __init__(self,element,next):
            self._element = element
            self._next = next
    def __init__(self):
        """create an empty stack"""
        self._head = None
        self._size = 0
    def __len__(self):
        """return the number of elementsin the stack"""
        return self._size
    def is_empty(self):
        """return true if the stack is empty"""
        return self._size==0
    def push(self,e):
        """add an element e to the top of the stack"""
        self._head = self._Node(e,self._head)
        self._size += 1
    def top(self):
        """return(but not remove) the element at the top of the stack"""
        if self.is_empty():
            raise Empty('stack is empty')
        return self._head._element
    def pop(self):
        """remove and return the element from the top of the stack"""
        if self.is_empty():
            raise Empty('stack is empty')
        answer = self._head._element
        self._head = self._head._next
        self._size -= 1
        return answer

队列:

class LinkedQueue():
    # 使用node节点实现队列,链表头是队首
    class _Node():
        """lightweight,nonpublic class for storing a singly linked node"""
        __slots__ = '_element','_next'
        def __init__(self,element,next):
            self._element = element
            self._next = next
    def __init__(self):
        """create an empty queue"""
        self._head = None
        self._tail = None
        self._size = 0
    def __len__(self):
        """return the length of elements in the queue"""
        return self._size
    def is_empty(self):
        """return true if the queue is empty"""
        return self._size == 0
    def first(self):
        """return but not remove the element at the front of the queue"""
        if self.is_empty():
            raise Empty('queue is empty')
        return self._head._element
    def dequeue(self):
        """remove and return the first element of the queue"""
        if self.is_empty():
            raise Empty('queue is empty')
        answer = self._head._element
        self._head = self._head._next
        self._size -= 1
        if self.is_e():
            self._tail = None
        return answer
    def enqueue(self,e):
        """add an element to the back of queue"""
        newset = self._Node(e,None)
        if self.is_empty():
            self._head = newset
        else:
            self._tail._next = newset
        self._tail = newset
        self._size += 1

循环队列

基于循环链表,本质上就是将之前链表的tail.next = head,和head接上。
这样我们只使用一个tail存储就能遍历整个链表。

注意最开始没有对象,添加第一个对象时,既是队首也是队尾。
如果是只有一个对象,pop之后tail=none

代码:

class CircularQueue():
    """queue implementation using circularly linked list for storage"""
    class _Node():
        """lightweight,nonpublic class for storing a singly linked node"""
        __slots__ = '_element','_next'
        def __init__(self,element,next):
            self._element = element
            self._next = next
    def __init__(self):
        """create an empty queue"""
        self._tail = None
        self._size = 0
    def __len__(self):
        """return the number of elements in the queue"""
        return self._size
    def is_empty(self):
        """return true if the queue is empty"""
        return self._size==0
    def first(self):
        """return but not remove the element at the front of the queue"""
        if self.is_empty():
            raise Empty('queue is empty')
        head = self._tail._next
        return head._emelent
    def dequeue(self):
        """remove and return the first element of the queue"""
        if self.is_empty():
            raise Empty('queue is empty')
        oldhead = self._tail._next
        if self._size == 1:
            self._tail = None
        else:
            self._tail._next = oldhead._next
        self._size -= 1
        return oldhead._element
    def enqueue(self,e):
        """add a element to the back of the queue"""
        newest = self._Node(e,None)
        if self.is_empty():
            newest._next = newest
        else:
            newest._next = self._tail._next
            self._tail._next = newest
        self._tail = newest
        self._size += 1
    def rotate(self):
        """rotate front element to the back of the queue"""
        # 这是一个遍历的方法,相当于__next__()
        if self._size > 0:
            self._tail = self._tail._next

双向链表

双向链表其实和单向差的不多,主要是每一个都有两个指针,所以插入删除麻烦一点,再就是注意边界条件

先实现一个双向链表:(因为是给双向队列服务的,所以用了私有变量形式)
我们实现的双向链表是有头节点和尾节点的!

class _DoublyLinkedBase():
    """a base class poviding a boubly linked list representation"""
    class _Node():
        __slots__ = '_element','_prev','_next'
        def __init__(self,element,prev,next):
            self._element = element
            self._prev = prev
            self._next = next
    def __init__(self):
        """create a empty list"""
        # 创建头尾结点并初始化
        self._header = self._node(None,None,None)
        self._trailer = self._Node(None,None,None)
        self._header._next = self._trailer
        self._trailer._prev = self._header
        self._size = 0
    def __len__(self):
        """return the number of elements in the list"""
        return self._size
    def is_empty(self):
        """return true if the list is empty"""
        return self._size==0
    def _insert_between(self,e,predecessor,successor):
        """add element e between pre and suc"""
        newest = self._Node(e,predecessor,successor)
        predecessor._next = newest
        successor._prev = newest
        self._size += 1
        return newest
    def _delete_node(self,node):
        """delete nonsentinel node from the list and return its element"""
        predecessor = node._prev
        successor = node._next
        predecessor._next = successor
        successor._prev - predecessor
        self._size -= 1
        element = node._element
        # be helpful for python to delete the node
        node._prev = node._next = node._element = None
        return element

双向队列

这样我们的双向队列就方便了很多,代码:

class LinkedDeque(_DoublyLinkedBase):
    """double-ended queue implementation based on a doubly linked list"""
    def first(self):
        """return but not remove the element at the front of the deque"""
        if self.is_empty():
            raise Empty('queue is empty')
        return self._header._next._element
    def last(self):
        """return but not remove the element at rhe back of the deque"""
        if self.is_empty():
            raise Empty('queue is empty')
        return self._trailer._prev._element
    def insert_first(self,e):
        """add an element to the front of the deque"""
        self._insert_between(e,self._header,self._header._next)
    def insert_last(self,e):
        """add an element to the back of the deque"""
        self._insert_between(e,self._trailer._prev,self._trailer)
    def delete_first(self):
        """remove and return the element from the front of the deque"""
        if self.is_empty():
            raise Empty('deque is empty')
        return self._delete_node(self._header._next)
    def delete_last(self):
        """remove and return the element from the back of the deque"""
        if self.is_empty():
            raise Empty('deque is empty')
        return self._delete_node(self._trailer._prev)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值