数据结构——线性结构(链表)
链表定义:链表是由一系列节点组成的元素结合。每个节点包含两个部分,数据域item和指向下一个节点的指针next。通过节点之间的相互连接,最终串联成一个链表。
一、单链表
1、节点定义
class Node: def __init__(self, item): self.item = item self.next = None # 模拟链表 a = Node(1) b = Node(2) c = Node(3) a.next = b b.next = c print(a.next.next.item) # 输出:3
2、建立链表
(1)头插法
头插法是在头结点这边插入。
(2)尾插法
不光要知道头还需要知道尾在哪。从尾节点插入。
(3)代码实现
class Node: def __init__(self, item): self.item = item # 存放数据 self.next = None # 指针,指向下一个节点 def create_linklist_head(li): """头插法创建链表""" head = Node(li[0]) # 头节点 for element in li[1:]: # 从第二个到最后一个遍历列表 node = Node(element) # 实例化为一个链表节点 node.next = head # 设置实例的next属性指向链表头节点 head = node # 将新加入链表节点设置为头节点 return head # 要遍历链表需要从头往回找 def create_linklist_tail(li): """尾插法创建链表""" head = Node(li[0]) # 创建头节点对象 tail = head # 尾节点也是头节点 for element in li[1:]: # 从第二个到最后一个遍历列表 node = Node(element) # 创建一个新链表节点 tail.next = node # 设置实例next属性指向链表尾节点 tail = node # 将新加入链表的节点设置为尾节点 return head # 返回头节点,可以从头往回找 def print_linklist(lk): """打印链表""" while lk: # 只要lk存在 print(lk.item, end=',') # 打印链表值 lk = lk.next # 到最后一个节点的时候,lk.next属性为空退出循环 lk = create_linklist_head([1, 2, 3]) print(lk) print_linklist(lk) """ <__main__.Node object at 0x10402de48> 3,2,1, """ lk2 = create_linklist_tail([1, 3, 6, 8, 9]) print_linklist(lk2) """ 3,2,1,1,3,6,8,9, """
3、链表的遍历
4、链表节点的插入和删除(视频缺,需要补)
二、双链表
双链表的每个节点有两个指针:一个指向后一个节点,另一个指向前一个节点。
1、节点定义
class Node(object): def __init__(self, item): self.item = item # 数据 self.next = None # 指针,指向后一个节点 self.prior = None # 指针,指向前一个节点
2、双链表节点插入
#插入 p.next = curNode.next curNode.next.prior = p p.prior = curNode curNode.next = p
代码过程图示如下:
(1)p.next = curNode.next 让p.next指针指向curNode下一个节点
(2)curNode.next.prior = p 让curNode下一个节点的prior指针指向p
(3)p.prior = curNode 让p的prior指针指向curNode
(4)curNode.next = p 让curNode的next指针指向p
3、双链表节点的删除
#删除 p = curNode.next curNode.next = p.next p.next.prior = curNode del p
代码过程图示如下:
(1)p = curNode.next 指定要删除的节点是curNode的next指针指向的节点
(2)curNode.next = p.next 修改curNode的next指针指向要删除节点的next指针指向的节点
(3)p.next.prior = curNode 修改p的next指针指向的节点的prior指针,将指针指向curNode
(4)del p 删除p
三、链表总结
1、顺序表(列表)与 链表复杂度对比分析
按元素值查找时:都是挨个查看,时间复杂度都为O(n)
按下标查找时:顺序表更快,直接插入到对位位置。链表则需要从头开始数。链表时间复杂度是O(n),顺序表时间复杂度是O(1)。
在某元素后插入:这种情况顺序表是O(n),插入后,后面的元素都需要往后挪。链表则是O(1)。
删除某元素:这种情况顺序表是O(n),删除后,后面的元素都需要往前挪。链表则是O(1)。
2、链表和顺序表对比总结
链表在插入和删除操作上明显快于顺序表。
链表的内存可以更灵活的分配。java等的数组一开始申请的空间如果满了是没有办法解决的,python的列表在一开始申请的空间不足时,也是通过重新申请新的空间,将原来内存空间的内容拷贝进去。
可以尝试利用链表重新实现栈和队列,使用栈实现队列就不用考虑队满的问题,也不用设计为环形。
链表这种链式存储的数据结构对树和图的结构有很大的启发性。