順序存儲一棵二叉樹時,首先對該樹中的每一個結點進行編號,而後以各結點的編號爲下標,把各結點的值對應存儲到一個一位數組中。每一個結點的編號與等深度的滿二叉樹中對應結點的編號相等,即樹根結點的編號爲1,接着按照從上到下和從左到右的次序,若一個結點的編號爲i,則左、右孩子的編號分別爲2i和2i+1。如圖,各結點上方的數字就是該結點的編號。算法
假設分別採用一維數組data1和data2來順序存儲上圖的兩棵二叉樹,則兩數組中各元素的值以下圖所示。數組
在二叉樹的順序存儲結構中,各結點之間的關係是經過下標計算出來的,所以訪問每個結點的雙親和左、右孩子都很是方便。如對於編號爲i的結點,其雙親結點的下標爲⌊i/2⌋,若存在左孩子,則左孩子結點的下標爲2i,若存在右孩子,則右孩子結點的下標爲2i+1。spa
二叉樹的順序存儲結構對於存儲徹底二叉樹是合適的,它可以充分利用存儲空間,但對於通常二叉樹,特別是對於那些單支結點較多的二叉樹來講是很不合適的,由於可能只有少數存儲位置被利用,而多數或絕大多數的存儲位置空間着。指針
在二叉樹的連接存儲中,一般採用的方法是,在每一個結點中設置3個域:值域、左指針域和右指針域。其結點結構爲:code
連接存儲的另外一種方法是:在上面的結點結構中再增長一個parent指針域,用來指向其雙親結點。這種存儲結構既便於查找孩子結點,也便於查找雙親結點,固然也帶來存儲空間的相應增長。blog
同單鏈表相同,二叉鏈表既可由獨立分配的結點連接而成,也可由數組中的元素結點連接而成。class
若採用獨立結點,則結點類型可定義爲:二叉樹
1 struct BTreeNode { 2 ElemType data; 3 BTreeNode* left; 4 BTreeNode* right; 5 };
若採用元素結點,則結點類型可定義爲:遍歷
1 struct ABTreeNode { 2 ElemType data; 3 int left, right; 4 };
元素結點從下標爲1的位置起使用,下標爲0的位置的左指針域一般用來存儲樹根指針,右指針域一般用來存儲空閒鏈表的表頭指針,空閒鏈表由空閒結點的right域連接而成。方法
二叉樹遍歷算法有:前序遍歷、中序遍歷、後序遍歷和按層遍歷。
若將跟結點、左子樹和右子樹分別用D、L和R表述,則前序遍歷順序爲DLR,中序遍歷順序爲LDR,後序遍歷順序爲LRD。
對於上圖二叉樹,
前序遍歷爲:ABCDEFG
中序遍歷爲:CBDAEGF
後序遍歷爲:CDBGFEA
按層遍歷爲:ABECDFG
1 void PreOrder(BTreeNode* BT) { 2 if(BT != NULL) { 3 cout << BT->data << ' '; //訪問根結點 4 PreOrder(BT->left); //前序遍歷左子樹 5 PreOrder(BT->right); //前序遍歷右子樹 6 } 7 }
1 void InOrder(BTreeNode* BT) { 2 if(BT != NULL) { 3 InOrder(BT->left); //中序遍歷左子樹 4 cout << BT->data << ' '; //訪問根結點 5 InOrder(BT->right); //中序遍歷右子樹 6 } 7 }
1 void PostOrder(BTreeNode* BT) { 2 if(BT != NULL) { 3 PostOrder(BT->left); //後序遍歷左子樹 4 PostOrder(BT->right); //後序遍歷右子樹 5 cout << BT->data << ' '; //訪問根結點 6 } 7 }