數據結構—徹底二叉樹

 


 

上篇博客介紹了一種非線性結構—普通樹 的含義以及一些特性,本文將介紹二叉樹滿二叉樹以及徹底二叉樹的一些特性及實現。ios

首先,什麼是二叉樹?數組

二叉樹,是度爲二的樹,二叉樹的每個節點最多只有二個子節點,且兩個子節點有序app

      

二叉樹的重要特性:測試

1.二叉樹的第i層上節點數最多2n-1spa

2.高度爲k的二叉樹中,最多有2k-1個節點。code

3.在任意一棵二叉樹中,若是終端節點的度爲n,度爲2的節點數爲m,則n=m+1。blog

4.二叉樹的子樹有左右之分,順序不能顛倒。內存

5.若採用連續儲存的方式存放二叉樹,則節點下標之間的關係:ci

  若某個節點的下標爲 i ,則這個節點的父節點的下標爲 i / 2。get

  若某個節點下標爲 i ,且節點的度爲2,則這個節點的左子節點的下標爲 2 * i + 1 ,右子節點的下標爲 2 * i + 2 。

 

滿二叉樹:樹最後一層沒有任何子節點,其他每一層的全部節點都有2個子節點。

滿二叉樹的性質:

1.滿二叉樹的第i層的節點數爲2n-1個。

2.深度爲k的滿二叉樹必有2k-1個節點 ,葉子數爲2k-1

3.滿二叉樹中不存在度爲1的節點,每個分支點中都兩棵深度相同的子樹,且葉子節點都在最底層。

4.具備n個節點的滿二叉樹的深度爲log2(n+1)。

 

徹底二叉樹:若是二叉樹的深度爲k,則除第k層外其他全部層節點的度都爲2,且葉子節點從左到右依次存在。也便是,將滿二叉樹的最後一層從左到右依次刪除若干節點就獲得徹底二叉樹。滿二叉樹是一棵特殊的徹底二叉樹,但徹底二叉樹不必定是滿二叉樹。

   

徹底二叉樹的性質:

1.滿二叉樹是一棵特殊的徹底二叉樹,但徹底二叉樹不必定是滿二叉樹。

2.在滿二叉樹中最下一層,連續刪除若干個節點獲得徹底二叉樹。

3.在徹底二叉樹中,若某個節點沒有左子樹,則必定沒有有子樹。

4.若採用連續儲存的方式存放二叉樹,則節點下標之間的關係(根節點下標爲0):

  若某個節點的下標爲 i ,則這個節點的父節點的下標爲 i / 2。

  若某個節點下標爲 i ,且節點的度爲2,則這個節點的左子節點的下標爲 2 * i + 1 ,右子節點的下標爲 2 * i + 2 。

  除了根節點外,左子樹的下標爲基數,右子樹的下標爲偶數。

   


 

[ MyBinaryTree.h ]

 1 /**********************************************  2  徹底二叉樹類模板 樹組實現  3  2018/3/22  4 /**********************************************/
 5 
 6 
 7 #pragma  once
 8 using namespace std;  9 #include "stdafx.h"
 10 #include <iostream>
 11 
 12 template<class T>
 13 class MyBinaryTree  14 {  15 private:  16     T *pRoot;    //採用動態數組存儲
 17  size_t len;  18  size_t maxSize;  19 
 20     void _sizeExpand();  21     int _find(const T& val);    //在樹中查找元素並返回他在容器中的下標 ,若沒找到返回-1;
 22 
 23 public:  24  MyBinaryTree();  25     ~MyBinaryTree();  26     void clear();    //清空二叉樹
 27     void appand(const T& val);    //在徹底二叉樹尾部追加數據
 28     T& find(const T& findVal);    //在樹中查找元素並返回鈣元素的引用
 29     bool isFind(const T& findVal);  30     void initTree(const T arr[], size_t n);    //傳入一個數組 初始化樹
 31     T& getParent(const T& val);  32     T& getLef/Child(const T& val);  33     T& getRightChild(const T& val);  34 
 35     void prePrint(int index = 0);  36     void posPrint(int index = 0);  37     void inPrint(int index = 0);  38 
 39 
 40 };  41 
 42 template<class T>
 43 void MyBinaryTree<T>::inPrint(int index /*= 0*/)  44 {  45     if (index < (int)len&&index >= 0)  46  {  47         inPrint(2 * index + 1);  48         cout << pRoot[index] << "  ";  49         inPrint(2 * index + 2);  50  }  51 }  52 
 53 template<class T>
 54 void MyBinaryTree<T>::posPrint(int index /* = 0*/)  55 {  56     if (index < (int)len&&index >= 0)  57  {  58         posPrint(2 * index + 1);  59         posPrint(2 * index + 2);  60         cout << pRoot[index] << "  " ;  61  }  62 }  63 
 64 template<class T>
 65 void MyBinaryTree<T>::prePrint(int index /* = 0*/)  66 {  67     if (index < (int)len&&index >= 0)  68  {  69         cout << pRoot[index]<<"  ";  70         prePrint(2 * index + 1);  71         prePrint(2 * index + 2);  72  }  73 }  74 
 75 template<class T>
 76 T& MyBinaryTree<T>::getRightChild(const T& val)  77 {  78     int temp = _find(val);  79     if (temp == -1 || 2 * temp + 2 >= len) //沒有找到元素,或者沒有右子樹
 80  {  81         throw"the data has no rightchild";  82  }  83     return pRoot[2 * temp + 2];  84 }  85 
 86 template<class T>
 87 T& MyBinaryTree<T>::getLeftChild(const T& val)  88 {  89     int temp = _find(val);  90     if (temp == -1 || 2 * temp + 1 >= len) //沒有找到元素,或者沒有左子樹
 91  {  92         throw"the data has no leftchild";  93  }  94     return pRoot[2 * temp + 1];  95 }  96 
 97 template<class T>
 98 T& MyBinaryTree<T>::getParent(const T& val)  99 { 100     int temp=_find(val); 101     if (temp == 0)    //返回0,表示val爲根節點 ,沒有父親
102         cout << "該節點爲根節點,沒有父親" << endl; 103     return -1; 104     if (temp == -1) //沒有找到數據val
105         throw "the data is not in zhe tree"; 106     else
107         return pRoot[(temp - 1) >> 1 ]108 } 109 
110 template<class T>
111 void MyBinaryTree<T>::initTree(const T arr[], size_t n) 112 { 113     clear();    //初始化以前先 判斷樹是否爲空 若不是,則先清空
114     len = n; 115     maxSize = n; 116     pRoot = new T[maxSize]; 117     memcpy_s(pRoot, len*sizeof(T), arr, len*sizeof(T)); 118 
119 // for (size_t i = 0; i < n; i++) 120 // { //循環效率過低,直接內存拷貝 121 //         //_sizeExpand(); 效率低 指直接一次性申請內存 //插入數據以前 先判斷容器是否已滿 122 // pRoot[i] = arr[i]; 123 // len++; 124 // }
125 } 126 
127 template<class T>
128 int MyBinaryTree<T>::_find(const T& val) 129 { 130     for (int i = 0; i < len;++i) 131  { 132         if (public[i] == val) 133             return i; 134  } 135     return -1; 136 } 137 
138 
139 template<class T>
140 bool MyBinaryTree<T>::isFind(const T& findVal) 141 { 142     return  _find(findVal)!=-1; 143 } 144 
145 template<class T>
146 T& MyBinaryTree<T>::find(const T& findVal) 147 { 148     int tempIndex = _find(findVal); 149     if (tempIndex != -1) 150         return pRoot[tempIndex]; 151     else
152         throw "can not find the data"; 153 } 154 
155 template<class T>
156 void MyBinaryTree<T>::_sizeExpand() 157 {//只擴充容量 容器沒存盡是不擴充
158     if (len>=maxSize) 159  { 160         maxSize = maxSize +(( maxSize / 2 > 1) ? maxSize / 2 : 1); 161         T *temp = new T[maxSize]; 162         if (pRoot) 163  { 164             memcpy_s(temp, len*sizeof(T), pRoot, len*sizeof(T)); 165             delete[]pRoot; 166             pRoot = temp; 167  } 168  } 169 } 170 
171 template<class T>
172 void MyBinaryTree<T>::appand(const T& val) 173 { 174  _sizeExpand(); 175     pRoot[len++] = val; 176 } 177 
178 template<class T>
179 void MyBinaryTree<T>::clear() 180 { 181     if (pRoot)    //若樹爲非空 刪除內存空間
182         delete[]pRoot; 183     pRoot = NULL; 184     len = maxSize = 0; 185 } 186 
187 template<class T>
188 MyBinaryTree<T>::~MyBinaryTree() 189 { 190  clear(); 191 } 192 
193 template<class T>
194 MyBinaryTree<T>::MyBinaryTree() 195 { 196     pRoot = NULL; 197     len = maxSize = 0; 198 }

代碼測試:

 

 1 // 徹底二叉樹.cpp : 定義控制檯應用程序的入口點。  2 //  3 
 4 #include "stdafx.h"
 5 #include "MyBinaryTree.h"
 6 #include <iostream>
 7 
 8 using namespace std;  9 
10 int _tmain(int argc, _TCHAR* argv[]) 11 { 12     MyBinaryTree<int> tree; 13     int arr[10]; 14     for (int i = 0; i < 10; ++i) 15         arr[i] = i; 16     cout << "徹底二叉樹初始化並遍歷打印" << endl; 17     tree.initTree(arr, 10); 18     cout << "前序遍歷: " ; 19     tree.prePrint(); cout << endl; 20     cout << "中序遍歷: "; 21     tree.inPrint(); cout << endl; 22     cout << "後序遍歷: " ; 23     tree.posPrint(); cout << endl; 24     cout << "----------------------------------" << endl; 25 
26     cout << "在樹的葉節點增長數據:" << endl; 27     tree.appand(10); 28     tree.appand(11); 29     tree.prePrint();    cout << endl; 30     tree.appand(12); 31     tree.appand(13); 32     tree.prePrint();    cout << endl; 33     cout << "----------------------------------" << endl; 34 
35     cout << "得到父節點、左右子節點:" << endl; 36     cout << "4的父節點:" << tree.getParent(4) << endl; 37     cout << "4的左子節點:" << tree.getLeftChild(4) << endl; 38     cout << "4的右子節點:" << tree.getRightChild(4) << endl; 39 
40      
41 
42 
43     cin.get(); 44     return 0; 45 }

 運行結果:

相關文章
相關標籤/搜索