樹(英語:tree)是一種抽象數據類型(ADT)或是實做這種抽象數據類型的數據結構,用來模擬具備樹狀結構性質的數據集合。它是由n(n>=1)個有限節點組成一個具備層次關係的集合。把它叫作「樹」是由於它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。它具備如下的特色:html
好比說:node
順序存儲:將數據結構存儲在固定的數組中,然在遍歷速度上有必定的優點,但因所佔空間比較大,是非主流二叉樹。二叉樹一般以鏈式存儲。mysql
鏈式存儲:算法
因爲對節點的個數沒法掌握,常見樹的存儲表示都轉換成二叉樹進行處理,子節點個數最多爲2sql
1.xml,html等,那麼編寫這些東西的解析器的時候,不可避免用到樹
2.路由協議就是使用了樹的算法
3.mysql數據庫索引
4.文件系統的目錄結構
5.因此不少經典的AI算法其實都是樹搜索,此外機器學習中的decision tree也是樹結構數據庫
二叉樹是每一個節點最多有兩個子樹的樹結構。一般子樹被稱做「左子樹」(left subtree)和「右子樹」(right subtree)數組
性質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層有葉子結點,而且葉子結點都是從左到右依次排布,這就是徹底二叉樹。app
(2)滿二叉樹——除了葉結點外每個結點都有左右子葉且葉子結點都處在最底層的二叉樹。機器學習
經過使用Node類中定義三個屬性,分別爲elem自己的值,還有lchild左孩子和rchild右孩子
class Node(object): """節點類""" def __init__(self, elem=-1, lchild=None, rchild=None): self.elem = elem self.lchild = lchild self.rchild = rchild
樹的建立,建立一個樹的類,並給一個root根節點,一開始爲空,隨後添加節點
class Tree(object): """樹類""" def __init__(self, root=None): self.root = root def add(self, elem): """爲樹添加節點""" node = Node(elem) #若是樹是空的,則對根節點賦值 if self.root == None: self.root = node else: queue = [] queue.append(self.root) #對已有的節點進行層次遍歷 while queue: #彈出隊列的第一個元素 cur = queue.pop(0) if cur.lchild == None: cur.lchild = node return elif cur.rchild == None: cur.rchild = node return else: #若是左右子樹都不爲空,加入隊列繼續判斷 queue.append(cur.lchild) queue.append(cur.rchild)
樹的遍歷是樹的一種重要的運算。所謂遍歷是指對樹中全部結點的信息的訪問,即依次對樹中每一個結點訪問一次且僅訪問一次,咱們把這種對全部節點的訪問稱爲遍歷(traversal)。那麼樹的兩種重要的遍歷模式是深度優先遍歷和廣度優先遍歷,深度優先通常用遞歸,廣度優先通常用隊列。通常狀況下能用遞歸實現的算法大部分也能用堆棧來實現。
對於一顆二叉樹,深度優先搜索(Depth First Search)是沿着樹的深度遍歷樹的節點,儘量深的搜索樹的分支。
那麼深度遍歷有重要的三種方法。這三種方式常被用於訪問樹的節點,它們之間的不一樣在於訪問每一個節點的次序不一樣。這三種遍歷分別叫作先序遍歷(preorder),中序遍歷(inorder)和後序遍歷(postorder)。咱們來給出它們的詳細定義,而後舉例看看它們的應用。
def preorder(self, root): """遞歸實現先序遍歷""" if root == None: return print root.elem self.preorder(root.lchild) self.preorder(root.rchild)
def inorder(self, root): """遞歸實現中序遍歷""" if root == None: return self.inorder(root.lchild) print root.elem self.inorder(root.rchild)
def postorder(self, root): """遞歸實現後續遍歷""" if root == None: return self.postorder(root.lchild) self.postorder(root.rchild) print root.elem
從樹的root開始,從上到下從從左到右遍歷整個樹的節點
def breadth_travel(self, root): """利用隊列實現樹的層次遍歷""" if root == None: return queue = [] queue.append(root) while queue: node = queue.pop(0) print node.elem, if node.lchild != None: queue.append(node.lchild) if node.rchild != None: queue.append(node.rchild)