链表

数组(Python中的列表)的结构实现如下:

 

对于101 25 36如果采用数组的形式存储的话如下图所示:

 

 数组在使用中需要事先预估要存储的数据的个数,一次性申请存储空间。查找元素时速度很快,但是在在扩充时会非常慢。需要重新申请一块新的内存地址。

链表可以解决顺序表扩充时的不足,链表扩充时,原存储不变,加一个扩一个,事先无需进行预估。

 

链表的节点结构如下:

,data为数据区,next为地址,指向下一个节点。

 

 

链表的节点结构如下图,其中head用于保存首位节点的地址,地址是无需连续得:

 

 接下来用Python实现链表,并实现相关属性:

上代码:

  1 # 节点类
  2 class LinklistNode:
  3     """节点"""
  4     def __init__(self, x):
  5         """
  6         elem:节点保存的数据
  7         next:保存指向下一个节点的地址
  8         """
  9         self.value = x
 10         self.next = None  # 由于此时不知道下一个节点的地址,此处初始化为空
 11 
 12 
 13 # 链表类,最终会由节点类来构造成链表,包括链表的各种属性
 14 class SinglelinkList:
 15     """单向链表"""
 16 
 17     def __init__(self, node=None):  # 这里对于node参数,如果传入数值则赋值,否则就使用默认值None
 18         self.__head = node  # 通过head找到头节点。对于节点的头部地址只对类内使用,不对外暴露,所以使用私有属性
 19 
 20     def is_empty(self):
 21         """链表是否为空"""
 22         return self.__head == None
 23 
 24     def length(self):
 25         """链表长度"""
 26         cur = self.__head  # cur用来移动遍历节点
 27         count = 0  # 记录数量,赋值为0与下面的判断条件结合很好的处理了空列表的情况
 28         while cur != None:  # 为什么不用cur.next != None,这个需要举例确定,与计数的初始值有关
 29             count += 1
 30             cur = cur.next  # 移动到下一个节点
 31         return count
 32 
 33     def travel(self):
 34         """遍历整个列表"""
 35         cur = self.__head
 36         while cur != None:
 37             print(cur.element, end=" ")
 38             cur = cur.next
 39 
 40     def addlast(self, data):  # 传入的是一个数,而不是一个节点,这样用户在使用中无需关心什么节点
 41         """链表尾部添加元素"""
 42         node = LinklistNode(data)
 43         if self.__head == None:
 44             self.__head = node
 45         else:
 46             cur = self.__head
 47         while cur.next != None:
 48             cur = cur.next
 49         cur.next = node
 50 
 51     def addhead(self, data):
 52         """链表头部添加元素,头插法"""
 53         node = LinklistNode(data)
 54         node.next = self.__head
 55         self.__head = node
 56 
 57     def insert(self, pos, data):
 58         """指定位置添加元素"""
 59         """
 60         :pos,由自己定义,从0开始,将data添加到pos位置,链表不同于顺序表,链表要找到某一位置,必须遍历
 61         """
 62         node = LinklistNode(data)
 63         if pos <= 0:
 64             # 此处认为使用头插法
 65             self.addhead(data)
 66         elif pos > (self.length() - 1):  # 此处不含等于号
 67             # 此处认为使用尾插法
 68             self.addlast(data)
 69         else:
 70             cur = self.__head
 71             count = 0
 72             while count <= (pos - 1):
 73                 cur = cur.next
 74                 count += 1
 75             # 等循环退出之后,cur指向pos-1的位置上,进行操作
 76             node.next = cur.next
 77             cur.next = node
 78 
 79     def search(self, data):
 80         """查找指定元素是否存在,遍历+比对"""
 81         cur = self.__head
 82         while cur != None:
 83             if cur.elem == data:
 84                 return True
 85             else:
 86                 cur = cur.next
 87         return False  # 考虑,对于空列表此处也可以实现
 88 
 89     def remove(self, data):
 90         """删除节点"""
 91         cur = self.__head
 92         pre = None  # 程序中,常使用 pre 或者 prior 来表示前一个
 93         while cur != None:
 94             if cur.value == data:
 95                 # 判断此节点是否为头节点
 96                 if cur == self.__head:
 97                     self.__head = cur.next
 98                 else:
 99                     pre = cur
100                     pre.next = cur.next
101                     break
102             else:
103                 cur = cur.next
104         """
105         在删除列表这个操作中要重点考虑以下四种特殊情况:
106         1.空列表
107         2.删除首节点
108         3.删除首节点且只有一个节点
109         4.删除尾结点
110         """
111 
112 
113 # 到此基本实现了链表的所有属性,下面对代码进行测试
114 if __name__ == "__main__":
115     ll = SinglelinkList()
116     print(ll.is_empty())
117     print(ll.length())
118     ll.remove(2)
119 
120     ll.addhead(1)
121     print(ll.is_empty())
122     print(ll.length())
123     ll.remove(1)
124 
125     ll.addhead(2)
126     ll.addhead(3)
127     ll.addhead(4)
128     ll.addhead(5)
129     ll.addhead(6)
130     ll.addhead(7)
131     print(ll.is_empty())
132     print(ll.length())
133 
134     ll.insert(-1, 9)
135     ll.insert(3, 100)
136     ll.remove(100)
137     print(ll.is_empty())
138     print(ll.length())

 

 

 

 

链表是数据结构之一,其中的数据呈线性排列。在链表中,数据的添加和删除都较为方便, 就是访问比较耗费时间。

关键点:
实际上,相比较数组来说,并不存在链表这样一个对象,链表是由多个节点组成的,因此,我们能接触到的数据对象只有节点。我们可以根据节点来寻找周围节点,许多节点之间的关系抽象地构成了一个链表。

 

posted @ 2019-10-21 23:16  一名石匠  阅读(195)  评论(0编辑  收藏  举报