单向链表
定义:单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。
- 表元素域elem用来存放具体的数据
- 链接域next用来存放下一个节点的位置(python中的标识)
- 表量p指向链表的头结点(首节点)的位置,从P出发能找到表中的任意节点。
1. 单链表的操作
- is_empty()链表是否为空
- length()链表长度
- travel() 遍历整个链表
- add(item) 链表头部添加元素
- append(item) 链表尾部添加元素
- insert(post,item)指定位置添加元素
- remove(item) 删除节点
- search(item) 查找节点是否存在
2. 单链表的实现
- 单链表结点实现
class Node(object):
"""结点类型"""
def __init__(self,item):
# 保存元素
self.item = item
# 保存下一个节点
self.next = None
- 判断链表是否为空、链表的长度、遍历链表。
class SingleLinkList(object):
"""链表"""
def __init__(self):
self.__head = None
def is_empty(self):
"""链表是否为空"""
# if self.__head is None:
# return True
# return False
return self.__head is None
def length(self):
"""链表的长度"""
cur = self.__head
count = 0
while cur is not None:
count += 1
cur = cur.next
return count
def travel(self):
"""遍历链表"""
cur = self.__head
while cur is not None:
print(cur.item, end=' ')
# 在这个位置 cur 就是上一个节点
cur = cur.next
- 头部添加元素
def add(self,item):
"""头部添加元素"""
node = Node(item)
# 添加的节点的 next 指向头结点
node.next = self.__head
# 链表的头结点属性指向新添加的节点
self.__head = node
- 尾部添加元素
def append(self,item):
"""链表的尾部追加元素"""
if self.is_empty():
self.add(item)
return
cur = self.__head
# 程序在此处会如果是空链表会boom
while cur.next is not None:
cur = cur.next
# 退出循环之后 cur 指向的就是最后一个节点
# 实例化新节点
node = Node(item)
cur.next = node
# # 方法2
# pre = None
# while cur is not None:
# pre = cur
# cur = cur.next
#
# # 循环退出之后 pre 指向的就是最后一个节点
- 指定位置添加元素
def insert(self, pos, item):
"""指定位置添加元素"""
# 若指定位置pos为第一个元素之前,则执行头部插入
if pos <= 0:
self.add(item)
# 若指定位置超过链表尾部,则执行尾部插入
elif pos > (self.length()-1):
self.append(item)
# 找到指定位置
else:
node = SingleNode(item)
count = 0
# pre用来指向指定位置pos的前一个位置pos-1,初始从头节点开始移动到指定位置
pre = self.__head
while count < (pos-1):
count += 1
pre = pre.next
# 先将新节点node的next指向插入位置的节点
node.next = pre.next
# 将插入位置的前一个节点的next指向新节点
pre.next = node
- 删除结点
def remove(self,item):
"""删除元素,只删除第一个元素"""
cur = self.__head
pre = None
while cur is not None:
# 比较节点的 item 和删除的 item 是否相等
if cur.item == item:
# 如果删除的是首节点
if cur == self.__head:
self.__head = cur.next
else:
# 其他节点
pre.next = cur.next
# 只删除一个元素 为 item 的节点
return
# 保存前端节点
pre = cur
cur = cur.next
- 查看结点是否存在
def search(self,item):
"""查找节点是否存在"""
# 遍历 满足条件就认为找到 return True
cur = self.__head
while cur is not None:
if cur.item == item:
return True
cur = cur.next
# 默认没有找到
return False
3. 链表与顺序表的对比
链表失去了顺序表随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大,但对存储空间的使用要相对灵活。
链表与顺序表的各种操作复杂度如下所示:
操作 | 链表 | 顺序表 |
---|---|---|
访问元素 | O(n) | O(1) |
在头部插入/删除 | O(1) | O(n) |
在尾部插入/删除 | O(n) | O(1) |
在中间插入/删除 | O(n) | O(n) |
4. 单链表的实现(全部功能)
class Node(object):
"""节点类型"""
def __init__(self,item):
# 保存元素
self.item = item
# 保存下一个节点
self.next = None
# 以面向对象的方式来操作链表
# 增删改查
class SingleLinkList(object):
"""链表"""
def __init__(self):
self.__head = None
"""
is_empty() 链表是否为空
length() 链表长度
travel() 遍历整个链表
add(item) 链表头部添加元素
append(item) 链表尾部添加元素
insert(pos, item) 指定位置添加元素
remove(item) 删除节点
search(item) 查找节点是否存在
"""
def is_empty(self):
"""链表是否为空"""
# if self.__head is None:
# return True
# return False
return self.__head is None
def length(self):
"""链表的长度"""
cur = self.__head
count = 0
while cur is not None:
count += 1
cur = cur.next
return count
def travel(self):
"""遍历链表"""
cur = self.__head
while cur is not None:
print(cur.item, end=' ')
# 在这个位置 cur 就是上一个节点
cur = cur.next
def search(self,item):
"""查找节点是否存在"""
# 遍历 满足条件就认为找到 return True
cur = self.__head
while cur is not None:
if cur.item == item:
return True
cur = cur.next
# 默认没有找到
return False
def add(self,item):
"""头部添加元素"""
node = Node(item)
# 添加的节点的 next 指向头结点
node.next = self.__head
# 链表的头结点属性指向新添加的节点
self.__head = node
def append(self,item):
"""链表的尾部追加元素"""
if self.is_empty():
self.add(item)
return
cur = self.__head
# 程序在此处会如果是空链表会boom
while cur.next is not None:
cur = cur.next
# 退出循环之后 cur 指向的就是最后一个节点
# 实例化新节点
node = Node(item)
cur.next = node
# # 方法2
# pre = None
# while cur is not None:
# pre = cur
# cur = cur.next
#
# # 循环退出之后 pre 指向的就是最后一个节点
def insert(self, pos,item):
"""在指定的位置插入元素"""
# 若指定位置pos为第一个元素之前,则执行头部插入
if pos <= 0:
self.add(item)
# 若指定位置超过链表尾部,则执行尾部插入
elif pos > (self.length() - 1):
self.append(item)
else:
# 在中间某一个位置添加元素
# 角标为的位置添加元素, 遍历的时候需要获取1位置的前端节点
index = 0
cur = self.__head
while index < (pos - 1):
index = index + 1
cur = cur.next
# 循环退出之后 cur 指向的就是前端节点
node = Node(item)
node.next = cur.next
cur.next = node
def remove(self,item):
"""删除元素,只删除第一个元素"""
cur = self.__head
pre = None
while cur is not None:
# 比较节点的 item 和删除的 item 是否相等
if cur.item == item:
# 如果删除的是首节点
if cur == self.__head:
self.__head = cur.next
else:
# 其他节点
pre.next = cur.next
# 只删除一个元素 为 item 的节点
return
# 保存前端节点
pre = cur
cur = cur.next
if __name__ == '__main__':
single = SingleLinkList()
print(single.is_empty()) # True
print(single.length()) # 0
single.append(0)
single.add(1)
single.add(2)
print(single.is_empty()) # False
print(single.length()) # 3
single.travel() # 2,1,0
print(" ")
print(single.search(1)) # True
print(single.search(10)) # False
single.append(5)
single.travel() # 2,1,0,5
print(" ")
single.insert(100000,6)
single.insert(-10,8)
single.insert(1,11) # 8,11,2,1,0,5,6
single.travel()
print(" ")
single.remove(0) # 8,11,2,1,5,6
single.travel()
print(" ")
single.remove(8) # 11,2,1,5,6
single.travel()
print(" ")
single.remove(6) # 11,2,1,5
single.travel()