链表(Linked)

链表是一种物理存储单元上非连续、非顺序的存储单元,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
link1.png

链表的特点

  • 不要求逻辑上相连的两个元素物理上也相连
  • 读取查询操作比数组难,链表结构无法通过指定索引位置来立即访问
  • 插入、删除操作比数组简单,不需要移动元素,只需要修改“链”
  • 在每一次插入和删除过程中,链表结构会调整大小,不需要额外的内存代价,不需要复制数据项

单链表(single linked)

链表结构的基本单位表示是节点,单链表的节点包括了:

  1. 一个数据项
  2. 到结构中下一个节点的一个链接

在单链表结构中,容易获取一个项的后继项,但不容易获取一个项的前驱项,用户通过沿着一个外部的头链接(head link)来访问第一个项,然后通过第一个项产生的、串联起来的、单个的链条,来访问其他项。

  1. # 用python定义一个简单的单链表节点类
  2. class Node(object):
  3. def __init__(self, data, next=None):
  4. self.data = data
  5. self.next = next
  6. # 用Node类创建一个含有5个节点的单链表结构
  7. head = None # head:指向链表头部的指针
  8. for i in range(5):
  9. head = Node(i, head)
  10. # Print the contents of the structure
  11. while head != None:
  12. print(head.data)
  13. head = head.next
  14. # 注:(1)指针head生成了链表结构,最近插入的项总是位于结构的开始处
  15. # (2)Print数据时,按照插入顺序相反出现
  16. # (3)Print数据时,head指针重新设置成下一个节点,直到变为None,
  17. # 所以这个过程后,节点从链表结构中删除,不可再用
  18. # 单链表结构上的操作
  19. # Create a single linked
  20. head = None
  21. for i in range(5):
  22. head = Node(i, head)
  23. # (1)遍历(traversal) O(n)
  24. print('(1)遍历(traversal)')
  25. # 访问每一个节点而不删除它们,使用一个临时指针变量prob
  26. prob = head
  27. while prob != None:
  28. print(prob.data)
  29. prob = prob.next
  30. # (2)搜索
  31. print('(2)搜索')
  32. targetItem = 9
  33. prob = head
  34. while prob != None and targetItem != prob.data:
  35. prob = prob.next
  36. if prob != None:
  37. print("targetItem {} has been found".format(prob.data))
  38. else:
  39. print("targetItem {} is not in the linked".format(targetItem))
  40. # 访问链表中第i项 O(n)
  41. # Assumes 0 <= index < n
  42. def read_data(head, index):
  43. prob = head
  44. while index > 0:
  45. prob = prob.next
  46. index -= 1
  47. return prob.data
  48. print(read_data(head, 0))
  49. # (3)替换
  50. print('(3)替换')
  51. # 替换一个给定项 O(n)
  52. targetItem = 0
  53. newItem = 10
  54. while head != None:
  55. head = head.next
  56. for i in range(5):
  57. head = Node(i, head)
  58. def print_linked(head):
  59. prob = head
  60. while prob != None:
  61. print(prob.data)
  62. prob = prob.next
  63. print_linked(head)
  64. # (4)插入
  65. print('在开始出插入') # O(1)
  66. head = Node(newItem, head)
  67. print_linked(head)
  68. print('在末尾插入') # O(n)
  69. newNode = Node(34)
  70. if head is None:
  71. head = newNode
  72. else:
  73. prob = head
  74. while prob.next != None:
  75. prob = prob.next
  76. prob.next = newNode
  77. print_linked(head)
  78. print('在任何位置插入')
  79. idx = 2
  80. newItem = 'b'
  81. if head is None or idx <= 0:
  82. head = Node(newItem, head)
  83. else:
  84. prob = head
  85. while idx>1 and prob.next != None:
  86. prob = prob.next
  87. idx -= 1
  88. prob.next = Node(newItem, prob.next)
  89. print_linked(head)
  90. #(5)删除
  91. print('从开始处删除') # O(1)
  92. removeItem = head.data
  93. head = head.next
  94. print_linked(head)
  95. head.next.data
  96. prob = head
  97. while prob != None and targetItem != prob.data:
  98. prob = prob.next
  99. if prob != None:
  100. prob.data = newItem
  101. print('Success')
  102. else:
  103. print('False')
  104. # 替换第i项 O(n)
  105. index = 1
  106. prob = head
  107. while index > 0:
  108. prob = prob.next
  109. index -= 1
  110. prob.data = newItem

双链表结构(doubly linked structure)

双链表结构的节点包括了:

  1. 一个数据项
  2. 到结构中下一个节点的一个链接
  3. 到结构中上一个节点的一个链接

双链表节点包括了两个方向的节点,所以用户很容易移动到一个节点的后继项和前驱项

  1. # 双链表节点的python实现
  2. class TwoWayNode(Node):
  3. def __init__(self, data, previous=None, next=None):
  4. Node.__init__(self, data, next)
  5. self.previous = previous
  6. # Create a double linked structure with one node
  7. head = TwoWayNode(0)
  8. tail = head # tail:指向尾部的指针
  9. # Add four nodes to the end of the double linked structure
  10. for i in range(1,5):
  11. tail = TwoWayNode(i, tail) # previous=tail
  12. # Print the contents of the double linked structure in reverse order
  13. prob = tail
  14. while prob != None:
  15. print(prob.data)
  16. prob = prob.previous