链表

链表是一种在存储单元上非连续、非顺序的存储结构。数据元素的逻辑顺序是通过链表中的指针链接次序实现。链表是由一系列的结点组成,结点可以在运行时动态生成。每个结点包含两部分:数据域与指针域。数据域存储数据元素,指针域存储下一结点的指针。

资料来源:https://zhuanlan.zhihu.com/p/60057180

单向链表

它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。
image.png
由图可知:

  • head 保存首地址,item 存储数据,next 指向下一结点地址。

链表的优缺点:

  • 链表失去了序列的随机读取优点,同时链表增加了指针域,空间开销也较大。
  • 但它对存储空间的使用要相对灵活。
  • 优势示例:
    • 列如:有一堆数据[1,2,3,5,6,7],要在3和5之间插入4, 如果用数组,需要将5之后的数据都往后退一位,然后再插入4,这样非常麻烦,但是如果用链表,我就直接在3和5之间插入4就行。


定义节点

结点的数据结构为数据元素(item)与 指针(next)

  1. class Node(object):
  2. """单链表的结点"""
  3. def __init__(self, item):
  4. # item存放数据元素
  5. self.item = item
  6. # next是下一个节点的标识
  7. self.next = None

定义链表

链表需要具有首地址指针head。

  1. class SingleLinkList(object):
  2. """单链表"""
  3. def __init__(self):
  4. self._head = None

示例:创建链表

  1. class Node(object):
  2. """单链表的结点"""
  3. def __init__(self, item):
  4. # item存放数据元素
  5. self.item = item
  6. # next是下一个节点的标识
  7. self.next = None
  8. class SingleLinkList(object):
  9. """单链表"""
  10. def __init__(self):
  11. self._head = None
  12. if __name__ == '__main__':
  13. # 创建链表
  14. link_list = SingleLinkList()
  15. # 创建结点
  16. node1 = Node(1)
  17. node2 = Node(2)
  18. # 将结点添加到链表
  19. link_list._head = node1
  20. # 将第一个结点的next指针指向下一结点
  21. node1.next = node2
  22. # 访问链表
  23. print(link_list._head.item) # 访问第一个结点数据 输出:1
  24. print(link_list._head.next.item) # 访问第二个结点数据 输出:2

在链表中添加操作方法(增删改查)

主要实现功能如下:

  • is_empty()链表是否为空
  • length()链表长度
  • items()获取链表数据迭代器
  • add(item)链表头部添加元素
  • addend(item) 链表尾部添加元素
  • insert(pos,item) 指定位置添加元素
  • remove(item) 删除节点
  • find(item) 查找节点是否存在

代码如下:

  1. class Node(object):
  2. """单链表的结点"""
  3. def __init__(self, item):
  4. # item存放数据元素
  5. self.item = item
  6. # next是下一个节点的标识
  7. self.next = None
  8. class SingleLinkList(object):
  9. """单链表"""
  10. def __init__(self):
  11. self.head = None
  12. def is_empty(self):
  13. """判断链表是否为空"""
  14. return self.head is None
  15. def length(self):
  16. """链表长度"""
  17. # 初始指针指向head
  18. cur = self.head
  19. count = 0
  20. # 指针指向None 表示到达尾部
  21. while cur is not None:
  22. count += 1
  23. # 指针下移
  24. cur = cur.next
  25. return count
  26. def items(self):
  27. """遍历链表"""
  28. # 获取head指针
  29. cur = self.head
  30. # 循环遍历
  31. while cur is not None:
  32. # 返回生成器
  33. yield cur.item
  34. # 指针下移
  35. cur = cur.next
  36. def add(self, item):
  37. """向链表头部添加元素"""
  38. node = Node(item)
  39. # 新结点指针指向原头部结点
  40. node.next = self.head
  41. # 头部结点指针修改为新结点
  42. self.head = node
  43. def append(self, item):
  44. """尾部添加元素"""
  45. node = Node(item)
  46. # 先判断是否为空链表
  47. if self.is_empty():
  48. # 空链表,head 指向新结点
  49. self.head = node
  50. else:
  51. # 不是空链表,则找到尾部,将尾部next结点指向新结点
  52. cur = self.head
  53. while cur.next is not None:
  54. cur = cur.next
  55. cur.next = node
  56. def insert(self, index, item):
  57. """指定位置插入元素"""
  58. # 指定位置在第一个元素之前,在头部插入
  59. if index <= 0:
  60. self.add(item)
  61. # 指定位置超过尾部,在尾部插入
  62. elif index > (self.length() - 1):
  63. self.append(item)
  64. else:
  65. # 创建元素结点
  66. node = Node(item)
  67. cur = self.head
  68. # 循环到需要插入的位置
  69. for i in range(index - 1):
  70. cur = cur.next
  71. node.next = cur.next
  72. cur.next = node
  73. def remove(self, item):
  74. """删除节点"""
  75. cur = self.head
  76. pre = None
  77. while cur is not None:
  78. # 找到指定元素
  79. if cur.item == item:
  80. # 如果第一个就是删除的节点
  81. if not pre:
  82. # 将头指针指向头节点的后一个节点
  83. self.head = cur.next
  84. else:
  85. # 将删除位置前一个节点的next指向删除位置的后一个节点
  86. pre.next = cur.next
  87. return True
  88. else:
  89. # 继续按链表后移节点
  90. pre = cur
  91. cur = cur.next
  92. def find(self, item):
  93. """查找元素是否存在"""
  94. return item in self.items()
  95. if __name__ == '__main__':
  96. link_list = SingleLinkList()
  97. # 向链表尾部添加数据
  98. for i in range(5):
  99. link_list.append(i)
  100. # 向头部添加数据
  101. link_list.add(6)
  102. # 遍历链表数据
  103. for i in link_list.items():
  104. print(i, end='\t')
  105. # 链表数据插入数据
  106. link_list.insert(3, 9)
  107. print('\n', list(link_list.items()))
  108. # 删除链表数据
  109. link_list.remove(0)
  110. # 查找链表数据
  111. print(link_list.find(4))

输出结果:

  1. 6 0 1 2 3 4
  2. [6, 0, 1, 9, 2, 3, 4]
  3. True

循环链表

image.png

单向循环链表为单向链表的变种,链表的最后一个next指向链表头,新增一个循环。

循环链表定义

  1. class Node(object):
  2. """单链表的结点"""
  3. def __init__(self, item):
  4. # item存放数据元素
  5. self.item = item
  6. # next是下一个节点的标识
  7. self.next = None
  8. class SingleCycleLinkList(object):
  9. """循环链表"""
  10. def __init__(self):
  11. self.head = None
  12. def is_empty(self):
  13. """判断链表是否为空"""
  14. return self.head is None
  15. def length(self):
  16. """链表长度"""
  17. # 链表为空
  18. if self.is_empty():
  19. return 0
  20. # 链表不为空
  21. count = 1
  22. cur = self.head
  23. while cur.next != self.head:
  24. count += 1
  25. # 指针下移
  26. cur = cur.next
  27. return count
  28. def items(self):
  29. """ 遍历链表 """
  30. # 链表为空
  31. if self.is_empty():
  32. return
  33. # 链表不为空
  34. cur = self.head
  35. while cur.next != self.head:
  36. yield cur.item
  37. cur = cur.next
  38. yield cur.item
  39. def add(self, item):
  40. """ 头部添加结点"""
  41. node = Node(item)
  42. if self.is_empty(): # 为空
  43. self.head = node
  44. node.next = self.head
  45. else:
  46. # 添加结点指向head
  47. node.next = self.head
  48. cur = self.head
  49. # 移动结点,将末尾的结点指向node
  50. while cur.next != self.head:
  51. cur = cur.next
  52. cur.next = node
  53. # 修改 head 指向新结点
  54. self.head = node
  55. def append(self, item):
  56. """尾部添加结点"""
  57. node = Node(item)
  58. if self.is_empty(): # 为空
  59. self.head = node
  60. node.next = self.head
  61. else:
  62. # 寻找尾部
  63. cur = self.head
  64. while cur.next != self.head:
  65. cur = cur.next
  66. # 尾部指针指向新结点
  67. cur.next = node
  68. # 新结点指针指向head
  69. node.next = self.head
  70. def insert(self, index, item):
  71. """ 指定位置添加结点"""
  72. if index <= 0: # 指定位置小于等于0,头部添加
  73. self.add(item)
  74. # 指定位置大于链表长度,尾部添加
  75. elif index > self.length() - 1:
  76. self.append(item)
  77. else:
  78. node = Node(item)
  79. cur = self.head
  80. # 移动到添加结点位置
  81. for i in range(index - 1):
  82. cur = cur.next
  83. # 新结点指针指向旧结点
  84. node.next = cur.next
  85. # 旧结点指针 指向 新结点
  86. cur.next = node
  87. def remove(self, item):
  88. """ 删除一个结点 """
  89. if self.is_empty():
  90. return
  91. cur = self.head
  92. pre = Node
  93. # 第一个元素为需要删除的元素
  94. if cur.item == item:
  95. # 链表不止一个元素
  96. if cur.next != self.head:
  97. while cur.next != self.head:
  98. cur = cur.next
  99. # 尾结点指向 头部结点的下一结点
  100. cur.next = self.head.next
  101. # 调整头部结点
  102. self.head = self.head.next
  103. else:
  104. # 只有一个元素
  105. self.head = None
  106. else:
  107. # 不是第一个元素
  108. pre = self.head
  109. while cur.next != self.head:
  110. if cur.item == item:
  111. # 删除
  112. pre.next = cur.next
  113. return True
  114. else:
  115. pre = cur # 记录前一个指针
  116. cur = cur.next # 调整指针位置
  117. # 当删除元素在末尾
  118. if cur.item == item:
  119. pre.next = self.head
  120. return True
  121. def find(self, item):
  122. """ 查找元素是否存在"""
  123. return item in self.items()
  124. if __name__ == '__main__':
  125. link_list = SingleCycleLinkList()
  126. print(link_list.is_empty())
  127. # 头部添加元素
  128. for i in range(5):
  129. link_list.add(i)
  130. print(list(link_list.items()))
  131. # 尾部添加元素
  132. for i in range(6):
  133. link_list.append(i)
  134. print(list(link_list.items()))
  135. # 添加元素
  136. link_list.insert(3, 45)
  137. print(list(link_list.items()))
  138. # 删除元素
  139. link_list.remove(5)
  140. print(list(link_list.items()))
  141. # 元素是否存在
  142. print(4 in link_list.items())