1. 程式人生 > >Python資料結構——樹的實現

Python資料結構——樹的實現

在用巢狀列表表示樹時,我們使用 Python 的列表來編寫這些函式。雖然把介面寫成列表的一系列方法與我們已實現其他的抽象資料型別有些不同,但這樣做比較有意思,因為它為我們提供一個簡單、可以直接檢視的遞迴資料結構。在列表實現樹時,我們將儲存根節點作為列表的第一個元素的值。列表的第二個元素的本身是一個表示左子樹的列表。這個列表的第三個元素表示在右子樹的另一個列表。為了說明這個儲存結構,讓我們來看一個例子。圖 1 展示出一個簡單的樹以及相應的列表實現。

圖 1: 簡單樹

12345678 myTree=['a',#root['b',#left subtree['d'[],[]],['e'[],[]]],['c',#right subtree['f'[],[]],[]]]

請注意,我們可以使用索引來訪問列表的子樹。樹的根是myTree[0],根的左子樹是myTree[1],和右子樹是myTree[2]。下面的程式碼說明了如何用列表建立簡單樹。一旦樹被構建,我們可以訪問根和左、右子樹。巢狀列表法一個非常好的特性就是子樹的結構與樹相同,本身是遞迴的。子樹具有根節點和兩個表示葉節點的空列表。列表的另一個優點是它容易擴充套件到多叉樹。在樹不僅僅是一個二叉樹的情況下,另一個子樹只是另一個列表。

12345 myTree=['a',['b',['d',[],[]],['e'
,[],[]]],['c',['f',[],[]],[]]]print(myTree)print('left subtree = ',myTree[1])print('root = ',myTree[0])print('right subtree = ',myTree[2])

讓我們定義一些函式,使我們很容易像使用列表一樣操作樹。請注意,我們不會去定義一個二叉樹類。我們將編寫的函式將只是操作列表使之類似於樹。

12 def BinaryTree(r):return[r,[],[]]

該二叉樹只是構建一個根節點和兩個空子節點的列表。左子樹新增到樹的根,我們需要插入一個新的列表到根列表的第二個位置。我們必須注意,如果列表中已經有值在第二個位置,我們需要跟蹤它,將新節點插入樹中作為其直接的左子節點。Listing 1 顯示了插入左子節點。

Listing 1

1234567 def insertLeft(root,newBranch):t=root.pop(1)iflen(t)>1:root.insert(1,[newBranch,t,[]])else:root.insert(1,[newBranch,[],[]])returnroot

請注意,插入一個左子節點,我們首先獲取對應於當前左子節點的列表(可能是空的)。然後,我們新增新的左子節點,將原來的左子節點作為新節點的左子節點。這使我們能夠將新節點插入到樹中的任何位置。對於insertRight的程式碼類似於insertLeft,如Listing 2 中。

Listing 2

1234567 def insertRight(root,newBranch):t=root.pop(2)iflen(t)>1:root.insert(2,[newBranch,[],t])else:root.insert(2,[newBranch,[],[]])returnroot

為了完善樹的實現(參見Listing3),讓我們寫幾個用於獲取和設定根值的函式,以及獲得左邊或右邊子樹的函式。

Listing 3

1234567891011 def getRootVal(root):returnroot[0]def setRootVal(root,newVal):root[0]=newValdef getLeftChild(root):returnroot[1]def getRightChild(root):returnroot[2]

以下是完整的巢狀列表表示樹的程式碼

1234567891011121314151617181920212223242526272829303132333435363738394041424344 def BinaryTree(r):return[r,[],[]]def insertLeft(root,newBranch):t=root.pop(1)iflen(t)>1:root.insert(1,[newBranch,t,[]])else:root.insert(1,[newBranch,[],[]])returnrootdef insertRight(root,newBranch):t=root.pop(2)iflen(t)>1:root.insert(2,[newBranch,[],t])else:root.insert(2,[newBranch,[],[]])returnrootdef getRootVal(root):returnroot[0]def setRootVal(root,newVal):root[0]=newValdef getLeftChild(root):returnroot[1]def getRightChild(root):returnroot[2]r=BinaryTree(3)insertLeft(r,4)insertLeft(r,5)insertRight(r,6)insertRight(r,7)l=getLeftChild(r)print(l)setRootVal(l,9)print(r)insertLeft(l,11)print(r)print(getRightChild(getRightChild(r)))

節點和引用

我們第二種表示樹的方式——節點和引用。在這種情況下,我們將定義具有根,以及左右子樹屬性的類。由於這種表示更緊密地結合了面向物件的方式,我們將繼續使用這種表示完成本章的其餘部分。

使用節點和引用,我們認為該樹的結構類似於圖 2 所示。

圖 2:使用節點和引用表示簡單樹

我們將開始用簡單的節點和引用的類定義如Listing 4 所示。重要的是要記住這種表示的是左右子樹引用的是其他二叉樹的例項。例如,當我們插入一個新的左子節點到樹上時,我們建立了二叉樹的另一個例項,修改了根節點的self leftChild使之指向新的樹。

Listing 4

12345 classBinaryTree:def __init__(self,rootObj):self.key=rootObjself.leftChild=Noneself.rightChild=None

注意Listing 4 中,建構函式需要得到一些型別的物件儲存在根中。就像你可以在列表中儲存你喜歡的任何一種型別,樹的根物件可以指向任何一種型別。對於我們之前的例子中,我們將儲存節點設為根值的名稱。使用節點和引用來表示圖 2 中的樹,我們將建立二叉樹類的 6 個例項。

接下來讓我們看一下我們需要構建的根節點以外的函式。為了新增左子節點,我們將建立一個新的二叉樹,並設定根的左屬性以指向這個新物件。insertLeft的程式碼Listing 5 所示。

Listing 5

1234567 def insertLeft(self,newNode):ifself.leftChild==None:self.leftChild=BinaryTree(newNode)else:t=BinaryTree(newNode)t.leftChild=self.leftChildself.leftChild=t

我們必須考慮兩種情況進行插入。第一種情況是,沒有左子節點。當沒有左子節點時,將新節點新增即可。第二種情況的特徵是,當前存在左子節點。在第二種情況下,我們插入一個節點並將之前的子節點降一級。第二種情況是由else語句在Listing 5的第 4 行進行處理。

對於insertRight的程式碼必須考慮一個對稱的情況。要麼沒有右子節點,要麼我們必須插入根和現有的右子節點之間。插入程式碼Listing 6 所示。

Listing 6

1234567 def insertRight(self,newNode):ifself.rightChild==None:self.rightChild=BinaryTree(newNode)else:t=BinaryTree(newNode)t.rightChild=self.rightChildself.rightChild=t

為了完成一個簡單的二叉樹資料結構的定義,我們寫出訪問(參見Listing 7)左右子節點和根值的方法。

Listing 7

1234567891011 def getRightChild(self):returnself.rightChilddef getLeftChild(self):returnself.leftChilddef setRootVal(self,obj):self.key=objdef getRootVal(self):returnself.key

既然我們已經有了所有建立和操作二叉樹的方法,讓我們再進一步檢查它的結構。讓我們把每一個節點比作一個簡單的樹的根,並新增節點 B 和 C 作為子節點。 下面的程式碼就是建立樹,並存儲一些鍵值,為左右子節點賦值。注意,左右子節點和根都是同一個二叉樹類的不同物件。正如我們之前樹的定義中說的,我們能夠把一個二叉樹的任何子節點當成二叉樹來做處理。
1234567891011121314151617181920212223

相關推薦

Python資料結構——實現

在用巢狀列表表示樹時,我們使用 Python 的列表來編寫這些函式。雖然把介面寫成列表的一系列方法與我們已實現其他的抽象資料型別有些不同,但這樣做比較有意思,因為它為我們提供一個簡單、可以直接檢視的遞迴資料結構。在列表實現樹時,我們將儲存根節點作為列表的第一個元素的值。列表的第二個元素的本身是一個表示左子樹

Python資料結構--遍歷演算法

1 ''' 2 遍歷是訪問樹的所有節點的過程,也可以列印它們的值。 因為所有節點都通過邊(連結)連線,所以始終從根(頭)節點開始。 3 也就是說,我們不能隨機訪問樹中的一個節點。 這裡介紹三種方式來遍歷一棵樹 -順序遍歷 -前序遍歷 -後序遍歷 4 ''' 5 6 7 class No

Python資料結構——的基本概念

我們已經學過了像棧和佇列這樣的線性資料結構,同時我們對遞迴也有了一定的瞭解,現在讓我們來看看另一種常見的資料結構——樹(Tree)。樹在計算機科學裡應用廣泛,包括作業系統,圖形學,資料庫和計算機網路。樹和真正的樹有許多相似的地方,也包括根、樹枝和葉子,它們的不同在於計算機中的樹的根在頂層而它的葉子在底部。

Python資料結構——二叉搜尋實現(下)

搜尋樹實現(續) 最後,我們把注意力轉向二叉搜尋樹中最具挑戰性的方法,刪除一個鍵值(參見Listing 7)。首要任務是要找到搜尋樹中要刪除的節點。如果樹有一個以上的節點,我們使用_get方法找到需要刪除的節點。如果樹只有一個節點,這意味著我們要刪除樹的根,但是我們仍然要檢查根的鍵值是否與要刪除的鍵值匹配。

Python資料結構——二叉搜尋實現(上)

二叉搜尋樹 我們已經知道了在一個集合中獲取鍵值對的兩種不同的方法。回憶一下這些集合是如何實現ADT(抽象資料型別)MAP的。我們討論兩種ADT MAP的實現方式,基於列表的二分查詢和雜湊表。在這一節中,我們將要學習二叉搜尋樹,這是另一種鍵指向值的Map集合,在這種情況下我們不用

Python資料結構——AVL實現

遞迴呼叫已到達樹的根。 父節點的平衡因子已調整為零。一旦子樹平衡因子為零,那麼父節點的平衡因子不會發生改變。 我們將實現 AVL 樹的子類BinarySearchTree。首先,我們將重寫_put方法,並寫一個新的輔助方法updateBalance。這些方法如Listing 1 所示。除了第 7 行和第

資料結構-以及深度、廣度優先遍歷(遞迴和非遞迴,python實現

前面我們介紹了佇列、堆疊、連結串列,你親自動手實踐了嗎?今天我們來到了樹的部分,樹在資料結構中是非常重要的一部分,樹的應用有很多很多,樹的種類也有很多很多,今天我們就先來建立一個普通的樹。其他各種各樣的樹將來我將會一一為大家介紹,記得關注我的文章哦~ 首先,樹的形狀就是類似這個樣子的: 它最頂上面的點叫做

Python-資料結構與演算法(十一、字典(對映)——基於兩種不同的底層實現

保證一週更兩篇吧,以此來督促自己好好的學習!程式碼的很多地方我都給予了詳細的解釋,幫助理解。好了,幹就完了~加油! 宣告:本python資料結構與演算法是imooc上liuyubobobo老師java資料結構的python改寫,並添加了一些自己的理解和新的東西,liuyubobobo

python資料結構之KMP演算法的實現

我相信網上已經有很多關於KMP演算法的講解,大致都是關於部分匹配表的實現思路和作用,還有就是目標串的下標不變,僅改變模式串的下標來進行匹配,確實用KMP演算法,當目標串很大模式串很小時,其效率很高的,但都是相對而言。至於對於部分匹配表的作用以及實現思路,建議看一下這篇文章寫的是比較易懂的

python 資料結構與演算法 day05 二叉的深度優先遍歷(縱向)

1. 二叉樹深度優先遍歷三種方式   不同於樹的廣度優先遍歷(一層一層的走,同一層從左到右走完開始走下一層的橫向遍歷方式),深度優先遍歷是一條路走到黑,然後再走下一條;    先序遍歷:根節點--左子節點---右子節點(先從根節點開始,走左子樹,對這個左子樹依然按照根節點

Python資料結構——二叉排序

二叉排序樹的過程主要是:二叉樹的構建和遍歷。 當樹構建好後,對樹進行中序遍歷(左中右),即可得到,對資料從小到大排序的結果。 如果對樹進行“右中左遍歷”,則可以得到,對資料從大到小排序的結果 # -*- coding:utf-8 -*- # file: pySort.py #

Python資料結構——二叉的遍歷(先根,中根,後根)

先序遍歷:根左右 中序遍歷:左根右 後序遍歷:左右根 # -*- coding:utf-8 -*- # file: TreeTraversal.py # class BTree: # 二叉樹節點 def __init__(self, value):

Python資料結構——二叉堆的實現

優先佇列的二叉堆實現 在前面的章節裡我們學習了“先進先出”(FIFO)的資料結構:佇列(Queue)。佇列有一種變體叫做“優先佇列”(Priority Queue)。優先佇列的出隊(Dequeue)操作和佇列一樣,都是從隊首出隊。但在優先佇列的內部,元素的次序卻是由“優先順序”來決定:高優先順序

python資料結構之二叉

這裡用python 實現了二叉樹 # Definition for a binary tree node. class TreeNode: def __init__(self, x): self.val = x self.left =

Python-資料結構與演算法(九、二分搜尋

保證一週更兩篇吧,以此來督促自己好好的學習!程式碼的很多地方我都給予了詳細的解釋,幫助理解。好了,幹就完了~加油! 宣告:本python資料結構與演算法是imooc上liuyubobobo老師java資料結構的python改寫,並添加了一些自己的理解和新的東西

Python資料結構——解析的遍歷

解析樹 完成樹的實現之後,現在我們來看一個例子,告訴你怎麼樣利用樹去解決一些實際問題。在這個章節,我們來研究解析樹。解析樹常常用於真實世界的結構表示,例如句子或數學表示式。 圖 1:一個簡單句的解析樹 圖 1 顯示了一個簡單句的層級結構。將一個句子表示為一個樹,能使我們通過利用子樹來處理句子中的每個獨立的

資料結構::如何實現哈夫曼

【哈夫曼樹的定義】:  哈夫曼樹又稱為最優二叉樹,它是加權路徑最短的二叉樹。     不同於普通的二叉樹,它的每個節點都有相應的權值,當我們構建的時候最終離根節點遠的節點權重小,反之就比較大。 【

資料結構實現(C語言)

1、樹的概念    樹形結構是節點之間以及分支關係定義的層次結構。作為一種重要的非線性結構,樹形結構中一個節點最多隻有一個前驅節點,但是可以有多個後繼節點。2、樹的儲存結構    在計算機中,樹有多種的儲存方式,下面介紹一種動態的“左子/右兄”二叉連結串列表示方法。#incl

Python資料結構——AVL的基本概念

平衡二叉搜尋樹 在上一節中我們討論了建立一個二叉搜尋樹。我們知道,當樹變得不平衡時get和put操作會使二叉搜尋樹的效能降低到O(n)。在這一節中我們將看到一種特殊的二叉搜尋樹,它可以自動進行調整,以確保樹隨時都保持平衡。這種樹被稱為AVL樹,命名源於其發明者:G.M. Ade

面試寶典之python資料結構---列表,棧與佇列,連結串列,,字典

Python基本資料結構 一、線性表 線性表是最常用且最簡單的一種資料結構,它是n個數據元素的有限序列。 實現線性表的方式一般有兩種,一種是使用陣列儲存線性表的元素,即用一組連續的儲存單元依次儲存線性表的資料元素。另一種是使用連結串列儲存線性表的元素,