單鏈表的python實現

  首先說下線性表,線性表是一種最基本,最簡單的數據結構,通俗點講就是一維的存儲數據的結構。node

  線性表分爲順序表和連接表:python

  • 順序表示指的是用一組地址連續的存儲單元依次存儲線性表的數據元素,稱爲線性表的順序存儲結構或順序映像;
  • 鏈式表示指的是用一組任意的存儲單元存儲線性表中的數據元素,稱爲線性表的鏈式存儲結構。而他既能夠是連續的也能夠不連續,是經過一個與後繼結點的鏈接信息構建起來的。

*順序表(這個不是本次重點,簡單介紹一下)

   順序表是用一段連續的存儲單元依次存儲數據元素,查找元素是很方便的,可是若是要向其中添加刪除元素就不那麼簡單了。由於添加刪除元素要先找到那個位置,因爲順序表內部是經過地址的連續才使他成爲一個表,當刪掉元素時,要把後面的元素所有向前移,填補上空出來的地址空間;添加元素也是同樣,須要先把該位置後面的元素向後移去,才能在這塊地址上添加元素。數組

  以C語言爲例:順序表能夠經過一個數組來表示,每建立一個數組就對應給他分配一塊內存。固然除了靜態分配空間,還能夠動態擴展。後續的操做要在這塊內存上進行,通常都須要移動數組元素,複雜度會很高。數據結構

  在python中,順序表還有兩種表示方式:app

    • 一體式結構
    • 分離式結構

  這裏的一體和分離是指表中的元素集合,和爲實現正確操做而需記錄的信息,這兩部分是在同一塊空間仍是在旁邊的一塊新的空間中。學習

  python中的tuple和list就是採用了順序表的實現技術,不過tuple是不可變的,不支持對內部的操做。而list是一個元素個數可變的線性表,支持添加刪除等操做。list的思想實際上是和C語言中同樣的,只是對其中的功能進行了一些封裝,也就是list的那些屬性。spa

 

*鏈式表

  鏈表,顧名思義,相鄰結點是經過鏈來鏈接的,那麼什麼是鏈呢。咱們知道,C語言中有指針,指針經過地址來找到他的目標。如此說來,一個節點不只僅有他的元素,還須要有一個他下一個元素的地址。指針

  那麼,這裏須要指針和地址。python中的指針是什麼呢?下面先把這個放一下,先去理解一下python裏面變量標識的實質。code

 

  先看一下這個,爲何a和b的id是同樣的呢?那我再問一個問題:python中交換兩個變量的值時怎樣來實現的?blog

 

1 a = 10
2 b = 20
3 a,b = b,a

  爲何python能夠這樣來賦值呢?下面我再畫一幅圖。

 

                                                                        

  如今是否能理解了呢,變量自己就是存儲的一個地址,交換他們的值就是把本身的指向更改一下。那麼如今知道了標識的含義,咱們的指針域該怎麼寫呢,是否是直接用變量等於下一個結點啊。這樣看來就不復雜了,接下來的內容就和通常的鏈表同樣了。我在這裏說這些就是爲了弄清楚python是怎麼創建連接的。

 

1、單鏈表

  那麼下面就經過一個類來實現一個節點,節點當中包括數據域和連接域,代碼中實現了一些經常使用的功能,好比插入,查找等等。今天主要是說一下單鏈表是如何運用到python中的,因爲我以前沒有了解過這些。學習了以後,用本身以前的知識,就能夠很方便的運用鏈表了。後面的代碼就不過多解釋了,本身仔細琢磨一下。有什麼不理解的能夠留言,我會盡可能詳細的回覆。

  1 #!/usr/bin/env python
  2 # -*- coding: utf-8 -*-
  3 # @Date    : 2018-06-12 11:23:21
  4 # @Author  : yudanqu (943775910@qq.com)
  5 # @Link    : https://www.cnblogs.com/yudanqu/
  6 # @Version : $Id$
  7 
  8 
  9 class Node(object):
 10     """節點"""
 11 
 12     def __init__(self, elem):
 13         self.elem = elem
 14         self.next = None  # 初始設置下一節點爲空
 15 
 16 '''
 17 上面定義了一個節點的類,固然也能夠直接使用python的一些結構。好比經過元組(elem, None)
 18 '''
 19 
 20 
 21 # 下面建立單鏈表,並實現其應有的功能
 22 
 23 
 24 class SingleLinkList(object):
 25     """單鏈表"""
 26 
 27     def __init__(self, node=None):  # 使用一個默認參數,在傳入頭結點時則接收,在沒有傳入時,就默認頭結點爲空
 28         self.__head = node
 29 
 30     def is_empty(self):
 31         '''鏈表是否爲空'''
 32         return self.__head == None
 33 
 34     def length(self):
 35         '''鏈表長度'''
 36         # cur遊標,用來移動遍歷節點
 37         cur = self.__head
 38         # count記錄數量
 39         count = 0
 40         while cur != None:
 41             count += 1
 42             cur = cur.next
 43         return count
 44 
 45     def travel(self):
 46         '''遍歷整個列表'''
 47         cur = self.__head
 48         while cur != None:
 49             print(cur.elem, end=' ')
 50             cur = cur.next
 51         print("\n")
 52 
 53     def add(self, item):
 54         '''鏈表頭部添加元素'''
 55         node = Node(item)
 56         node.next = self.__head
 57         self.__head = node
 58 
 59     def append(self, item):
 60         '''鏈表尾部添加元素'''
 61         node = Node(item)
 62         # 因爲特殊狀況當鏈表爲空時沒有next,因此在前面要作個判斷
 63         if self.is_empty():
 64             self.__head = node
 65         else:
 66             cur = self.__head
 67             while cur.next != None:
 68                 cur = cur.next
 69             cur.next = node
 70 
 71     def insert(self, pos, item):
 72         '''指定位置添加元素'''
 73         if pos <= 0:
 74                 # 若是pos位置在0或者之前,那麼都當作頭插法來作
 75             self.add(item)
 76         elif pos > self.length() - 1:
 77             # 若是pos位置比原鏈表長,那麼都當作尾插法來作
 78             self.append(item)
 79         else:
 80             per = self.__head
 81             count = 0
 82             while count < pos - 1:
 83                 count += 1
 84                 per = per.next
 85             # 當循環退出後,pre指向pos-1位置
 86             node = Node(item)
 87             node.next = per.next
 88             per.next = node
 89 
 90     def remove(self, item):
 91         '''刪除節點'''
 92         cur = self.__head
 93         pre = None
 94         while cur != None:
 95             if cur.elem == item:
 96                 # 先判斷該節點是不是頭結點
 97                 if cur == self.__head:
 98                     self.__head = cur.next
 99                 else:
100                     pre.next = cur.next
101                 break
102             else:
103                 pre = cur
104                 cur = cur.next
105 
106     def search(self, item):
107         '''查找節點是否存在'''
108         cur = self.__head
109         while not cur:
110             if cur.elem == item:
111                 return True
112             else:
113                 cur = cur.next
114         return False
115 
116 
117 if __name__ == "__main__":
118 
119         # node = Node(100)  # 先建立一個節點傳進去
120 
121     ll = SingleLinkList()
122     print(ll.is_empty())
123     print(ll.length())
124 
125     ll.append(3)
126     ll.add(999)
127     ll.insert(-3, 110)
128     ll.insert(99, 111)
129     print(ll.is_empty())
130     print(ll.length())
131     ll.travel()
132     ll.remove(111)
133     ll.travel()

 2、單向循環鏈表和雙向鏈表

  與單鏈表相關聯的,還有單向循環鏈表和雙向鏈表:

  單向循環鏈表:在單鏈表的基礎上,再多一個由尾節點指向首節點的連接,首節點是指鏈表的第一個存數據的結點,而頭結點是指指向第一個存數據的結點的那個東西,僅有個連接域,而不是真正存儲內容的鏈表結點。須要注意的是,循環鏈表中,一些功能的建立是和單鏈表不同的,好比判空、判滿,它是循環的該怎麼判斷呢?這些內容能夠在上面給出的單鏈表的實現中進行修改得到,能夠試一下。

  雙向鏈表:與單鏈表相比,這個新增的特性就是雙向。能夠從前面向後面傳遞,也能夠從後面向前面傳遞,這個前面和後面是咱們本身定義的,認爲從一端到另外一端是正向,那麼倒過來則相反。這個雙向鏈表的實現和單鏈表也是基本上同樣的。單向鏈表是除了數據域再添加一個連接域,來指向下一個結點。那麼一樣的道理,雙向鏈表就再添加一個指向前一個結點的連接不就行了。這個時候再建立鏈表的時候就要把每一個節點與前驅結點以及後繼結點的連接創建好。

  雙向鏈表的插入和刪除等等操做,都要注意,不要把存儲的地址信息丟了,仔細考慮好兩邊的指向,先把誰連接上去,再連接誰。

 

 

  今天原本只想說說前面那一點點內容的,寫的寫的,後面感受不得不說一下,不過也沒有寫的比較完整。你們撿有用的東西來看。

相關文章
相關標籤/搜索