python數據結構基礎(單鏈表,多鏈表,二叉樹,棧,隊列)


python數據結構基礎(單鏈表,多鏈表,二叉樹)

數據結構指數據對象中數據元素之間的關系

Python 給我們提供了很多現成的數據結構類型,這些系統自己定義好的,不需要我們自己去定義的數據結構叫做 Python 的內置數據結構,比如列表、元組、字典。而有些數據組織方式,Python 系統里面沒有直接定義,需要我們自己去定義實現這些數據的組織方式,這些數據組織方式稱之為 Python 的擴展數據結構,比如棧,隊列等.

線性表:一組序列元素的組織形式,我們可以將其抽象為線性表。一個線性表是某類元素的一個集合,還記錄着元素之間的一種順序關系。線性表是最基本的數據結構之一。

根據線性表的實際存儲方式,分為兩種實現模型:順序表和鏈表。Python 中的 list 和 tuple 兩種類型采用了順序表的實現技術。

順序表的構建需要預先知道數據大小來申請連續的存儲空間,而在進行擴充時又需要進行數據的搬遷,所以使用起來並不是很靈活

鏈表結構可以充分利用計算機內存空間,實現靈活的內存動態管理,常見的有單向鏈表和雙向鏈表。

在 Python 的官方實現中,list 實現采用了如下的策略:在建立空表(或者很小的表)時,系統分配一塊能容納 8 個元素的存儲區;在執行插入操作(insert 或 append)時,如果元素存儲區滿就換一塊 4 倍大的存儲區。但如果此時的表已經很大(目前的閥值為 50000),則改變策略,采用加一倍的方法。引入這種改變策略的方式,是為了避免出現過多空閑的存儲位置。

單鏈表:

 


class Node():
   '''單鏈表節點類'''
   def __init__(self,elem):
       self.elem = elem
       self.next = None

class SLink():
   def __init__(self,node=None):
       if node is None:
           self.__head = node
       else:
           self.__head = Node(node)

   def is_empty(self):
       return self.__head==None

   def length(self):
       count = 0
       curNode = self.__head
       while curNode != None:
           count+=1
           # self.__head = curNode.next
           curNode = curNode.next
       return count
   #遍歷
   def travel(self):
       curNode = self.__head
       while curNode !=None:
           print(curNode.elem,end='\t')
           curNode= curNode.next
       print()

   #查找
   def find(self,item):
       node = Node(item)
       curNode = self.__head
       while curNode !=None:
           if curNode.elem == node.elem:
               return True
           self.__head = curNode.next
           curNode = curNode.next
       return False


   #頭部添加
   def add(self,item):
       node = Node(item)
       if self.__head == None:
           self.__head=node
       else:
           curNode = self.__head
           self.__head = node
           node.next = curNode
   #尾部插入
   def append(self,item):
       node = Node(item)
       if self.__head == None:
           self.__head = node
       else:
           curNode = self.__head
           while curNode.next is not None:
               curNode = curNode.next
           curNode.next = node

   #指定位置插入
   def insert(self,num,item):
       node = Node(item)
       if self.__head ==None:
           self.__head = node
       else:
           if num>self.length():
               self.append(item)
               return
           if num<=0:
               self.add(item)
               return
           curNode = self.__head
           count = 1
           p = None
           while curNode is not None:
               if count == num:
                   node.next = curNode
                   p.next = node
                   break
               count+=1
               p=curNode
               curNode = curNode.next
   #刪除節點
   def delete(self,item):
       curNode = self.__head
       preNode = None
       while curNode is not None:
           if curNode.elem == item:
               #判斷是不是頭
               if preNode == None:
                   self.__head = curNode.next
               else:
                   preNode.next = curNode.next
               return
           else:
               preNode = curNode
               curNode = curNode.next




if __name__ == '__main__':
   a = SLink(10)
   print(a.is_empty())
   print(a.length())
   print(a.find(101))
   a.add(1)
   a.add(2)
   a.add(3)
   a.add(4)
   a.append(5)
   a.append(6)
   a.append(7)
   a.append(8)
   a.travel()
   a.insert(0,7)
   a.insert(100, 7)
   a.insert(4,100)
   a.travel()
   a.delete(100)
   a.travel()

 

雙鏈表


class Node():
   def __init__(self,elem=None):
       self.elem = elem
       self.pre = None
       self.next = None

class Dlink():
   def __init__(self,elem=None):
       if elem == None:
           self.__head = None
       else:
           self.__head = Node(elem)

   def length(self):
       count = 0
       curNode = self.__head
       while curNode is not None:
           count += 1
           curNode = curNode.next
       return count

   def is_empty(self):

       return self.__head == None

   def travel(self):
       if self.is_empty():
           return None
       curNode = self.__head
       while curNode != None:
           print(curNode.elem,end='\t')
           curNode = curNode.next
       print()

   #頭部添加
   def add(self,item):
       node = Node(item)
       if self.is_empty():
           self.__head=node
       else:
           curNode = self.__head
           curNode.pre= node
           node.next = curNode
           self.__head= node

   #尾部添加
   def append(self,item):
       node = Node(item)
       if self.is_empty():
           self.__head=node
       else:
           curNode = self.__head
           while curNode.next is not None:
               curNode = curNode.next
           curNode.next = node
           node.pre = curNode
   #制定位置插入
   def insert(self,num,item):
       if num <= 0:
           self.add(item)
       elif num > self.length()-1:
           self.append(item)
       else:
           node = Node(item)
           curNode = self.__head
           count = 0
           while count < num-1:
               count += 1
               curNode = curNode.next
           #這里需要注意順序,指向會變得
           node.pre = curNode
           node.next = curNode.next
           curNode.next.pre = node
           curNode.next = node


   def delete(self, item):
       '''刪除節點'''
       curNode = self.__head
       while curNode is not None:
           if curNode.elem == item:
               if curNode == self.__head:
                   self.__head = curNode.next
                   if curNode.next:
                       curNode.next.pre = None
               else:
                   curNode.pre.next = curNode.next
                   if curNode.next:
                       curNode.next.pre = curNode.pre
               break
           else:
               curNode = curNode.next




if __name__ == '__main__':
   b = Dlink(10)
   # print(b.length())
   b.add(1)
   b.add(2)
   b.add(3)
   b.add(4)
   b.travel()
   b.delete(3)
   b.travel()
   b.append(11)
   b.append(22)
   b.append(33)
   b.append(44)
   b.travel()
   b.insert(0,100)
   # b.travel()
   b.insert(1, 200)
   b.insert(100,300)
   b.travel()
   #刪除節點
   print('刪除節點1')
   b.delete(1)
   b.travel()
   print('刪除節點200')
   b.delete(200)
   b.travel()
   print('刪除節點4')
   b.delete(4)
   b.travel()

 

棧(stack),有些地方稱為堆棧,是一種容器,可存入數據元素、訪問元素、刪除元素,它的特點在於只能允許在容器的一端(稱為棧頂端指標,英語:top)進行加入數據(英語:push)和輸出數據(英語:pop)的運算。沒有了位置概念,保證任何時候可以訪問、刪除的元素都是此前最后存入的那個元素,確定了一種默認的訪問順序。 由於棧數據結構只允許在一端進行操作,因而按照后進先出(LIFO, Last In First Out)的原理運作。

隊列

隊列(queue)是只允許在一端進行插入操作,而在另一端進行刪除操作的線性表。 隊列是一種先進先出的(First In First Out)的線性表,簡稱 FIFO。允許插入的一端為隊尾,允許刪除的一端為隊頭。隊列不允許在中間部位進行操作.



class Stack():
   '''棧的實現后進先出'''
   def __init__(self,):
       self.__list = []
   
   #壓棧
   def push(self,item):
       self.__list.append(item)
       
   #彈出元素  
   def pop(self,item):    
       return self.__list.pop()
   
   #返回棧頂元素
   def peek(self):
       return self.__list[len(self.__list)-1]
   
   #返回棧的大小
   def size(self):
       return len(self.__list)
   
   def is_empty(self):
       return self.__list==[]
       
       
       
class Queue():
   '''隊列的實現先進先出'''

   def __init__(self):
       self.__list=[]
       
   def push(self,item):
       self.__list.insert(0,item)
       #self.list.append(item)

   def pop(self):
       return self.__list.pop()
       #return self.__list.pop(0)

   def is_empty(self):
       return self.__list==[]
       
   def size(self):
       return len(self.__list)

 

樹(英語:tree)是一種抽象數據類型(ADT)或是實作這種抽象數據類型的數據結構,用來模擬具有樹狀結構性質的數據集合。它是由 n(n>=1)個有限節點組成一個具有層次關系的集合

樹的術語:

(1) 節點的度:一個節點含有的子樹的個數稱為該節點的度; (2) 樹的度:一棵樹中,最大的節點的度稱為樹的度; (3) 葉節點或終端節點:度為零的節點; (4) 父親節點或父節點:若一個節點含有子節點,則這個節點稱為其子節點的父節點; (5) 孩子節點或子節點:一個節點含有的子樹的根節點稱為該節點的子節點; (6) 兄弟節點:具有相同父節點的節點互稱為兄弟節點; (7) 節點的層次:從根開始定義起,根為第 1 層,根的子節點為第 2 層,以此類推; (8) 樹的高度或深度:樹中節點的最大層次; (9) 堂兄弟節點:父節點在同一層的節點互為堂兄弟; (10)節點的祖先:從根到該節點所經分支上的所有節點; (11)子孫:以某節點為根的子樹中任一節點都稱為該節點的子孫。 (12)森林:由 m(m>=0)棵互不相交的樹的集合稱為森林;

樹的種類
  • 無序樹: :樹中任意節點的子節點之間沒有順序關系,這種樹稱為無序樹,也稱為自由樹;

  • 有序樹:樹中任意節點的子節點之間有順序關系,這種樹稱為有序樹;

    • 二叉樹:每個節點最多含有兩個子樹的樹稱為二叉樹;

      • 完全二叉樹:對於一顆二叉樹,假設其深度為 d(d>1)。除了第 d 層外,其它各層的節點數目均已達最大值,且第 d 層所有節點從左向右連續地緊密排列,這樣的二叉樹被稱為完全二叉樹,其中 滿二 叉樹的定義是所有葉節點都在最底層的完全二叉樹;

      • 平衡二叉樹(AVL 樹):當且僅當任何節點的兩棵子樹的高度差不大於 1 的二叉樹;

      • 排序二叉樹(二叉查找樹(英語:Binary Search Tree),也稱二叉搜索樹、有序二叉樹);

      • 霍夫曼樹(用於信息編碼):帶權路徑最短的二叉樹稱為哈夫曼樹或最優二叉樹;

      • B 樹 :一種對讀寫操作進行優化的自平衡的二叉查找樹,能夠保持數據有序,擁有多余兩個子樹;

        mysql數據庫的索引方式之一(還有一種是hash);

二叉樹:

性質 1: 在二叉樹的第 i 層上至多有 2^(i-1)個節點(i>0) 性質 2: 深度為 k 的二叉樹至多有 2^k - 1 個節點(k>0) 性質 3: 對於任意一棵二叉樹,如果其葉節點數為 N0,而度數為 2 的結點總數為 N2,則 N0=N2+1; 性質 4:具有 n 個節點的完全二叉樹的深度必為 log2(n+1) 性質 5:對完全二叉樹,若從上至下、從左至右編號,則編號為 i 的結點,其左孩子編號必為 2i,其右孩子號必為 2i+1;其雙親的編號必為 i/2(i=1 時為根,除外)

(1)完全二叉樹——若設二叉樹的高度為 h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第 h 層有葉子結點,並且葉子結點都是從左到右依次排布,這就是完全二叉樹。

(2)滿二叉樹——除了葉結點外每一個結點都有左右子葉且葉子結點都處在最底層的二叉樹。

二叉樹的節點及樹的創建


#樹結構

class Node():
   '''二叉樹的節點類'''
   def __init__(self,elem):
       self.elem = elem
       self.lchild = None
       self.rchild = None


#廣度遍歷,層次遍歷 A,B,C,D,E,F,...
#判斷A 的左節點,右節點
#判斷b 的左節點,右節點
#...
class Tree():
   def __init__(self):
       self.root = None
       
   def add(self,elem):
       node = Node(elem)
       #判斷根節點是否存在
       if self.root == None:
           self.root =node
       else:
           queue = [self.root]
           while queue:
               curNode = queue.pop(0)
               if curNode.lchild==None:
                   curNode.lchild=node
                   return
               else:
                   queue.append(curNode.lchild)
                   
               if curNode.rchild==None:
                   curNode.rchild=node
                   return
               else:
                   queue.append(curNode.rchild)
   #廣度優先遍歷
   def travel(self):
       queue = []
       #判斷root節點是否存在
       if self.root is None:
           return
       else:
           queue.append(self.root)
       while queue:
           curNode = queue.pop(0)
           print(curNode.elem,end='\t')
           if curNode.lchild is not None:
               queue.append(curNode.lchild)
           if curNode.rchild is not None:
               queue.append(curNode.rchild)
       print()
   #深度優先遍歷
   #先序遍歷 根 左 右
   def preOrder(self,root):
       if root is None:
           return
       else:
           print(root.elem,end='\t')
           self.preOrder(root.lchild)
           self.preOrder(root.rchild)
   #中序遍歷 左 根 右
   def inOrder(self,root):
       if root is None:
           return
       else:
           self.inOrder(root.lchild)
           print(root.elem,end='\t')
           self.inOrder(root.rchild)
   #后續遍歷 左 右 根
   def nextOrder(self,root):
       if root is None:
           return
       else:
           self.nextOrder(root.lchild)
           self.nextOrder(root.rchild)
           print(root.elem,end='\t')

if __name__=='__main__':
   tree = Tree()
   tree.add(0)
   tree.add(1)
   tree.add(2)
   tree.add(3)
   tree.add(4)
   tree.add(5)
   tree.add(6)
   tree.add(7)
   tree.add(8)
   tree.add(9)
   print('廣度優先')
   tree.travel()
   print('先序')
   tree.preOrder(tree.root)
   print()
   print('中序')
   tree.inOrder(tree.root)
   print()
   print('后序')
   tree.nextOrder(tree.root)

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM