二叉樹的構建要注意與鏈式表的區別,二叉樹這裏的構建十分低級,每個樹只是構建了一個單一的二叉樹節點,總體來看是有下向上構建的。用戶需要手動去構建自己需要的樹,而不是直接去插入數據就到二叉樹中了,因爲不是鏈式結構的單一,二叉樹十分豐富的。
提一下遍歷:
迭代的方式遍歷十分簡單。先序、中序、後序遍歷都只是針對根節點。比如中序,就是先遍歷左子樹-->根節點-->右子樹。(根節點在中間)
/* 1) 樹的基本概念: 度:說白了就是節點擁有的子分支數 葉子節點:說白了就是度爲0的節點 雙親:說白了就是父親節點 層次:約定根節點爲1,以後的子節點依次遞增 高度:說白了就是層次最大的數 2)二叉樹的類型 1>滿二叉樹:葉子必須位於最後一層,並且其他節點度爲2 2>擴充二叉樹:除葉子節點外,其他節點度爲2 1,擴充二叉樹的最大特點在於他的外路徑長度=內路徑的長度+2*非葉節點的數目 2,典型應用就是哈弗曼編碼 3>完全二叉樹: 只有最後兩層的節點的度能小於2,並且最後1層的葉子節點必須靠左邊。 1,將整個完全二叉樹依照從左到右,從上到下的進行0-->n進行編號,若子節點序號爲i,則父節點爲(i-1)/2。 2,典型的應用大小堆的實現。 4>其他類型二叉樹 3)森林與二叉樹的互轉 */ template <class T> struct BTNode { BTNode<T> *_lChild, *_rChild; T element; BTNode(const T &e) { element = e; _lChild = _rChild = NULL; } }; template <class T> class JBBinaryTree { public: JBBinaryTree(); ~JBBinaryTree(); BTNode<T> *_root; //清空當前樹 void clear(); //獲取到當前元素 T getElement() const; //判斷當前二叉樹是不是空二叉樹 bool isEmpty() const; //構建一棵數 void makeTree(const T &x,JBBinaryTree<T> *left,JBBinaryTree<T> *right); //拆除一棵數 void breakTree(T &x,JBBinaryTree*left,JBBinaryTree*right); //前序遍歷 統一採用遞歸遍歷 void preOrder(BTNode<T> *t); //中序遍歷 void inOrder(BTNode<T> *t); //後序遍歷 void postOrder(BTNode<T> *t); }; template <class T> JBBinaryTree<T>::JBBinaryTree() { _root = NULL; } template<class T> JBBinaryTree<T>::~JBBinaryTree() { clear(); } template<class T> void JBBinaryTree<T>::clear() { if(_root==NULL){
return;
}
delete _root; _root = NULL; } template<class T> T JBBinaryTree<T>::getElement() const { if (isEmpty()) { reurn NULL; } return _root->element; } template<class T> bool JBBinaryTree<T>::isEmpty() const { return _root == NULL; } template<class T> void JBBinaryTree<T>::makeTree(const T &x, JBBinaryTree<T> *left, JBBinaryTree<T> *right) { if (_root)return;//如果根節點不爲空 就直接return 這實際上讓用戶操作起來十分不方便 不能自己構建自己 必須重一個節點 _root = new BTNode<T>(x);//實例化二叉樹根節點 _root->_lChild = left->_root;//讓左指針指向左子樹的根節點 _root->_rChild = right->_root;//讓右指針指向右子樹的根節點 left->_root = right->_root = NULL; } template<class T> void JBBinaryTree<T>::breakTree(T &x, JBBinaryTree*left, JBBinaryTree*right) { if (!_root || left == right || left->_root || right->_root) { //若此樹本身就是空的,或則用於承接的左右樹本身一樣,或則用於承接的左子樹不爲空都直接退出 return; } x = _root->element;//將這個樹的根節點的元素域轉移走 left->_root = _root->_lChild;//將左子樹單獨拆成一棵樹 right->_root = _root->_rChild;//將右子樹單獨拆成一棵樹 clear(); } template<class T> void JBBinaryTree<T>::preOrder(BTNode<T> *t) { if (t) { printf("%d",t->element); preOrder(t->_lChild); preOrder(t->_rChild); } } template<class T> void JBBinaryTree<T>::inOrder(BTNode<T> *t) { if (t) { inOrder(t->_lChild); printf("%d",t->element); inOrder(t->_rChild); } } template<class T> void JBBinaryTree<T>::postOrder(BTNode<T> *t) { if (t) { postOrder(t->_lChild); postOrder(t->_rChild); printf("%d",t->element); } }
下面看一下主程序
#include "stdafx.h" #include"stdlib.h" #include"JBQueue.h" #include"JBStack.h" #include"JBBinaryTree.h" int main() { { JBBinaryTree<int> L,R,a,b,c,d,e; a.makeTree(0,&L,&R); b.makeTree(1,&L,&R); c.makeTree(2,&a,&b); d.makeTree(3,&a,&b); e.makeTree(4,&c,&d); printf("前序遍歷:"); e.preOrder(e._root); printf("\n中序遍歷:"); e.inOrder(e._root); printf("\n後序遍歷:"); e.postOrder(e._root); printf("\n"); } system("pause"); return 0; }
結果: