代碼參考:node
http://blog.csdn.net/iqrocket/article/details/8266365ios
http://blog.csdn.net/luno1/article/details/7951993ide
二叉樹的性質:函數
一、在二叉樹的第 i 層上,至多有 2 i-1 個節點。(i >= 1)
二、深度爲 k 的二叉樹至多有 2k -1 個節點 (k >= 1)
三、對任何一棵二叉樹 T,若是其終端節點數爲 n0, 度爲2 的節點數爲 n2, 則 n0 = n2 +1
證實: 分支線總數是 W, 節點總數是 N, 度爲1的節點是 n1。 W = N -1
W = N -1 = n1 + 2*n2
N = n0 + n1 + n2
=> n0 = n2 + 1測試
四、具備 N 個結點的徹底二叉樹的深度爲【log N】 + 1. (【X】表示不大於X 的最大整數,底是2)spa
證實: 2k-1 -1 < N <= 2k -1
2k-1 <= N < 2k
對兩邊取對數
k -1 <= log N < k k = 【log N】 + 1.net
五、若是對一棵有 N 個結點的徹底二叉樹(其深度爲【log n】+ 1)的結點按層序編號(從第一層到第【log n】+ 1 層,每層從左到右),對任一結點 i (1<= i<=n)有:
a: 若是 i = 1, 則結點 i 是二叉樹的根,無雙親;若是 i>1,則其雙親是結點【i/2】
b: 若是2i > n, 則結點 i 無左孩子(結點 i 爲葉子結點);不然其左孩子是結點 2i;
c: 若是2i+1 > n,則結點 i 無右孩子(結點 i 爲葉子結點);不然其左孩子是結點 2i+1;code
二叉樹類的聲明:包括樹的創建、遞歸遍歷、非遞歸遍歷、結點總數、葉子節點數、樹的高度blog
#include<iostream> #include<stack> #include<queue> using namespace std; template<class T> struct TreeNode { T element; TreeNode* rightNode, *leftNode; }; template<class T> class BinaryTree { public: BinaryTree(); ~BinaryTree(); TreeNode<T>*GetRoot(); //遞歸遍歷 void PreOrder(TreeNode<T>*); void Inorder(TreeNode<T>*); void PostOrder(TreeNode<T>*); //非遞歸遍歷 void NonPreOrder(TreeNode<T>*); void NonInOrder(TreeNode<T>*); void NonPostOrder(TreeNode<T>*); void LevelOrder(TreeNode<T>*); //層序遍歷 int BTreeSize(TreeNode<T>*); //計算樹的節點總數 int BTreeLeaves(TreeNode<T>*); //計算樹的葉子數 int BTreeHight(TreeNode<T>*); //計算樹的高度 private: TreeNode<T>* root; TreeNode<T>*Create(); void Release(TreeNode<T>*root); };
二叉樹中函數的實現:遞歸
//獲取根結點 template<class T> TreeNode<T>* BinaryTree<T>::GetRoot() { return root; } //構造函數 template<class T> BinaryTree<T>::BinaryTree() { root = new TreeNode<T>; root = Create(); } //析構函數 template<class T> BinaryTree<T>::~BinaryTree() { Release(root); delete root; } //生成樹,採用先序遍歷的方式生成樹 template<class T> TreeNode<T>* BinaryTree<T>::Create() { char elem; cin >> elem; TreeNode<T>* node; if (elem == '#') node = NULL; else { node = new TreeNode<T>; node->element = elem; node->leftNode = Create(); node->rightNode = Create(); } return node; } //刪除結點 template<class T> void BinaryTree<T>::Release(TreeNode<T>*root) { if (root != NULL) { Release(root->leftNode); Release(root->rightNode); } } //前序遍歷 template<class T> void BinaryTree<T>::PreOrder(TreeNode<T>*node) { if (node == NULL) return; else { cout << node->element<<" "; PreOrder(node->leftNode); PreOrder(node->rightNode); } } //中序遍歷 template<class T> void BinaryTree<T>::Inorder(TreeNode<T>*node) { if (node == NULL) return; else { Inorder(node->leftNode); cout << node->element << " "; Inorder(node->rightNode); } } //後序遍歷 template<class T> void BinaryTree<T>::PostOrder(TreeNode<T>*node) { if (node == NULL) return; else { PostOrder(node->leftNode); PostOrder(node->rightNode); cout << node->element<<" "; } } template<class T> void BinaryTree<T>::NonPreOrder(TreeNode<T>*node) { //前序遍歷的順序是:根左右 stack<TreeNode<T>*>s; TreeNode<T>*pNode = node; while (pNode != NULL || !s.empty()) { while (pNode != NULL) //當pNode非空時, 一、打印根節點,並把根結點壓入棧 二、將左葉子節點複製給 pNode, { cout << pNode->element << " "; s.push(pNode); pNode = pNode->leftNode; } if (!s.empty()) //當棧非空時,將棧頂元素的右葉子複製給 pNode { pNode = s.top(); s.pop(); pNode = pNode->rightNode; } } } //非遞歸中序遍歷 template<class T> void BinaryTree<T>::NonInOrder(TreeNode<T>*node) { stack<TreeNode<T>*>s; TreeNode<T>*pNode = node; while ( pNode != NULL || !s.empty()) { while (pNode != NULL) { s.push(pNode); pNode = pNode->leftNode; } if (!s.empty()) { pNode = s.top(); cout << pNode->element << " "; s.pop(); pNode = pNode->rightNode; } } } //非遞歸後序遍歷 template<class T> void BinaryTree<T>::NonPostOrder(TreeNode<T>*node) { //遍歷順序:左右跟 /* 對任一結點,先將其入棧,訪問該結點的左節點和右節點。若左右結點均訪問過,則訪問該節點 */ if (node == NULL) return; stack<TreeNode<T>*>s; queue<TreeNode<T>*>q; s.push(node); //將根結點壓入棧 TreeNode<T>*pre = NULL; TreeNode<T>* cur; while (!s.empty()) { cur = s.top(); //上一次訪問的是當前節點的左子樹 if (cur->leftNode == NULL&&cur->rightNode == NULL || (pre != NULL) && (pre == cur->leftNode || pre == cur->rightNode)) { cout << cur->element << " "; s.pop(); pre = cur; } else { if (cur->rightNode) s.push(cur->rightNode); if (cur->leftNode) s.push(cur->leftNode); } } } //層序遍歷 template<class T> void BinaryTree<T>::LevelOrder(TreeNode<T>*node) //層序遍歷 { TreeNode<T>*pNode = node; if (pNode == NULL) return; //將每次層的葉子節點進入隊列 queue<TreeNode<T>*>q; q.push(pNode); while (!q.empty()) { pNode = q.front(); cout << pNode->element << " "; q.pop(); if (pNode->leftNode) q.push(pNode->leftNode); if (pNode->rightNode) q.push(pNode->rightNode); } } //求二叉樹結點個數的函數 template<class T> int BinaryTree<T>::BTreeSize(TreeNode<T>* node) { //二叉樹的結點個數爲左右子樹的高度之和再+1 if (node == NULL) return 0; else return 1 + BTreeSize(node->leftNode) + BTreeSize(node->rightNode); } //求二叉樹葉子結點個數的函數 template<class T> int BinaryTree<T>::BTreeLeaves(TreeNode<T>* node) { //當爲空時,返回0;當找到葉子時返回1 if (node == NULL) return 0; else if (node->leftNode == 0 && node->rightNode == 0) return 1; else return BTreeLeaves(node->leftNode) + BTreeLeaves(node->rightNode); } //求二叉樹高度的函數 template<class T> int BinaryTree<T>::BTreeHight(TreeNode<T>* node) { if (node == NULL) return 0; else { //二叉樹的高度爲左右子樹的最大者+1 int lHei = BTreeHight(node->leftNode); int rHei = BTreeHight(node->rightNode); return (lHei>rHei) ? lHei + 1 : rHei + 1; } }
測試代碼:輸入: A B # D # C # #。 樹的形式爲:
#include<iostream> #include<string> #include"BinaryTree.cpp" using namespace std; int main() { cout << "請輸入節點" << endl; // A B # D # C # # BinaryTree<char>my_tree; my_tree.PreOrder(my_tree.GetRoot()); cout << "遞歸先序遍歷" << endl; my_tree.Inorder(my_tree.GetRoot()); cout << "遞歸中序遍歷" << endl; my_tree.PostOrder(my_tree.GetRoot()); cout << "遞歸後序遍歷" << endl; my_tree.LevelOrder(my_tree.GetRoot()); cout << "層序遍歷" << endl; my_tree.NonPreOrder(my_tree.GetRoot()); cout << "非遞歸先序遍歷" << endl; my_tree.NonInOrder(my_tree.GetRoot()); cout << "非遞歸中序遍歷" << endl; my_tree.NonPostOrder(my_tree.GetRoot()); cout << "非遞歸後序遍歷" << endl; cout << "二叉樹的節點數是: " << my_tree.BTreeSize(my_tree.GetRoot()) << endl; cout << "二叉樹的葉子數是: " << my_tree.BTreeLeaves(my_tree.GetRoot()) << endl; cout << "二叉樹的高度是: " << my_tree.BTreeHight(my_tree.GetRoot()) << endl; cout << endl; cout << "hello world" << endl; system("pause"); return 0; }