单链表ADT模型
节点类
class Node():
def __init__(self,elem):
#存放元素数据
self.elem=elem
#下一个节点
self.next=None
单链表的操作
class Single_LinkList():
def __init__(self,node=None):
#头节点定义为私有变量
self._head=node
def is_empty(self):
#判断链表是否为空
if self._head is None:
return True
else:
return False
def length(self):
#返回链表的长度
# cur游标,用来移动遍历节点
# count用来计数
cur=self._head
count = 0
while cur !=None:
count+=1
cur=cur.next
return count
def travel(self):
#遍历整个链表
cur=self._head
while cur!=None:
print(cur.elem,end=' ')
cur=cur.next
print()
def add(self,item):
#在头部添加一个节点
# 先创建一个保存item值的节点
node=Node(item)
#判断链表是否为空
if self._head==None:
self._head=node
else:
# 将新节点的链接域next指向头节点,即_head指向的位置
node.next=self._head
# 将链表的头_head指向新节点
self._head=node
def append(self,item):
#在尾部添加一个节点
node=Node(item)
#若链表为空,直接将该节点作为链表的第一个元素
if self._head==None:
self._head=node
else:
cur = self._head
while cur.next !=None:
cur=cur.next
cur.next=node
def insert(self,pos,item):
#在指定位置pos添加节点
#pos从0开始
# 若指定位置pos为第一个元素之前,则执行头部插入
if pos<=0:
self.add(item)
# 若指定位置超过链表尾部,则执行尾部插入
elif pos>=self.length():
self.append(item)
# 找到指定位置
else:
# pre用来指向指定位置pos的前一个位置pos-1,初始从头节点开始移动到指定位置
pre=self._head
count=0
node = Node(item)
while count<(pos-1):
count+=1
pre=pre.next
# 先将新节点node的next指向插入位置的节点
node.next=pre.next
# 将插入位置的前一个节点的next指向新节点
pre.next=node
def remove(self,item):
#删除某一个节点
# 若链表为空,则直接返回
if self.is_empty():
return
pre=None
cur=self._head
while cur!=None:
#若没有找到元素,继续按链表后移节点
if cur.elem!=item:
pre=cur
cur=cur.next
else:
#若要删除的点为头节点
if cur==self._head:
self._head=cur.next
#删完要break,不然陷入死循环
break
else:
#要删除的点不是头节点
pre.next=cur.next
break
def search(self,item):
#查找节点是否存在
cur=self._head
while cur!=None:
if cur.elem==item:
return True
else:
cur = cur.next
return False
链表与顺序表的对比
链表失去了顺序表随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大,但对存储空间的使用要相对灵活。
链表与顺序表的各种操作复杂度如下所示:
操作 | 链表 | 顺序表 |
---|---|---|
在头部插入/删除 | O(1) | O(n) |
在尾部插入/删除 | O(n) | O(1) |
在中间插入/删除 | O(n) | O(n) |
注意虽然表面看起来复杂度都是 O(n),但是链表和顺序表在插入和删除时进行的是完全不同的操作。链表的主要耗时操作是遍历查找,删除和插入操作本身的复杂度是O(1)。顺序表查找很快,主要耗时的操作是拷贝覆盖。因为除了目标元素在尾部的特殊情况,顺序表进行插入和删除时需要对操作点之后的所有元素进行前后移位操作,只能通过拷贝和覆盖的方法进行。
单向循环链表
class Node():
"""节点"""
def __init__(self,elem):
self.elem=elem
self.next=None
class Single_CYCLE_LinkList():
"""单向循环链表"""
def __init__(self,node=None):
self._head=node
if node:
node.next=node
def is_empty(self):
#链表是否为空
if self._head==None:
return True
else:
return False
def length(self):
#链表长度
if self.is_empty():
return 0
cur=self._head
count=1
while cur.next!=self._head:
count+=1
cur=cur.next
return count
def travel(self):
#遍历整个链表
if self.is_empty():
return
else:
cur=self._head
while cur.next!=self._head:
print(cur.elem,end=' ')
cur=cur.next
print(cur.elem)
def add(self,item):
node=Node(item)
if self.is_empty():
self._head=node
node.next=node
else:
cur=self._head
while cur.next!=self._head:
cur=cur.next
node.next=self._head
self._head=node
cur.next=node
def append(self,item):
node=Node(item)
if self._head == None:
self._head = node
node.next=node
else:
cur=self._head
while cur.next!=self._head:
cur=cur.next
cur.next=node
node.next=self._head
def insert(self,pos,item):
if pos<=0:
self.add(item)
elif pos>=self.length():
self.append(item)
else:
node=Node(item)
pre=self._head
count=0
while count<pos-1:
count+=1
pre=pre.next
node.next=pre.next
pre.next=node
def remove(self,item):
"""删除一个节点"""
# 若链表为空,则直接返回
if self.is_empty():
return
# 将cur指向头节点
pre=None
cur=self._head
while cur.next !=self._head:
if cur.elem==item:
#先判断此节点是否是头结点
if cur==self._head:
#先找到尾节点
rear=self._head
while rear.next !=self._head:
rear=rear.next
rear.next=self._head
self._head=cur.next
else:
#中间节点
pre.next=cur.next
return
else:
pre=cur
cur=cur.next
#退出循环,cur指向尾节点
if cur.elem==item:
if self.length()==1:
self._head=None
else:
pre.next = cur.next
def search(self,item):
if self.is_empty():
return False
cur=self._head
while cur.next!=self._head:
if cur.elem==item:
return True
else:
cur=cur.next
if cur.elem==item:
return True
return False
if __name__ == '__main__':
single_obj=Single_CYCLE_LinkList()
print(single_obj.is_empty())
print(single_obj.length())
single_obj.append(1)
single_obj.append(2)
single_obj.append(3)
single_obj.append(4)
single_obj.append(5)
single_obj.travel()
single_obj.add(-1)
single_obj.travel()
single_obj.insert(-1,-2)
single_obj.travel()
single_obj.insert(2,0)
single_obj.travel()
print(single_obj.search(0))
single_obj.remove(2)
single_obj.travel()
single_obj.remove(5)
single_obj.travel()
single_obj.remove(-2)
single_obj.travel()