目录
4.1链表
4.1.1单链表
# 结点
class SingleNode:
def __init__(self,item):
# 存放数据元素
self.item=item
# 存放下一个结点标识
self.next=None
# 单项链表的实现
class SimgleLinkList:
# 初始化链表
def __init__(self):
self._head=None
# 向前插入值
def add(self,item):
node=SingleNode(item)
node.next=self._head
self._head=node
# 指定链表位置插入元素的值
def insert(self,index,item):
if index<=0:
self.add(item)
elif index>=self.length():
self.append(item)
else:
node=SingleNode(item)
cur=self._head
count=0
while count<index-1:
cur=cur.next
count+=1
node.next=cur.next
cur.next=node
# 向链表元素之后插入值
def append(self,item):
node=SingleNode(item)
if self._head==None:
self._head=node
return None
cur=self._head
while True: # 如果当前结点的下一个结点为None
if cur.next==None:
cur.next=node
break
else:
cur=cur.next
# 删除最后一个元素,并返回删除的元素
def pop(self):
if self.isempty():
return -1
cur=self._head
count=0
pop_value=None
while True:
if count==self.length()-2:
pop_value=cur.next.item
cur.next=None
break
count+=1
cur=cur.next
return pop_value
# 根据元素本身删除链表中的元素,如果元素不存在,我们返回-1
def remove(self,elem):
pow=self.search(elem)
# 如果没有找到该元素,我们就返回-1
if pow==-1:
return -1
cur=self._head # 找到链表的头的位置
count=0
pre=None
while True:
if pow==self.length()-1: # 说明删除的是最后一个元素
self.pop()
break
elif pow==0: # 如果删除的元素是第一个元素
self._head=cur.next # 将当前元素的下一个元素作为_head,删除了当前元素
break
else: # 如果不是最后一个元素,那么被删除的元素就有下一个元素
pre=cur # 当前结点作为前一个结点
cur=cur.next # 当前结点后移一位
count+=1
if pow==count: # 如果说指定位置等于要删除的位置
pre.next=cur.next # 将当前结点指向当前结点的前一个位置
break
# 元素的替换,指定位置替换成指定元素,如果替换的位置超出范围,返回-1
def replace(self,index,elem):
if index>=self.length():
return -1
cur=self._head
count=0
while True:
if count==index:
cur.item=elem # 将我们的当前元素替换成该元素
break
cur=cur.next
count+=1
return 1
# 查找指定元素的位置
def search(self,elem):
cur=self._head
count=0
while True:
if count>=self.length():
return -1
elif cur.item==elem:
return count
else:
count+=1
cur=cur.next
return count
# 遍历链表
def travel(self):
cur=self._head
while cur!=None:
print(cur.item)
cur=cur.next
# 获取链表的长度
def length(self):
count=0
cur=self._head
while True:
if cur!=None:
count+=1
cur=cur.next
else:
break
return count
# 判断链表是否为空
def isempty(self):
if self._head==None:
return True
return False
测试代码
single=SimgleLinkList()
single.append(1)
single.append(2)
single.append(3)
single.append(4)
single.remove(4)
print('--------',single.replace(4,10))
single.travel()
4.1.2单项循环链表
单项循环链表的最后一个节点的next不是指向None,而是指向头节点
class Node:
def __init__(self, item):
self.item = item
self.next = None
# %%
class SingleCycLinkedList:
def __init__(self):
self._head = None
# 判断节点是否为空
def is_empty(self):
return self._head == None
# 头部添加元素
def add(self, item):
node = Node(item)
if self.is_empty(): # 如果链表为空
self._head = node
node.next = self._head
else:
# 目标:node的next指向head,链表的最后节点的next指向node
node.next = self._head
cur = self._head
while True:
# 如果当前结点的下一个结点指向的是头结点,
# 说明当前结点已经是该圈的最后一个节点了
if cur.next == self._head:
break
cur = cur.next
cur.next = node
self._head = node # _head只是一个指向头结点的索引,头改变了,_head指向也应该发生改变
# 尾部添加元素
def append(self, item):
node = Node(item)
if self.is_empty():
self._head = node
node.next = self._head
node.next = self._head
cur = self._head
while True:
if cur.next == self._head:
cur.next = node
break
cur = cur.next
# 遍历
def travel(self):
if self.is_empty():
return None
cur = self._head
while True:
print(cur.item) # 打印当前结点的值
if cur.next == self._head: # 如果当前结点没有next,那么直接退出循环
break
cur = cur.next # 如果当前结点有下一个值,我们就将当前结点指向向下一个结点
def insert(self, index, item):
if self.is_empty():
self._head = node
node.next = self._head
elif index <= 0:
self.add(item)
elif index >= self.length():
self.append(item)
else:
cur = self._head
count = 0
while True:
if index >= count:
break
count += 1
def length(self):
count = 0
if self.is_empty():
return count
count += 1
cur = self._head
while True:
if cur.next == self._head:
break
count += 1
cur = cur.next
return count
# %%
scll = SingleCycLinkedList()
for i in range(4):
scll.append(i)
print('---------------')
scll.insert(4, 10)
scll.travel()
4.1.3双向链表
既有指向上一个节点的指针也有指向下一个节点的指针.
class Node(object):
"""双向链表节点"""
def __init__(self, item):
self.item = item
self.next = None
self.prev = None
class DLinkList(object):
"""双向链表"""
def __init__(self):
self._head = None
def is_empty(self):
"""判断链表是否为空"""
return self._head == None
def length(self):
"""返回链表的长度"""
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.item,
cur = cur.next
print ""
def add(self, item):
"""头部插入元素"""
node = Node(item)
if self.is_empty():
# 如果是空链表,将_head指向node
self._head = node
else:
# 将node的next指向_head的头节点
node.next = self._head
# 将_head的头节点的prev指向node
self._head.prev = node
# 将_head 指向node
self._head = node
def append(self, item):
"""尾部插入元素"""
node = Node(item)
if self.is_empty():
# 如果是空链表,将_head指向node
self._head = node
else:
# 移动到链表尾部
cur = self._head
while cur.next != None:
cur = cur.next
# 将尾节点cur的next指向node
cur.next = node
# 将node的prev指向cur
node.prev = cur
def search(self, item):
"""查找元素是否存在"""
cur = self._head
while cur != None:
if cur.item == item:
return True
cur = cur.next
return False
def insert(self, pos, item):
"""在指定位置添加节点"""
if pos <= 0:
self.add(item)
elif pos > (self.length() - 1):
self.append(item)
else:
node = Node(item)
cur = self._head
count = 0
# 移动到指定位置的前一个位置
while count < (pos - 1):
count += 1
cur = cur.next
# 将node的prev指向cur
node.prev = cur
# 将node的next指向cur的下一个节点
node.next = cur.next
# 将cur的下一个节点的prev指向node
cur.next.prev = node
# 将cur的next指向node
cur.next = node
def remove(self, item):
"""删除元素"""
if self.is_empty():
return
else:
cur = self._head
if cur.item == item:
# 如果首节点的元素即是要删除的元素
if cur.next == None:
# 如果链表只有这一个节点
self._head = None
else:
# 将第二个节点的prev设置为None
cur.next.prev = None
# 将_head指向第二个节点
self._head = cur.next
return
while cur != None:
if cur.item == item:
# 将cur的前一个节点的next指向cur的后一个节点
cur.prev.next = cur.next
# 将cur的后一个节点的prev指向cur的前一个节点
cur.next.prev = cur.prev
break
cur = cur.next
测试代码:
if __name__ == "__main__":
ll = DLinkList()
ll.add(1)
ll.add(2)
ll.append(3)
ll.insert(2, 4)
ll.insert(4, 5)
ll.insert(0, 6)
print "length:",ll.length()
ll.travel()
print ll.search(3)
print ll.search(4)
ll.remove(1)
print "length:",ll.length()
ll.travel()
面试题:如何判断带环链表?
我们声明两个指针,一个指针变化的速度快在前面跑,另一个指针变化的慢在后面缀,在运行的过程中,如果返现突然两个指针相遇了,那么说明该链表中一定存在环,否则不存在,如果不存在遍历完整个链表总会出来某个节点的next指针指向None.