一、链表
1. 单向链表
(1). 增加,遍历,删除等操作
#coding=utf-8
class Node(object):
'''节点类'''
def __init__(self,elem):
self.elem=elem
self.next=None #一开始不知道这个节点指向谁
pass
# node=Node(100)
class SingLinkList(object):
'''单链表类'''
def __init__(self,node=None):
self.__head = node #一个私有的head属性指向了None
pass
def is_empty(self):
'''链表是否为空'''
return self.__head==None
pass
def length(self):
'''链表长度'''
cur=self.__head #cur游标:用来移动遍历节点
count=0 #count:记录数量
while cur!=None:
count+=1
cur=cur.next
return count
pass
def travel(self):
'''遍历整个链表'''
cur=self.__head
while cur!=None:
print(cur.elem,end=' ')
cur=cur.next
print('')
pass
def add(self,item):
'''链表头部添加元素'''
node=Node(item)
node.next=self.__head
self.__head=node
pass
def append(self,item):
'''链表尾部添加元素'''
node=Node(item)
if self.is_empty():
self.__head=node
else:
cur=self.__head
while cur.next!=None:
cur=cur.next
cur.next=node
pass
def insert(self,pos, item):
'''指定位置添加元素
:param pos 从0开始
'''
if pos<=0: #认为是头插法
self.add(item)
pass
elif pos>self.length()-1: #不能包含等号
self.append(item)
else:
node=Node(item)
pre=self.__head
count=0
while count!=pos-1:
count+=1
pre=pre.next
pass #当循环结束后,per指向pos-1位置
node.next=pre.next
pre.next=node
pass
def remove(self,item):
'''删除节点'''
cur=self.__head
pre=None
while cur!=None:
if cur.elem==item:
#先判断此节点是否是头节点
if cur==self.__head: #是头节点
self.__head=cur.next
else: #不是头节点
pre.next=cur.next
break
else:
pre=cur
cur=cur.next
def search(self,item):
'''查找节点是否存在'''
cur=self.__head
while cur != None:
if cur.elem==item:
return True
else:
cur=cur.next
return False
pass
if __name__=='__main__':
ll=SingLinkList()
print(ll.is_empty())
print(ll.length())
ll.append(1)
print(ll.is_empty())
print(ll.length())
ll.append(2)
ll.append(3)
ll.append(4)
ll.append(5)
ll.append(6)
print(ll.is_empty())
print(ll.length())
ll.add(100)
ll.travel()
ll.insert(2,50)
ll.travel()
ll.insert(-1,20)
ll.travel()
ll.insert(80, 20)
ll.travel()
print(ll.search(20))
print(ll.search(30))
ll.remove(100)
ll.travel()
ll.remove(20)
ll.travel()
ll.remove(20)
ll.travel()
运行结果:
True
0
False
1
False
6
100 1 2 3 4 5 6
100 1 50 2 3 4 5 6
20 100 1 50 2 3 4 5 6
20 100 1 50 2 3 4 5 6 20
True
False
20 1 50 2 3 4 5 6 20
1 50 2 3 4 5 6 20
1 50 2 3 4 5 6
(2). 链表与顺序表的对比
- 链表失去了顺序表随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大,但对存储空间的使用要相对灵活。
链表与顺序表的各种操作复杂度如下所示:
- 注意虽然表面看起来复杂度都是 O(n),但是链表和顺序表在插入和删除时进行的是完全不同的操作。链表的主要耗时操作是遍历查找,删除和插入操作本身的复杂度是O(1)。顺序表查找很快,主要耗时的操作是拷贝覆盖。因为除了目标元素在尾部的特殊情况,顺序表进行插入和删除时需要对操作点之后的所有元素进行前后移位操作,只能通过拷贝和覆盖的方法进行。
2.单向循环链表
- 单向循环链表的相关常用操作
#coding=utf-8
class Node(object):
'''节点类'''
def __init__(self,elem):
self.elem=elem
self.next=None #一开始不知道这个节点指向谁
pass
# node=Node(100)
class SingCycleLinkList(object):
'''单向循环链表类'''
def __init__(self,node=None):
self.__head = node #一个私有的head属性指向了None
if node:
node.next=node
pass
def is_empty(self):
'''链表是否为空'''
return self.__head==None
pass
def length(self):
'''链表长度'''
if self.is_empty():
return 0
cur=self.__head #cur游标:用来移动遍历节点
count=1 #count:记录数量
while cur.next!=self.__head:
count+=1
cur=cur.next
return count
pass
def travel(self):
'''遍历整个链表'''
if self.is_empty():
return
cur=self.__head
while cur.next!=self.__head:
print(cur.elem,end=' ')
cur=cur.next
#退出循环,cur指向尾节点,但尾节点的元素未打印
print(cur.elem)
print('')
pass
def add(self,item):
'''链表头部添加元素'''
node=Node(item)
if self.is_empty():
self.__head=node
node.next=node
cur=self.__head
while cur.next!=self.__head:
cur=cur.next
pass
node.next=self.__head
self.__head=node
cur.next=node
pass
def append(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=cur.next
cur.next=node
pass
def insert(self,pos, item):
'''指定位置添加元素
:param pos 从0开始
'''
if pos<=0: #认为是头插法
self.add(item)
pass
elif pos>self.length()-1: #认为是尾插法,不能包含等号
self.append(item)
else:
node=Node(item)
pre=self.__head
count=0
while count!=pos-1:
count+=1
pre=pre.next
pass #当循环结束后,per指向pos-1位置
node.next=pre.next
pre.next=node
pass
def remove(self,item):
'''删除节点'''
if self.is_empty():
return
cur=self.__head
pre=None
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指向尾节点
self.__head=cur.next
rear.next=self.__head
else: #中间节点
pre.next=cur.next
return
else:
pre=cur
cur=cur.next
# 跳出while循环,cur指向尾结点
if cur.elem==item:
if cur==self.__head:
#说明链表只有这一个节点
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
else:
return False
pass
if __name__=='__main__':
ll=SingCycleLinkList()
print(ll.is_empty())
print(ll.length())
ll.append(1)
print(ll.is_empty())
print(ll.length())
ll.append(2)
ll.append(3)
ll.append(4)
ll.append(5)
ll.append(6)
print(ll.is_empty())
print(ll.length())
ll.add(100)
ll.travel()
ll.insert(2,50)
ll.travel()
ll.insert(-1,20)
ll.travel()
ll.insert(80, 20)
ll.travel()
print(ll.search(20))
print(ll.search(30))
ll.remove(100)
ll.travel()
ll.remove(20)
ll.travel()
ll.remove(20)
ll.travel()
运行结果:
True
0
False
1
False
6
100 1 2 3 4 5 6
100 1 50 2 3 4 5 6
20 100 1 50 2 3 4 5 6
20 100 1 50 2 3 4 5 6 20
True
False
20 1 50 2 3 4 5 6 20
1 50 2 3 4 5 6 20
1 50 2 3 4 5 6
3.双向链表
- 双向链表的相关常用操作
#coding=utf-8
class Node(object):
'''结点'''
def __init__(self,item):
self.elem=item
self.next=None
self.prev=None
class DoubleLinkList(object):
'''双链表'''
def __init__(self, node=None):
self.__head = node # 一个私有的head属性指向了None
pass
def is_empty(self):
'''链表是否为空'''
return self.__head is None
pass
def length(self):
'''链表长度'''
cur = self.__head # cur游标:用来移动遍历节点
count = 0 # count:记录数量
while cur != None:
count += 1
cur = cur.next
return count
pass
def travel(self):
'''遍历整个链表'''
cur = self.__head
while cur != None:
print(cur.elem, end=' ')
cur = cur.next
print('')
pass
def add(self, item):
'''链表头部添加元素'''
node = Node(item)
node.next = self.__head
self.__head = node
node.next.prev=node
pass
def append(self, item):
'''链表尾部添加元素'''
node = Node(item)
if self.is_empty():
self.__head = node
else:
cur = self.__head
while cur.next != None:
cur = cur.next
cur.next = node
node.prev=cur
pass
def insert(self, pos, item):
'''指定位置添加元素
:param pos 从0开始
'''
if pos <= 0: # 认为是头插法
self.add(item)
pass
elif pos > self.length() - 1: # 不能包含等号
self.append(item)
else:
node = Node(item)
cur = self.__head
count = 0
while count != pos:
count += 1
cur = cur.next
pass # 当循环结束后,per指向pos-1位置
node.next = cur
node.prev=cur.prev
cur.prev= node
node.prev.next=node
pass
def remove(self, item):
'''删除节点'''
cur = self.__head
while cur != None:
if cur.elem == item:
# 先判断此节点是否是头节点
if cur == self.__head: # 是头节点
self.__head = cur.next
if cur.next: #如果后面有就走这个if,后面没有了就不走(判断链表是否是只有一个节点)
cur.next.prev=None
else: # 不是头节点
cur.prev.next= cur.next
if cur.next: #判断是否是最后一个节点
cur.next.prev= cur.prev
break
else:
pre = cur
cur = cur.next
def search(self, item):
'''查找节点是否存在'''
cur = self.__head
while cur != None:
if cur.elem == item:
return True
else:
cur = cur.next
return False
pass
if __name__=='__main__':
ll=DoubleLinkList()
print(ll.is_empty())
print(ll.length())
ll.append(1)
print(ll.is_empty())
print(ll.length())
ll.append(2)
ll.append(3)
ll.append(4)
ll.append(5)
ll.append(6)
print(ll.is_empty())
print(ll.length())
ll.add(100)
ll.travel()
ll.insert(2, 50)
ll.travel()
ll.insert(-1, 20)
ll.travel()
ll.insert(80, 20)
ll.travel()
print(ll.search(20))
print(ll.search(30))
ll.remove(100)
ll.travel()
ll.remove(20)
ll.travel()
ll.remove(20)
ll.travel()
运行结果:
True
0
False
1
False
6
100 1 2 3 4 5 6
100 1 50 2 3 4 5 6
20 100 1 50 2 3 4 5 6
20 100 1 50 2 3 4 5 6 20
True
False
20 1 50 2 3 4 5 6 20
1 50 2 3 4 5 6 20
1 50 2 3 4 5 6