目錄node
遍歷過程爲:python
/* c語言實現 */ // 定義結點 typedef struct TreeNode *BinTree; typedef BinTree Position; struct TreeNode{ ElementType Data; BinTree Left; BinTree Right; } void PreOrderTraversal (BinTree BT) { if (BT) { printf("%d", BT->Data); PreOrderTraversal(BT->Left); PreOrderTraversal(BT->Right); } }
# python語言實現 # 定義結點 class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None def preorder(root): if not root: return print(root.val) preorder(root.left) preorder(root.right)
先序遍歷:A (B D F E)(C G H I)算法
遍歷過程爲:app
/* c語言實現 */ void InOrderTraversal (BinTree BT) { if (BT) { InOrderTraversal(BT->Left); printf("%d", BT->Data); InOrderTracersal(BT->Right); } }
# python語言實現 def inorder(root): if not root: return inorder(root.left) print(root.val) inorder(root.right)
中序遍歷:(D B E F)A(G H C I)函數
遍歷過程爲:post
/* c語言實現 */ void PostOrderTraversal (BinTree BT) { if (BT) { PostOrderTraversal(BT->Left); PostORderTraversal(BT->Right); printf("%d", BT->Data); } }
# python語言實現 def postorder(root): if not root: return postorder(root.left) postorder(root.right) print(root.val)
後序遍歷:(D E F B)(H G I C)Aspa
先序、中序和後序遍歷過程:遍歷過程當中通過結點的路線同樣,只是訪問各結點的時機不一樣。指針
圖中在從入口到出口的曲線上用×、☆、△三種符號分別標記出了先序、中序和後序訪問各結點的時刻。code
非遞歸算法實現的基本思路:使用堆棧對象
/* c語言實現 */ void InOrderTraversal(BinTree BT) { BinTree T = BT; Stack S = CreateStack(MaxSize); // 建立並初始化堆棧S while (T || !IsEmpty(S)){ while (T) { // 一直向左並將沿途結點壓入堆棧 Push(S, T); T = T->Left; } if (!IsEmpty(S)){ T = Pop(S); // 結點彈出堆棧 printf("%5d", T->Data); // (訪問)打印結點 T = T->Right; // 轉向右子樹 } } }
# python語言實現 def inorder(root): stack = [] while stack or root: while root: stack.append(root) root = root.left root = stack.pop() print(root.val) root = root.right
/* c語言實現 */ void InOrderTraversal(BinTree BT) { BinTree T = BT; Stack S = CreateStack(MaxSize); // 建立並初始化堆棧S while (T || !IsEmpty(s)){ while (T) { // 一直向左並將沿途結點壓入堆棧 printf("%5d", T->Data); // (訪問)打印結點 Push(S, T); T = T->Left; } if (!IsEmpty(S)){ T = Pop(S); // 結點彈出堆棧 T = T->Right; // 轉向右子樹 } } }
# python語言實現 def preorder(root): stack = [root] while stack: s = stack.pop() if s: print(s.val) stack.append(s.right) stack.append(s.left)
// c語言實現 // 定義結點 typedef struct TreeNode{ int data; struct TreeNode *lChild; struct TreeNode *rChild; } TreeNode; void postOrder(TreeNode *T){ TreeNode *stack[15]; int top = -1; int flagStack[15]; //記錄每一個節點訪問次數棧 TreeNode *p = T; while(p!=NULL||top!=-1){ if(p!=NULL){ //第一次訪問,flag置1,入棧 stack[++ top] = p; flagStack[top] = 1; p = p->lChild; }else{//(p == NULL) if(flagStack[top] == 1){ //第二次訪問,flag置2,取棧頂元素但不出棧 p = stack[top]; flagStack[top] = 2; p = p->rChild; }else{ //第三次訪問,出棧 p = stack[top --]; printf("%d\t",p->data); //出棧時,訪問輸出 p = NULL; //p置空,以便繼續退棧 } } }
# python語言實現 def postorder(root): stack = [] while stack or root: while root: # 下行循環,直到找到第一個葉子節點 stack.append(root) if root.left: # 能左就左,不能左就右 root = root.left else: root = root.right s = stack.pop() print(s.val) #若是當前節點是上一節點的左子節點,則遍歷右子節點 if stack and s == stack[-1].left: root = stack[-1].right else: root = None
二叉樹遍歷的核心問題:二維結構的線性化。即從結點訪問其左、右兒子結點,訪問左兒子後,若是根結點信息丟失,右兒子結點也會隨之丟失,所以須要一個存儲結構保存暫時不訪問的結點,這個存儲結構能夠爲堆棧,也能夠是隊列。
遍歷從根節點開始,首先將根節點入隊,而後開始執行循環:結點出隊、訪問該結點、其左右兒子入隊。
層序基本過程:先根結點入隊,而後:
/* c語言實現 */ void LevelOrderTraversal (BinTree BT) { Queue Q; BinTree T; if (!BT) return; // 如果空樹則直接返回 Q = CreateQueue(MaxSize); // 建立並初始化隊列Q AddQ(Q, BT); while (!IsEmptyQ(Q)) { T = DeleteQ(Q); printf("%d\n", T->Data); // 訪問取出隊列的結點 if (T->Left) AddQ(Q, T->Left); if (T->Right) AddQ(Q, T->Right); } }
# python語言實現 def BFS(root): queue = [root] while queue: n = len(queue) for i in range(n): q = queue.pop(0) if q: print(q.val) queue.append(q.left if q.left else None) queue.append(q.right if q.right else None)
在二叉樹的遍歷算法中檢測結點的左右子樹是否都爲空。
/* c語言實現 */ void PreOrderPrintLeaves (BinTree BT) { if (BT) { if (!BT->Left && !BT->Right) printf("%d", BT->Data); PreOrderPrintLeaves(BT->Left); PreOrderPrintLeaves(BT->Right); } }
# python語言實現 class Node(object): """節點類""" def __init__(self, val=-1, left=None, right=None): self.val = val self.left = left self.right = right class Tree(object): """樹類""" def __init__(self): self.root = Node() self.queue = [] # 使用列表模擬隊列 def add(self, val): """爲樹添加節點""" node = Node(val) if self.root.val == -1: # 若是樹是空的,則對根節點賦值 self.root = node self.queue.append(self.root) else: treeNode = self.queue[0] # 此結點的子樹尚未齊。 if treeNode.left == None: treeNode.left = node # 左子樹變成節點(初始此節點左右都是None) self.queue.append(treeNode.left) else: treeNode.right = node self.queue.append(treeNode.right) self.queue.pop(0) # 若是該結點存在右子樹,將此結點丟棄。 def leave(self, root): if root == None: return 0 elif root.left == None and root.right == None: return 1 else: return (self.leave(root.left) + self.leave(root.right)) # 遞歸遍歷全部左子樹右子樹,當左右都爲None時纔算1 if __name__ == '__main__': """主函數""" vals = range(10) # 生成十個數據做爲樹節點 tree = Tree() # 新建一個樹對象 for val in vals: tree.add(val) # 逐個添加樹的節點 print('葉子節點個數:', tree.leave(tree.root))
/* c語言實現 */ int PostOrderGetHeight(BinTree BT) { int HL, HR, MaxH; if (BT) { HL = PostOrderGetHeight(BT->Left); // 求左子樹的深度 HR = PostOrderGetHeight(BT->Right); // 求右子樹的深度 MaxH = (HL > HR) ? HL : HR; // 取左右子樹較大的深度 return (MaxH + 1); // 返回樹的深度 } else return 0; // 空樹深度爲0 }
# python實現 # 基本思路就是遞歸,當前樹的最大深度等於(1+max(左子樹最大深度,右子樹最大深度))。 def maxDepth(root): if not root: return 0 return 1+max(maxDepth(root.left), maxDepth(root.right))
三種遍歷能夠獲得三種不一樣的訪問結果:
++a*bc*+*defg
a+b*c+d*e+f*g
abc*+de*f+g*+
已知三種遍歷中的任意兩種遍歷序列,不能惟一肯定一顆二叉樹,若是兩種遍歷序列中有中序遍歷,則能夠惟一肯定一顆二叉樹。
對於給出的先序遍歷序列爲:AB
和後序遍歷序列:BA
,可能有以下兩種狀況:
先序和中序遍歷序列來肯定一顆二叉樹
相似地,後序和中序遍歷序列也能夠肯定一顆二叉樹。