二叉樹(建立、遍歷、樹的最大深度和最小深度)
樹的引出最初是由二分查詢的原理引出來的,一般順序查詢演算法的複雜度為O(N),而一般二分查詢的複雜度為logN
一個二分查詢演算法可以用一顆查詢樹來表示,樹的根結點為順序陣列的中點,這樣依次查詢效率等同於二分查詢演算法
一般的樹用陣列表示或連結串列表示都會造成空間的浪費,而由於一般的樹可以通過兄弟兒子表示法將一般樹轉換為二叉樹
因此對樹的研究主要針對是針對二叉樹的研究
二叉樹可以分為一般二叉樹,完全二叉樹和完美二叉樹
1 二叉樹的儲存:
陣列:
這需要將二叉樹填充為完全二叉樹,並按編號儲存在陣列中,並根據編號左孩子=父節點*2,右孩子=父節點*2+1,父節點=[子節點/2]的確定層次關係
而這對於非完全二叉樹會造成一定的資源浪費
連結串列:
一個節點包含一個數據和一個左指標和右指標,依然會有一些浪費
2 二叉樹的遍歷:先序/中序/後序----遍歷的核心問題為:二維結構的線性化
遞迴:
方法較簡單,其實遞迴的實現是依靠棧
如中序遍歷:
(1)中序遍歷其左子樹
(2)訪問根節點
(3)中序遍歷其右子樹
結論:以上三種遍歷方法都有一個連通的遍歷路徑,三種遍歷過程經過的路線一樣,只是訪問節點的時機不同,由此引出堆疊實現遍歷的方法:
堆疊:
如中序遍歷的堆疊實現方法:
--遇到一個節點,就把它壓棧,並去遍歷它的左子樹;
--當左子樹遍歷結束後,從棧頂彈出一個結點,並訪問它
--然後按照這個節點的右指標再去中序遍歷該節點的右子樹。
其他遍歷方法類似
具體程式碼參考網上
接下來我們利用連結串列來實現一個二叉樹,其實一般的二叉樹用處並不大,後面會引申出二叉搜尋樹,紅黑樹,堆等。。再此我們只需要掌握如何對二叉樹進行遍歷,首先我們用前序遍歷的方法建立一個二叉樹,然後研究其遍歷方法(遞迴),只給出了中序遍歷,其他遍歷方法類似,交換一下順序即可。
另外,還需要了解一些其他對樹的操作,再此舉一個《劍指offer》上的一個筆試題,即給出一個樹,求出樹的最大深度和最小深度。
#include <iostream> using namespace std; typedef char elemtype; typedef struct TreeNode{ elemtype val; struct TreeNode *left; struct TreeNode *right; TreeNode(elemtype x) : val(x),left(NULL),right(NULL){} }Node, *Tree; Tree creatTree() { elemtype x; Node *node; cin >> x; if(x == -1) node = NULL; else { node = new Node(x); node->left = creatTree(); node->right = creatTree(); } return node; } int maxDepth(Tree T) { int DL, DR, Dmax; if(T) { DL = maxDepth(T->left); DR = maxDepth(T->right); Dmax = (DL<DR)?DR : DL; return (Dmax+1); } else return 0; } int minDepth(Tree T) { int DL, DR, Dmin; if(T) { if(T->left == NULL) return minDepth(T->right) + 1; if(T->right == NULL) return minDepth(T->left) + 1; DL = minDepth(T->left); DR = minDepth(T->right); Dmin = (DL>DR)?DR : DL; return (Dmin+1); } else return 0; } void inorderTraverse(Tree T) { if(T) { cout << T->val << " "; inorderTraverse(T->left); inorderTraverse(T->right); } } int main() { Tree tree; tree = creatTree(); inorderTraverse(tree); cout << endl; cout << "minDepth:" << minDepth(tree) << endl; cout << "maxDepth:" << maxDepth(tree) << endl; return 0; }