当前位置:   article > 正文

常见数据结构线性表(数组和链表)python实现_python线性表输出列表代码

python线性表输出列表代码

数组

数据在内存中顺序存储,可以通过下标索引。

特点:支持随机访问,索引元素效率高,插入元素和删除元素效率低。

数组存放空间连续,插入元素时需要将插入位置及后面的元素一次往后移动一位,然后将元素插入到空出的插入位置。

python中的list是一个动态数组,支持动态扩容(2^n),list中封装了数组常用的方法:

  1. >>> list = [3, 5, 7]
  2. >>> list.append(9) # 往数组尾部添加元素
  3. >>> list
  4. [3, 5, 7, 9]
  5. >>> list.insert(2,5) # 在指定位置插入元素
  6. >>> list
  7. [3, 5, 5, 7, 9]
  8. >>> list.pop() # 取数组最后一个元素,会从数组中删除该元素
  9. 9
  10. >>> list
  11. [3, 5, 5, 7]
  12. >>> list.remove(5) # 删除数组中的指定元素,有多个时只删除第一个
  13. >>> list
  14. [3, 5, 7]
  15. >>> list.index(5) # 查找元素在列表中的位置
  16. 1
  17. >>> list.reverse() # 列表反转
  18. >>> list
  19. [7, 5, 3]

在python中通过id()函数来输出列表元素的第地址时,可以看到id的值并不是连续的,这是为什么呢?

  1. >>> arr = ['a','b','c']
  2. >>> for char in arr:
  3. print(id(char))
  4. 2204167613216
  5. 2204167611536
  6. 2204167474288

因为python的list存的是元素对象的引用而不是元素本身,从下面代码中可以看出来,所以输出的id值是元素对象的引用值,在底层的c语言中是使用数组来实现的。

  1. >>> a = 1
  2. >>> id(a)
  3. 1598830848
  4. >>> b = [a]
  5. >>> id(b)
  6. 9390640
  7. >>> id(b[0])
  8. 1598830848

链表

链表数据在内存中的存储不连续,链表有一系列的节点通过指针依次连接起来,每个节点包含数据域和指针域,数据域存储数据,指针域存储下一个节点的指针。

单向链表

单向链表也叫单链表,是链表中最简单的形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。

image.png

因为链表中的数据不是顺序存储的,不能随机访问,因此链表的查询效率低,但是链表在任意位置插入和删除节点时不用移动节点位置,因此插入和删除效率高。

链表实现

通常有以下步骤:

  1. 定义节点
  2. 定义链表
  3. 使用链表
    1. class Node(object):
    2. '''1.节点定义'''
    3. def __init__(self,data):
    4. # 数据域
    5. self.data = data
    6. # 指针域,创建时为None
    7. self.next = None
    8. class SingleList(object):
    9. '''2.链表定义'''
    10. def __init__(self):
    11. # 链表头
    12. self.head = None
    13. if __name__ == '__main__':
    14. #3.链表使用
    15. # 创建链表
    16. singlelist = SingleList()
    17. # 创建节点
    18. node1 = Node(3)
    19. # 将链表头指向节点
    20. singlelist.head = node1
    21. # 创建节点往链表上添加
    22. node2 = Node(5)
    23. node1.next = node2
    24. node3 = Node(7)
    25. node2.next = node3
    26. # 创建临时变量指向头节点
    27. temp = singlelist.head
    28. # 取头节点的数据
    29. print(temp.data)
    30. # 取下一个节点的数据
    31. temp = temp.next
    32. print(temp.data)

    输出结果:

3

5

上面定义并使用了一个单项链表,但是链表的使用很不方便,获取元素添加和获取需要定位到节点,长度也没法知道,所以需要定义一些常用的方法,方便链表的使用。

链表中的常用方法:

  • is_empty() 链表是否为空
  • length() 链表长度
  • items() 获取链表数据迭代器
  • add(item) 链表头部添加元素
  • append(item) 链表尾部添加元素
  • insert(pos, item) 指定位置添加元素
  • remove(item) 删除节点
  • find(item) 查找节点是否存在
  1. class Node(object):
  2. '''节点定义'''
  3. def __init__(self,data):
  4. # 数据域
  5. self.data = data
  6. # 指针域,创建时为None
  7. self.next = None
  8. class SingleList(object):
  9. '''链表定义'''
  10. def __init__(self):
  11. # 链表头
  12. self.head = None
  13. def is_empty(self):
  14. '''链表判空'''
  15. return self.head is None
  16. def length(self):
  17. '''链表长度'''
  18. # 获取初始的头指针
  19. cur = self.head
  20. count = 0
  21. while cur is not None:
  22. count += 1
  23. # 指针后移1位
  24. cur = cur.next
  25. return count
  26. def datas(self):
  27. '''链表遍历'''
  28. cur = self.head
  29. while cur is not None:
  30. # 返回生成器
  31. yield cur.data
  32. # 指针后移1位
  33. cur = cur.next
  34. def add(self,data):
  35. '''在头部插入节点'''
  36. # 创建新节点
  37. node = Node(data)
  38. # 新节点指向原头节点
  39. node.next = self.head
  40. # 头节点指向新节点
  41. self.head = node
  42. def append(self,data):
  43. '''向尾部插入节点'''
  44. node = Node(data)
  45. if self.is_empty():
  46. # 空链表则直接将head指向node
  47. self.head = node
  48. else:
  49. cur = self.head
  50. while cur.next is not None:
  51. # 将指针移到最后一个节点
  52. cur = cur.next
  53. # 将最后一个节点的指针指向node
  54. cur.next = node
  55. def insert(self,index,data):
  56. '''任意位置插入节点'''
  57. if index <= 0:
  58. # 在头部插入
  59. self.add(data)
  60. elif index >= self.length():
  61. # 在尾部插入
  62. self.append(data)
  63. else:
  64. cur = self.head
  65. for i in range(index - 1):
  66. cur = cur.next
  67. # 创建新节点
  68. node = Node(data)
  69. # 将新节点指向就节点
  70. node.next = cur.next
  71. # 将旧节点前一个节点指向新节点
  72. cur.next = node
  73. def remove(self, item):
  74. """ 删除一个结点 """
  75. if self.is_empty():
  76. return
  77. cur = self.head
  78. pre = None
  79. # 第一个元素为需要删除的元素
  80. if cur.data == item:
  81. if cur.next != None:
  82. cur.next = self.head.next
  83. # 调整头部结点
  84. self.head = self.head.next
  85. else:
  86. # 只有一个元素
  87. self.head = None
  88. else:
  89. # 不是第一个元素
  90. pre = self.head
  91. while cur.next != self.head:
  92. if cur.data == item:
  93. # 删除
  94. pre.next = cur.next
  95. return True
  96. else:
  97. pre = cur # 记录前一个指针
  98. cur = cur.next # 调整指针位置
  99. # 当删除元素在末尾
  100. if cur.data == item:
  101. pre.next = self.head
  102. return True
  103. def find(self, data):
  104. """ 查找元素是否存在"""
  105. return data in self.datas()
  106. def printlist(self):
  107. '''打印链表元素'''
  108. print('当前链表:')
  109. for i in self.datas():
  110. print(i)
  111. if __name__ == '__main__':
  112. # 创建链表
  113. singlelist = SingleList()
  114. #添加节点
  115. singlelist.add(3)
  116. singlelist.append(5)
  117. singlelist.append(7)
  118. # 链表长度
  119. length = singlelist.length()
  120. print('链表长度:',length)
  121. singlelist.printlist()
  122. # 删除元素
  123. singlelist.remove(5)
  124. print('--删除元素--')
  125. singlelist.printlist()
  126. # 任意位置插入元素
  127. singlelist.insert(2,666)
  128. print('--任意位置插入元素--')
  129. singlelist.printlist()

双向链表

双向链表与与单向链表的区别在于,双向链表的节点包含了两个指针域,如下图,prev指针域指向前一个节点,next指向后一个节点,head指向头节点,第一个节点的prev指针为None,最后一个节点的next为空。

image.png为了方便操作双向链表,也会在链表中定义一些常用的方法。实例如下:

  1. class Node(object):
  2. '''双链表的节点'''
  3. def __init__(self,data):
  4. self.data = data
  5. self.prev = None
  6. self.next = None
  7. class DoubleLinkedList(object):
  8. '''双向链表'''
  9. def __init__(self):
  10. self.head = None
  11. self.tail = None
  12. def is_empty(self):
  13. return self.head is None
  14. def length(self):
  15. cur = self.head
  16. count = 0
  17. while cur is not None:
  18. cur = cur.next
  19. count += 1
  20. return count
  21. def items(self):
  22. '''顺序遍历'''
  23. cur = self.head
  24. while cur is not None:
  25. yield cur.data
  26. cur = cur.next
  27. def add(self,data):
  28. '''向链表头部添加节点'''
  29. node = Node(data)
  30. if self.head is None:
  31. self.head = node
  32. self.tail = node
  33. else:
  34. node.next = self.head
  35. self.head.prev = node
  36. self.head = node
  37. def append(self,data):
  38. '''向链表尾部添加节点'''
  39. node = Node(data)
  40. if self.tail is None:
  41. self.head = node
  42. self.tail = node
  43. else:
  44. node.prev = self.tail
  45. self.tail.next = node
  46. self.tail = node
  47. def insert(self,index,data):
  48. '''向指定位置添加节点'''
  49. if index <= 0:
  50. self.add(data)
  51. elif index >= self.length():
  52. self.append(data)
  53. else:
  54. node = Node(data)
  55. cur = self.head
  56. for i in range(index):
  57. cur = cur.next
  58. # 循环完后cur指向节点index了
  59. node.next = cur
  60. node.prev = cur.prev
  61. cur.prev.next = node
  62. cur.prev = node
  63. def remove(self, item):
  64. """ 删除一个结点 """
  65. if self.is_empty():
  66. return
  67. # 当删除的节点在尾部
  68. if item == self.tail.data:
  69. self.tail = self.tail.prev
  70. self.tail.next = None
  71. return True
  72. cur = self.head
  73. pre = None
  74. # 第一个节点为需要删除的节点
  75. if cur.data == item:
  76. # 有多个节点
  77. if cur.next != None:
  78. self.head = cur.next
  79. return True
  80. # 只有一个节点
  81. else:
  82. self.head = None
  83. return True
  84. else:
  85. # 首尾之外的任意节点
  86. while cur.next != self.tail:
  87. if cur.data == item:
  88. pre.next = cur.next
  89. cur.next.prev = pre
  90. return True
  91. else:
  92. pre = cur
  93. cur = cur.next
  94. def find(self, data):
  95. """ 查找节点是否存在"""
  96. return data in self.items()
  97. def print_list(self):
  98. '''打印链表数据'''
  99. print('链表当前节点:')
  100. for node in self.items():
  101. print(node)
  102. if __name__ == '__main__':
  103. # 实例化双向链表
  104. doublelist = DoubleLinkedList()
  105. # 向头部添加节点
  106. doublelist.add(10)
  107. doublelist.add(20)
  108. doublelist.print_list()
  109. # 向尾部添加节点
  110. doublelist.append(30)
  111. doublelist.append(40)
  112. doublelist.print_list()
  113. # 任意位置添加节点
  114. doublelist.insert(2,666)
  115. doublelist.print_list()
  116. # 删除首尾和任意节点
  117. doublelist.remove(666)
  118. doublelist.remove(20)
  119. doublelist.remove(40)
  120. doublelist.print_list()

输出结果:

链表当前节点:

20

10

链表当前节点:

20

10

30

40

链表当前节点:

20

10

666

30

40

链表当前节点:

10

30

其他数据结构:栈、队列、树等的实现可以看:python-data-structure

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/549720
推荐阅读
相关标签
  

闽ICP备14008679号