Python 新手刚学链表,做了一个“捣浆糊”版的单链表类
鏈表定義
鏈表是一種物理存儲結構上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。
單向鏈表,又叫單鏈表、單向表,是由一個個節點組成的,每個節點是一種信息集合,包含元素本身以及下一個節點的地址。節點在內存中是非連續分布的,在程序運行期間,根據需要可以動態的創建節點,這就使得鏈表的長度沒有邏輯上的限制,有限制的是堆的大小。
在單向鏈表中,每個節點中存儲著下一個節點的地址?;趩蜗蜴湵?#xff0c;在每個節點內增加一個前驅節點的地址,這就是所謂的雙向鏈表,又叫雙鏈表、雙向表。
如單向鏈表的尾節點指針指向頭節點,即為循環單向鏈表。
 如單向鏈表的頭、尾節點指針互相指,即為循環雙向鏈表。
指針是C/C++等語言中的概念,也就是內存地址;python中沒有指針,也很少直接操作地址。
 在?python 這一類沒有指針的語言里,很難真正體現出鏈表的精髓,只能模擬出一個靜態鏈表來意思意思。
單向表類的實現
模仿python中二叉樹的節點Node類,把左右子樹的left,right換成一個Next,就有點像了。因為剛學python不久功力有限,愣是用字符串和列表,偽實現了一個單向表的類:
class Node():def __init__(self,val=None,Next=None):self.val = valself.Next = Nextdef __repr__(self):return 'listNode('+str(self.val)+')'def __getitem__(self, slices):list = self.values()return list[slices]def is_empty(self):return self.val is Nonedef value(self):return self.valdef values(self):head = selft = 'head'r = []while eval(t) is not None:r.append(eval(t).val)t+='.Next'return rdef size(self):if self.is_empty():return 0r = self.values()return len(r)def append(self, node):if self.val is None:self.val = nodereturnhead = selft = 'head'while eval(t) is not None:t+='.Next'exec(f'{t}=Node({node})')def pop(self):head = selfif head.size() < 2:res = head.valhead.val = Nonereturn rest = 'head'while eval(t).Next is not None:t+='.Next'res = eval(t).valexec(f'{t}=None')return resdef pprint(self):r = self.values()r = [i.join(["'"]*2) if type(i) is str else str(i) for i in r]print('->'.join(r))之所以說是“偽實現”,因為根本就是用字符串和列表模擬出來的效果。盡管這個類如此不入門,有點傻傻的,用上海咸話的講法,稱之為“搗漿糊”。但還是能完成不少功能的。呈上測試代碼,如下:
1. 逐個賦值
>>> LinkedList = Node() >>> LinkedList.is_empty() True >>> LinkedList.size() 0 >>> LinkedList = Node(1) >>> LinkedList.is_empty() False >>> LinkedList.size() 1 >>> LL = LinkedList >>> LL.Next = Node(2) >>> LL listNode(1) >>> LL.Next listNode(2) >>> LL.val 1 >>> LL.Next.val 2 >>> LL.value() 1 >>> LL.Next.value() 2 >>> LL.values() [1, 2] >>> >>> >>> LinkedList = Node() >>> LinkedList = Node(1,Node(2)) >>> linked = Node(1,Node(2)) >>> linked.Next.Next = Node('3',Node(4)) >>> linked.pprint() 1->2->'3'->4 >>> linked.values() [1, 2, '3', 4] >>>注:此鏈表類允許數字、字符串混裝?
2.追加append()和彈出pop()
>>> single = Node(1,Node(2,Node(3,Node(4,Node(5))))) >>> single.pprint() 1->2->3->4->5 >>> single.append(6) >>> single.pprint() 1->2->3->4->5->6 >>> single.pop() 6 >>> single.pop() 5 >>> single.pprint() 1->2->3->4 >>>?3. 嵌套賦值或用循環賦值
>>> single = Node(1,Node(2,Node(3,Node(4,Node(5))))) >>> single.size() 5 >>> single.values() [1, 2, 3, 4, 5] >>> >>> >>> link = Node() >>> for i in range(1,9):link.append(i)>>> link.pprint() 1->2->3->4->5->6->7->8 >>>4. 索引和切片
>>> lList = Node() >>> t = [lList.append(i) for i in range(1,9)] >>> lList.pprint() 1->2->3->4->5->6->7->8 >>> lList[:] [1, 2, 3, 4, 5, 6, 7, 8] >>> lList[::-1] [8, 7, 6, 5, 4, 3, 2, 1] >>> lList[0] 1 >>> lList[1] 2 >>> lList[7] 8 >>> lList[-1] 8 >>> lList[-2] 7 >>> lList[-8] 1 >>> lList[:5] [1, 2, 3, 4, 5] >>> lList[5:] [6, 7, 8] >>> lList[::2] [1, 3, 5, 7] >>> lList[1::2] [2, 4, 6, 8] >>>注:鏈表一般是不帶索引功能的,這里用類的內置方法__getitem__(self, slices)來強加一個索引和切片的功能,完全是繼承了列表的功能。
5. 刪除和插入
>>> single = Node(1,Node(2,Node(3,Node(4,Node(5))))) >>> single.pprint() 1->2->3->4->5 >>> single.Next.Next = single.Next.Next.Next >>> single.pprint() 1->2->4->5 >>> >>> tmp = single.Next.Next >>> single.Next.Next = Node(6) >>> single.Next.Next.Next = tmp >>> single.pprint() 1->2->6->4->5 >>>注:刪除和插入方法沒有直接寫進這個類里,但也能用代碼實現類似操作。
單鏈表真實的刪除和插入操作過程,如下所示:
6. 單鏈表的反轉(倒序)
>>> linked = Node() >>> assign = [linked.append(i) for i in range(1,9)] >>> linked.pprint() 1->2->3->4->5->6->7->8 >>> tmp,linked = linked,Node() >>> while not tmp.is_empty():linked.append(tmp.pop())>>> linked.pprint() 8->7->6->5->4->3->2->1 >>>注:用循環反復追加append原鏈表的pop()返回值完成倒序操作。
 ?
“搗漿糊”版的鏈表類就到此結束吧,準備下一篇再來重寫一個進階一點的鏈表類? ?^_^
總結
以上是生活随笔為你收集整理的Python 新手刚学链表,做了一个“捣浆糊”版的单链表类的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 灵活操作MS SQL 2005 中的数据
 - 下一篇: 等差数列求和