- 链表的定义
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
- 链表类型
- 单链表
- 双链表
- 循环链表
- 双向循环链表
- 时间复杂度
- 单链表
(1)、插入操作只需要改变相邻节点的指针就可以,例如将a插入n位置只需将n-1位置的next指针指向a,将a的next指针指向n+1。整个操作的时间复杂度为O(1)
(2)、删除操作同理只需改变,相邻节点的指针
(3)、查询操作最坏时间复杂度为O(n),与数组的连续存储空间,只需要首地址和下标就能计算出对应的内存地址不同,链表需要根据指针一个节点一个节点地依次遍历之后才能知道想要查找的数据的相应节点的内存地址。时间复杂度为O(n)
2、双链表
相对与单链表,双链表多了个前驱指针。由此可知双链表比单链表占用更多的内存空间
(1)、插入操作与单链表类似,只不过单链表插入时。需要遍历查找到该节点和插入节点的前驱节点。虽然插入和删除操作O(1)但查找该节点的操作为O(n),双链表因为有前驱指针所以不需要重新遍历就可以找到前驱节点
(2)、删除操作同理,虽然同为O(1)的时间复杂度,但是理论上双链表会比单链表快一倍。
3、循环链表
与单链表类似,只不过循环链表从链尾到链头比较方便。适合处理一些循环结构的数据。例如’约瑟夫环’
- 双向循环链表
就是双向链表加循环链表,如果上面的理解了,这个就比较好理解
- 深入理解
- 指针
在C语言中称为指针,python和java中称为引用。其功能都是存储期所指向的对象的内存地址
- 哨兵简化链表实现难度
针对链表的插入、删除操作,需要对插入第一个结点和删除最后一个节点的情况进行特殊处理。
- python代码实现
定义链表,并实现单链表反转。以后会添加其他相关代码
class Node(object):
def __init__(self,data,next=None):
self.data = data
self.next = next
class MyLink(object):
def __init__(self,data):
# 尾指针指向最后一个节点,不包括头结点
self.headnode = Node(None)
self.rear = None
#定义链表
for d in data:
NewNode = Node(d)
if self.rear is None:
self.rear = NewNode
self.headnode.next = NewNode
else:
self.rear.next = NewNode
self.rear = NewNode
#打印链表
def print_all(self):
next = self.headnode.next
while next is not None:
print(next.data,end=' ')
next = next.next
print()
# 头插法实现反转
def reverse(self):
# 将链表的头结点之后的元素分开来
next = self.headnode.next
self.headnode.next = None
while next is not None:
NewNode = next
next = next.next
NewNode.next = self.headnode.next
self.headnode.next = NewNode
# 递归实现
def reverse2(self):
next = self.headnode.next
self.print_next(next)
print()
def print_next(self,next):
if next is None:
return
self.print_next(next.next)
print(next.data,end=' ')
def get_last_k_node(self,k):
advance_node = self.headnode.next
behind_node = self.headnode.next
while k>0:
if advance_node is None:
return None
advance_node = advance_node.next
k -= 1
while advance_node is not None:
advance_node = advance_node.next
behind_node = behind_node.next
return behind_node.data
def main():
data = [1,2,3,4,5]
queue = MyLink(data)
queue.print_all()
print(queue.get_last_k_node(1))
queue.reverse2()
queue.reverse()
queue.print_all()
if __name__ == '__main__':
main()
链表中环检测
class Node():
def __init__(self,data,next=None):
self.data = data
self.next = next
class MyLink(object):
def __init__(self,data):
self.headnode = Node(None)
self.rear = None
for d in data:
NewNode = Node(d)
if self.rear is None:
self.rear = NewNode
self.headnode.next = NewNode
else:
self.rear.next = NewNode
self.rear = NewNode
#self.rear.next = self.headnode
def cry(self):
slow , fast = self.headnode ,self.headnode
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
if __name__ == "__main__":
data = [1,2,3,4,56,7]
ml = MyLink(data)
print(ml.cry())