網站首頁 編程語言 正文
一、鏈表簡介
鏈表是一種在存儲單元上非連續、非順序的存儲結構。數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現。鏈表是由一系列的結點組成,結點可以在運行時動態生成。每個結點包含兩部分:數據域與指針域。數據域存儲數據元素,指針域存儲下一結點的指針。
二、單向鏈表
單向鏈表也叫單鏈表,是鏈表中最簡單的形式,它的每個節點包含兩個域,一個信息域(元素域)和一個鏈接域。這個鏈接指向鏈表中的下一個節點,而最后一個節點的鏈接域則指向一個空值。
head 保存首地址,item 存儲數據,next 指向下一結點地址。
鏈表失去了序列的隨機讀取優點,同時鏈表增加了指針域,空間開銷也較大,但它對存儲空間的使用要相對靈活。
列如:有一堆數據[1,2,3,5,6,7],要在3和5之間插入4, 如果用數組,需要將5之后的數據都往后退一位,然后再插入4,這樣非常麻煩,但是如果用鏈表,我就直接在3和5之間插入4就行。
1. 定義結點
結點的數據結構為數據元素(item)與 指針(next)
class Node(object):
"""單鏈表的結點"""
def __init__(self, item):
# item存放數據元素
self.item = item
# next是下一個節點的標識
self.next = None
2. 定義鏈表
鏈表需要具有首地址指針head。
class SingleLinkList(object):
"""單鏈表"""
def __init__(self):
self._head = None
示例:創建鏈表
if __name__ == '__main__':
# 創建鏈表
link_list = SingleLinkList()
# 創建結點
node1 = Node(1)
node2 = Node(2)
# 將結點添加到鏈表
link_list._head = node1
# 將第一個結點的next指針指向下一結點
node1.next = node2
# 訪問鏈表
print(link_list._head.item) # 訪問第一個結點數據
print(link_list._head.next.item) # 訪問第二個結點數據
是不是感覺很麻煩,所以我們要在鏈表中增加操作方法。
- is_empty() 鏈表是否為空
- length() 鏈表長度
- items() 獲取鏈表數據迭代器
- add(item) 鏈表頭部添加元素
- append(item) 鏈表尾部添加元素
- insert(pos, item) 指定位置添加元素
- remove(item) 刪除節點
- find(item) 查找節點是否存在
代碼如下:
class SingleLinkList(object):
"""單鏈表"""
def __init__(self):
self._head = None
def is_empty(self):
"""判斷鏈表是否為空"""
return self._head is None
def length(self):
"""鏈表長度"""
# 初始指針指向head
cur = self._head
count = 0
# 指針指向None 表示到達尾部
while cur is not None:
count += 1
# 指針下移
cur = cur.next
return count
def items(self):
"""遍歷鏈表"""
# 獲取head指針
cur = self._head
# 循環遍歷
while cur is not None:
# 返回生成器
yield cur.item
# 指針下移
cur = cur.next
def add(self, item):
"""向鏈表頭部添加元素"""
node = Node(item)
# 新結點指針指向原頭部結點
node.next = self._head
# 頭部結點指針修改為新結點
self._head = node
def append(self, item):
"""尾部添加元素"""
node = Node(item)
# 先判斷是否為空鏈表
if self.is_empty():
# 空鏈表,_head 指向新結點
self._head = node
else:
# 不是空鏈表,則找到尾部,將尾部next結點指向新結點
cur = self._head
while cur.next is not None:
cur = cur.next
cur.next = node
def insert(self, index, item):
"""指定位置插入元素"""
# 指定位置在第一個元素之前,在頭部插入
if index <= 0:
self.add(item)
# 指定位置超過尾部,在尾部插入
elif index > (self.length() - 1):
self.append(item)
else:
# 創建元素結點
node = Node(item)
cur = self._head
# 循環到需要插入的位置
for i in range(index - 1):
cur = cur.next
node.next = cur.next
cur.next = node
def remove(self, item):
"""刪除節點"""
cur = self._head
pre = None
while cur is not None:
# 找到指定元素
if cur.item == item:
# 如果第一個就是刪除的節點
if not pre:
# 將頭指針指向頭節點的后一個節點
self._head = cur.next
else:
# 將刪除位置前一個節點的next指向刪除位置的后一個節點
pre.next = cur.next
return True
else:
# 繼續按鏈表后移節點
pre = cur
cur = cur.next
def find(self, item):
"""查找元素是否存在"""
return item in self.items()
示例:操作鏈表
if __name__ == '__main__':
link_list = SingleLinkList()
# 向鏈表尾部添加數據
for i in range(5):
link_list.append(i)
# 向頭部添加數據
link_list.add(6)
# 遍歷鏈表數據
for i in link_list.items():
print(i, end='\t')
# 鏈表數據插入數據
link_list.insert(3, 9)
print('\n', list(link_list.items()))
# 刪除鏈表數據
link_list.remove(0)
# 查找鏈表數據
print(link_list.find(4))
三、循環鏈表
單向循環鏈表為單向鏈表的變種,鏈表的最后一個next指向鏈表頭,新增一個循環。
1. 循環鏈表結點
class Node(object):
"""鏈表的結點"""
def __init__(self, item):
# item存放數據元素
self.item = item
# next是下一個節點的標識
self.next = None
2. 定義循環鏈表
class SingleCycleLinkList(object):
def __init__(self):
self._head = None
def is_empty(self):
"""判斷鏈表是否為空"""
return self._head is None
def length(self):
"""鏈表長度"""
# 鏈表為空
if self.is_empty():
return 0
# 鏈表不為空
count = 1
cur = self._head
while cur.next != self._head:
count += 1
# 指針下移
cur = cur.next
return count
def items(self):
""" 遍歷鏈表 """
# 鏈表為空
if self.is_empty():
return
# 鏈表不為空
cur = self._head
while cur.next != self._head:
yield cur.item
cur = cur.next
yield cur.item
def add(self, item):
""" 頭部添加結點"""
node = Node(item)
if self.is_empty(): # 為空
self._head = node
node.next = self._head
else:
# 添加結點指向head
node.next = self._head
cur = self._head
# 移動結點,將末尾的結點指向node
while cur.next != self._head:
cur = cur.next
cur.next = node
# 修改 head 指向新結點
self._head = node
def append(self, item):
"""尾部添加結點"""
node = Node(item)
if self.is_empty(): # 為空
self._head = node
node.next = self._head
else:
# 尋找尾部
cur = self._head
while cur.next != self._head:
cur = cur.next
# 尾部指針指向新結點
cur.next = node
# 新結點指針指向head
node.next = self._head
def insert(self, index, item):
""" 指定位置添加結點"""
if index <= 0: # 指定位置小于等于0,頭部添加
self.add(item)
# 指定位置大于鏈表長度,尾部添加
elif index > self.length() - 1:
self.append(item)
else:
node = Node(item)
cur = self._head
# 移動到添加結點位置
for i in range(index - 1):
cur = cur.next
# 新結點指針指向舊結點
node.next = cur.next
# 舊結點指針 指向 新結點
cur.next = node
def remove(self, item):
""" 刪除一個結點 """
if self.is_empty():
return
cur = self._head
pre = Node
# 第一個元素為需要刪除的元素
if cur.item == item:
# 鏈表不止一個元素
if cur.next != self._head:
while cur.next != self._head:
cur = cur.next
# 尾結點指向 頭部結點的下一結點
cur.next = self._head.next
# 調整頭部結點
self._head = self._head.next
else:
# 只有一個元素
self._head = None
else:
# 不是第一個元素
pre = self._head
while cur.next != self._head:
if cur.item == item:
# 刪除
pre.next = cur.next
return True
else:
pre = cur # 記錄前一個指針
cur = cur.next # 調整指針位置
# 當刪除元素在末尾
if cur.item == item:
pre.next = self._head
return True
def find(self, item):
""" 查找元素是否存在"""
return item in self.items()
if __name__ == '__main__':
link_list = SingleCycleLinkList()
print(link_list.is_empty())
# 頭部添加元素
for i in range(5):
link_list.add(i)
print(list(link_list.items()))
# 尾部添加元素
for i in range(6):
link_list.append(i)
print(list(link_list.items()))
# 添加元素
link_list.insert(3, 45)
print(list(link_list.items()))
# 刪除元素
link_list.remove(5)
print(list(link_list.items()))
# 元素是否存在
print(4 in link_list.items())
四、雙向鏈表
雙向鏈表比單向鏈表更加復雜,它每個節點有兩個鏈接:一個指向前一個節點,當此節點為第一個節點時,指向空值;而另一個鏈接指向下一個節點,當此節點為最后一個節點時,指向空值。
head 保存首地址,item 存儲數據,next 指向下一結點地址,prev 指向上一結點地址。
1. 定義雙向鏈表結點
class Node(object):
"""雙向鏈表的結點"""
def __init__(self, item):
# item存放數據元素
self.item = item
# next 指向下一個節點的標識
self.next = None
# prev 指向上一結點
self.prev = None
2. 定義雙向鏈表
class BilateralLinkList(object):
"""雙向鏈表"""
def __init__(self):
self._head = None
def is_empty(self):
"""判斷鏈表是否為空"""
return self._head is None
def length(self):
"""鏈表長度"""
# 初始指針指向head
cur = self._head
count = 0
# 指針指向None 表示到達尾部
while cur is not None:
count += 1
# 指針下移
cur = cur.next
return count
def items(self):
"""遍歷鏈表"""
# 獲取head指針
cur = self._head
# 循環遍歷
while cur is not None:
# 返回生成器
yield cur.item
# 指針下移
cur = cur.next
def add(self, item):
"""向鏈表頭部添加元素"""
node = Node(item)
if self.is_empty():
# 頭部結點指針修改為新結點
self._head = node
else:
# 新結點指針指向原頭部結點
node.next = self._head
# 原頭部 prev 指向 新結點
self._head.prev = node
# head 指向新結點
self._head = node
def append(self, item):
"""尾部添加元素"""
node = Node(item)
if self.is_empty(): # 鏈表無元素
# 頭部結點指針修改為新結點
self._head = node
else: # 鏈表有元素
# 移動到尾部
cur = self._head
while cur.next is not None:
cur = cur.next
# 新結點上一級指針指向舊尾部
node.prev = cur
# 舊尾部指向新結點
cur.next = node
def insert(self, index, item):
""" 指定位置插入元素"""
if index <= 0:
self.add(item)
elif index > self.length() - 1:
self.append(item)
else:
node = Node(item)
cur = self._head
for i in range(index):
cur = cur.next
# 新結點的向下指針指向當前結點
node.next = cur
# 新結點的向上指針指向當前結點的上一結點
node.prev = cur.prev
# 當前上一結點的向下指針指向node
cur.prev.next = node
# 當前結點的向上指針指向新結點
cur.prev = node
def remove(self, item):
""" 刪除結點 """
if self.is_empty():
return
cur = self._head
# 刪除元素在第一個結點
if cur.item == item:
# 只有一個元素
if cur.next is None:
self._head = None
return True
else:
# head 指向下一結點
self._head = cur.next
# 下一結點的向上指針指向None
cur.next.prev = None
return True
# 移動指針查找元素
while cur.next is not None:
if cur.item == item:
# 上一結點向下指針指向下一結點
cur.prev.next = cur.next
# 下一結點向上指針指向上一結點
cur.next.prev = cur.prev
return True
cur = cur.next
# 刪除元素在最后一個
if cur.item == item:
# 上一結點向下指針指向None
cur.prev.next = None
return True
def find(self, item):
"""查找元素是否存在"""
return item in self.items()
原文鏈接:https://blog.csdn.net/weixin_39589455/article/details/130504551
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-07-01 ASP.NET中的Web控件介紹_基礎應用
- 2022-05-21 Python中with上下文管理協議的作用及用法_python
- 2022-02-05 Tableau:如何處理Excel中一個sheet中有多張表的問題?
- 2022-10-01 sql語法中的concat()函數詳解_MsSql
- 2022-08-20 PostgreSQL實現按年、月、日、周、時、分、秒的分組統計_PostgreSQL
- 2021-12-01 linux下umask命令用途原理和計算方式詳解_Linux
- 2021-11-02 利用shadowsocks搭建局域網透明網關_Linux
- 2022-12-26 C#操作xml文件之Linq?To?Xml詳解_C#教程
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支