单链表缺点:
- remove 时间O(n)
- 单向遍历
双链表:
- 有
pre
结点和next
结点 - 循环双端链表:
- 属性:
- data : root、maxsize、length
- method:headnode、tailnode、append、appendleft、remove (这个变为O(1)的时间复杂度)、iter_node、iter_node_reverse
- 属性:
# -*- coding:utf-8 -*-
# Author: Greed_Vic(PL Z)
# Product_name: PyCharm
# File_name: CircularDoubleLinkedList
# @Time: 22:42 2021/6/5
class Node(object):
"""
类似于C语言中的结构体
这一个节点中有数值域和指针域
"""
def __init__(self, val=None, pre=None, next=None):
self.val = val # 值
self.pre = pre # 指针
self.next = next
class CircularDoubleLinkedList(object):
"""
进行各种操作,借助上方的结构体,这里进行增加删减等操作
"""
def __init__(self, maxsize=None):
self.maxsize = maxsize # 定义一个最长长度
node = Node() # 创建一个节点,这个根节点不用做存储,只是为了更方便的管理整个链表
node.next, node.pre = node, node # 刚开始创建的时候要注意将根节点的上一个和下一个节点都安置在自己身上
self.root = node # 定义为根
self.length = 0 # 根不算入长度
def __len__(self):
return self.length # 特殊方法,求长度用的
def headnode(self):
return self.root.next # 头结点,为根的下一个
def tailnode(self):
return self.root.pre # 尾节点,根的上一个
def append(self, value):
if self.maxsize is not None and len(self) > self.maxsize:
raise Exception('FULL')
node = Node(val=value)
tailnode = self.tailnode() # 获取尾节点
tailnode.next = node # 连接尾部
node.pre = tailnode
node.next = self.root
self.root.pre = node
self.length += 1 # 长度加一
def appendleft(self, value):
if self.maxsize is not None and len(self) > self.maxsize:
raise Exception('FULL')
node = Node(val=value) # 创建
if self.root.next is self.root: # 如果还没有头结点
node.next = self.root
node.pre = self.root
self.root.next = node
self.root.pre = node
else:
node.pre = self.root
headnode = self.root.next
node.next = headnode
headnode.pre = node
self.root.next = node
self.length += 1
def remove(self, node):
"""
删除结点,针对头尾结点的删除,操作时间复杂度O(1)
:param node:
:return:
"""
if node is self.root:
return
else:
node.pre.next = node.next
node.next.pre = node.pre
self.length -= 1
return node
def iter_node(self):
"""
正向遍历
:return:
"""
if self.root.next is self.root:
return
curnode = self.root.next # 从头结点开始
while curnode.next is not self.root: # 如果下一个结点不是None,继续遍历
yield curnode # 形成可迭代对象
curnode = curnode.next
yield curnode # 最后再一次遍历,这个是因为其下一个结点是None
def __iter__(self):
for node in self.iter_node(): # 特殊方法写出迭代方法,迭代得到值
yield node.val
def iter_node_reverse(self):
if self.root.pre is self.root:
return
curnode = self.root.pre # 从后往前,获取尾节点
while curnode.pre is not self.root: # 如果未遍历到头结点则继续生成
yield curnode
curnode = curnode.pre
yield curnode
if __name__ == '__main__':
"""
检测
"""
def test_double_link_list():
dll = CircularDoubleLinkedList(12)
assert len(dll) == 0
dll.append(0)
dll.append(1)
dll.append(2)
assert len(dll) == 3
headnode = dll.headnode()
assert headnode.val == 0
dll.remove(headnode)
assert len(dll) == 2
dll.appendleft(99)
assert dll.tailnode().val == 2
assert len(dll) == 3
assert [node.val for node in dll.iter_node()] == [99, 1, 2]
assert [node.val for node in dll.iter_node_reverse()] == [2, 1, 99]
print("Test Done!")
test_double_link_list()