1. 无序表列表:
1.1 定义:
列表是一种数据项按照相对位置存放的数据集。
无序表unordered list是指数据项之间没有顺序的列表。
如一个考试分数的集合“54, 26, 93, 17, 77和31”。
用无序表来表示,就是[54, 26, 93,17, 77, 31]。
2. Python中的无序表List
2.1 定义
List由如下操作定义,为了简单起见,假设表中不存在重复数据项:
- List():创建一个空列表
- add(item):添加一个数据项到列表中,假设item原先不存在于列表中
- remove(item):从列表中移除item,列表被修改,item原先应存在于表中
- search(item):在列表中查找item,返回布尔类型值
- isEmpty():返回列表是否为空
- size():返回列表包含了多少数据项
- append(item):添加一个数据项到表末尾,假设item原先不存在于列表中
- index(item):返回数据项在表中的位置
- insert(pos, item):将数据项插入到位置pos,假设item原先不存在与列表中,同时原列表具有足够多个数据项,能让item占据位置pos
- pop():从列表末尾移除数据项,假设原列表至少有1个数据项
- pop(pos):移除位置为pos的数据项,假设原列表存在位置pos
3. 链表
3.1 定义和性质
链表可以实现一个无序表数据格式。
虽然列表数据结构要求保持数据项的前后相对位置,但这种前后位置的保持,并不要求数据项依次存放在连续的存储空间
如下图,数据项存放位置并没有规则,但如果在数据项之间建立链接指向,就可以保持其前后相对位置
- 第一个和最后一个数据项需要显式标记出来,一个是队首,一个是队尾,后面再无数据了。
![](https://img-blog.csdnimg.cn/b181b8449bbe4040bdd045f181b0bf96.png)
3.2 节点Node
链表由节点Node组成
每个节点Node包含两部分:
- 数据项本身: data
- 指向下一个节点的引用信息: next。
注意next为None的意思是没有下一个节点了,这个很重要
![](https://img-blog.csdnimg.cn/2c6b29645d1643a4b9dd7a3bccd060db.png)
3.3 Python实现链表的节点Node
class Node:
def __init__(self, init_data):
self.data = init_data
self.next = None
def get_data(self):
return self.data
def get_next(self):
return self.next
def set_data(self, new_data):
self.data = new_data
def set_next(self, new_next):
self.next = new_next
node1 = Node(54)
print(node1.get_data()) # 54
node2 = Node(26)
node1.set_next(node2)
print(node2.get_data()) # 26
print(node1.get_next().get_data()) # 26
node3 = Node(93)
node2.set_next(node3)
print(node3.get_data()) # 93
print(node2.get_next().get_data()) # 93
3.4 用链表节点Node实现无序表
链表的第一个和最后一个节点最重要
如果想访问到链表中的所有节点,就必须从第一个节点开始沿着链接遍历下去,就是说从头节点开始,第一个next开始遍历无序表(即头节点的next的节点的数据被访问),直到next是None的时候遍历停止。
- 所以无序表必须要有对第一个节点的引用信息
3.4.1 头节点head
头节点就是用来保存列表中第一个数据的引用信息的,空表也有head,空表的head是None。意思是self.head就相当于self.head.next(),由于self.head.data()是不存在的,所以这部分就直接省略了。换句话说self.head()就表示了第一个存储数据的节点就等同于self.head.next()。
class UnorderList:
def __init__(self):
self.head = None
mylist = UnorderList()
print mylist.head # 结果为None
随着数据项的加入,无序表的head始终指向链条中的第一个节点
- 注意无序表mylist对象本身并head不包含数据项(数据项在节点中)
- head只是对首个节点Node的引用
- 判断空表的isEmpty()很容易实现
return self.head == None
![](https://img-blog.csdnimg.cn/7e23f3a5ba034005ab1060689bbf4250.png)
3.4.2 add方法
add方法:向无序表中添加数据项
无序表并没有限定数据项之间的顺序,新数据项可以加入到原表的任何位置
按照实现的性能考虑,应添加到最容易加入的位置上。
要访问到整条链上的所有数据项,必须从表头head开始沿着next链接逐个向后查找,所以添加新数据项最快捷的位置是表头,整个链表的首位置。
![](https://img-blog.csdnimg.cn/fbb145b991a24ea5960472e921b419cc.png)
![](https://img-blog.csdnimg.cn/02b7cbfab4eb4f168be02a622e6960a8.png)
def add(self, item):
temp = Node(item)
temp.setNext(self.head)
self.head = temp
![](https://img-blog.csdnimg.cn/147ff6b242b54f37b125b7d87e414bbe.png)
3.4.3 size方法
size:从链条头head开始遍历到表尾同时用变量累加经过的节点个数
![](https://img-blog.csdnimg.cn/f7762981fbf742058aca009bfce02515.png)
def size(self):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.getNext()
return count
3.4.4 search方法
从链表头head开始遍历到表尾,同时判断当前节点的数据项是否为目标
![](https://img-blog.csdnimg.cn/12524804c7734acca6d3910fe4ce7bc3.png)
def search(self, item)
current = self.head
found = False
while current != None and not found:
if current.getData() == item:
found = True
else:
current = current.getNext()
return found
3.4.5 remove方法
首先要找到item,这个过程跟search一样,但在删除节点时,需要特别的技巧
- current指向的是当前匹配数据项的节点
- 而删除需要把前一个节点的next指向current的下一个节点
- 所以我们在search current的同时,还要维护前一个(previous)节点的引用
![](https://img-blog.csdnimg.cn/93ee258e3b5b460aac28e6beaa459c67.png)
找到item之后,current指向item节点,previous指向前一个节点,开始执行删,需要区分两种情况:
- current是首个节点
- current是位于链条中间的节点
![](https://img-blog.csdnimg.cn/0bb437b6f8ca43a8a50a6b507e5e4dd2.png)
def remove(item):
current = self.head
previous = None
found = False
while not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())
整个链表的对象和操作和节点定义如下:
class Node:
def __init__(self, init_data):
self.data = init_data
self.next = None
def get_data(self):
return self.data
def get_next(self):
return self.next
def set_data(self, new_data):
self.data = new_data
def set_next(self, new_next):
self.next = new_next
class UnorderList:
def __init__(self):
self.head = None
def add(self, item):
temp = Node(item)
temp.set_next(self.head)
self.head = temp
def size(self):
count = 0
current = self.head
while current.next is not None:
count = count + 1
current = current.next
return count
def search(self, item):
current = self.head
found = False
while current.next is not None:
current = current.next
if current.data == item:
return current.data
return found
def remove(self, item):
current = self.head
if current.data == item:
self.head = current.next
else:
previous = current
current = current.next
while current.next is not None:
previous = previous.next
current = current.next
if current.data == item:
previous.next = current.next
my_list = UnorderList()
print(my_list.head)
my_list.add(31)
my_list.add(77)
my_list.add(17)
my_list.add(93)
my_list.add(26)
my_list.add(54)
print(my_list.head.get_data())
print(my_list.size())
print(my_list.search(31))
my_list.remove(31)
print(my_list.size())
print(my_list.search(31))
print(my_list.remove(93))
print(my_list.size())
print(my_list.search(93))
参考文献
本文的知识来源于B站视频 【慕课+课堂实录】数据结构与算法Python版-北京大学-陈斌-字幕校对-【完结!】,是对陈斌老师课程的复习
总结