线性结构:内存连续,能通过下标访问。
链式结构:内存不连续,不能通过下标访问,查找元素需要从头到尾遍历。
单链表
单链表:有一个一个节点,用指针方式串起来,有root节点,是入口,第一个节点为首节点(Head),有尾节点(Tail)
#Node节点,表示每一个元素
class Node(object):
#定义节点,两个值:value,next
def __init__(self, value=None, next=None):
self.value, self.next = value, next
#定义单链表
class LinkedList(object):
#初始化,None为无限
def __init__(self, maxsize=None):
self.maxsize = maxsize
#根节点
self.root = Node()
#长度
self.length = 0
#最后一个节点
self.tailnode = None
#返回记录的长度
def __len__(self):
return self.length
#构造一个节点,再用最后一个节点指向他,O(1)
def append(self, value):
#判断是否超过了最大值,若超过了,抛出异常
if self.maxsize is not None and len(self) > self.maxsize:
raise Exception('FUll')
node = Node(value)
tailnode = self.tailnode
if tailnode is None:
self.root.next = node
else:
tailnode.next = node
#更新尾节点
self.tailnode = node
self.length += 1
#往左边节点插入,O(1)
def appendleft(self, value):
#头结点headnode
headnode = self.root.next
#构造新节点
node = Node(value)
self.root.next = node
node.next = headnode
self.length += 1
#遍历,从Head节点到tail节点
def iter_node(self):
currnode = self.root.next
while currnode is not self.tailnode:
yield currnode
#更新节点
currnode = currnode.next
yield currnode
#__iter__方法
def __iter__(self):
for node in self.iter_node():
yield node.value
#删除,将其前一个节点的next指向被查询节点的下一个即可,复杂度O(n)
def remove(self, value):
prevnode = self.root
currnode = self.root.next
while currnode.next is not None:
if currnode.value == value:
#上一个节点的元素指向下一个节点的下一个元素
prevnode.next = currnode.next
#NOTE:注意更新tailnode
if currnode is self.tailnode:
self.tailnode = prevnode
del currnode
self.length -= 1
return 1
else:
#更新prevnode
prevnode = currnode
return -1
#查找操作,复杂度O(n)
def find(self, value):
index = 0
for node in self.iter_node():
if node.value == value:
return index
index += 1
return -1
#拿掉第一个节点
def popleft(self):
if self.root.next is None:
raise Exception('pop from empty LinkedList')
headnode = self.root.next
self.root.next = headnode.next
self.length -= 1
value = headnode.value
del headnode
#返回value值
return value
#清除操作
def claer(self):
for node in self.iter_node():
del node
self.root.next = None
self.length = 0
#测试脚本
def test_linked_list():
ll = LinkedList()
ll.append(0)
ll.append(1)
ll.append(2)
#断言
assert len(ll) == 3
assert ll.find(2) == 2
assert ll.find(3) == -1
ll.remove(0)
assert len(ll) == 2
assert ll.find(0) == -1
assert list(ll) ==[1, 2]
ll.appendleft(0)
assert list(ll) == [0, 1, 2]
assert len(ll) == 3
headvalue = ll.popleft()
assert headvalue == 0
assert len(ll) == 2
assert list(ll) == [1, 2]
ll.claer()
assert len(ll) == 0
循环双端链表
双链表:节点比单链表节点多一个prew值。可双向查找。
#Node节点,表示每一个元素
class Node(object):
#定义节点,两个值:value,prew, next
def __init__(self, value=None, prew=None, next=None):
self.value,self.prew, self.next = value, prew, next
#循环双端链表
class CircualDoubleLinedList(object):
#初始化
def __init__(self, maxsize=None):
self.maxsize = maxsize
node = Node()
node.next, node.prew = 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.prew
#添加操作
def append(self, value):
#判断是否超过了最大值,若超过了,抛出异常
if self.maxsize is not None and len(self) > self.maxsize:
raise Exception('FUll')
node = Node(value=value)
tailnode = self.tailnode
tailnode.next = node
node.prew = tailnode
node.next = self.root
self.root.prew = node
self.length += 1
#左侧插入
def appendleft(self, value):
if self.maxsize is not None and len(self) > self.maxsize:
raise Exception('FUll')
node = Node(value = value)
#如果节点为空
if self.root.next is self.root:
node.next = self.root
node.prew = self.root
self.root.next = node
self.root.prew = node
else:
node.prew = self.root
headnode = self.root.next
node.next = headnode
headnode.prew = node
self.root.next = node
self.length += 1
#删除操作,O(1)
def remove(self, node):
if node is self.root:
return
else:
node.prew.next = node.next
node.next.prew = node.prew
self.length -= 1
return node
#遍历
def iter_node(self):
if self.root.next is self.root:
return
curnode = self.root.next
while curnode.next is not self.root:
yield curnode
curnode = curnode.next
yield curnode
#__iter__方法
def __iter__(self):
for node in self.iter_node():
yield node.value
#反向遍历
def iter_node_reverse(self):
if self.root.prew is self.root:
return
curnode = self.root.prew
while curnode.prew is not self.root:
yield curnode
curnode = curnode.prew
yield curnode
#测试
def test_double_link_list():
dll = CircualDoubleLinedList()
assert len(dll) == 0
dll.appeend(0)
dll.appeend(1)
dll.appeend(2)
assert list(dll) == [0, 1, 2]
assert [node.value for node in dll.iter_node()] == [0, 1, 2]
assert [node.value for node in dll.iter_node_reverse()] == [2, 1, 0]
headnode = dll.headnode()
assert headnode.value == 0
dll.remove(headnode)
assert len(dll) == 2
assert [node.value for node in dll.iter_node()] == [1, 2]
dll.appendleft(0)
assert [node.value for node in dll.iter_node_reverse()] == [2, 1, 0]