樹的淺析與實現
一、基本概念
樹是一種簡單的非線性結構,所有元素之間具有明顯的層次特性。在樹結構中,每一個結點只有一個前驅節點,稱為父結點,沒有前驅節點的結點只有一個,稱為樹的根結點,簡稱樹的根。每一個結點可以有多個後繼節點,稱為該結點的子結點。沒有後繼節點的結點稱為葉子結點。在樹結構中,一個結點所擁有的後件的個數稱為該結點的度,所有結點中最大的度稱為樹的度。樹的最大層次稱為樹的深度。
二、二叉樹
定義:二叉樹是每個結點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree)。二叉樹常被用於實現二叉查找樹和二叉堆。二叉樹通常分為滿二叉樹和完全二叉樹。
(1)滿二叉樹:一個深度為K且有2k+1-1個節點的二叉樹。
(2)完全二叉樹:只多有最下面的兩層的節點的度數可以小於2,其余各層節點的度數都等於2,並且最下面一層的節點都集中在該層最左邊的若幹位置。
性質:
(1)對於非空二叉樹,其i層最大的節點數目為2i,其中i>=0。
(2)深度為k的二叉樹之多有2k+1-1個節點,其中k>=-1。
(3)在任意一棵非空二叉樹中,若終端節點的個數為n0,度為2的節點數為n2,則存在n0 = n2 +1。
(4)具有n個節點的完全二叉樹的深度為k等於log2(n+1)向上取整再減1。
(5)如將一棵有n個節點的完全二叉樹子上(根節點)向下(葉節點),同一層,子做向右連續賦予節點編號0,1,2,3,4....,n-1則對任意下標為i的節點有:
1、若i=0,則i為根節點,無父節點;若i>0,i>0,則i的父節點下標為(i-1)/2向下取整。
2、若2*i+1<n,則i的左子女為2*i+1。
3、若2*i+2<n,則i的右子女為2*i+2。
4、若i為偶數,且i≠0,則左兄弟為i-1。
5、若i為奇數,且i≠n-1,則右兄弟為i+1。
6、節點i所在的層次為log2(i+1)向下取整。
實現:
樹節點定義
![技術分享圖片](/img/jia.gif)
1 #pragma once 2 #include <iostream> 3 #include <assert.h> 4binaryTreeNode.husing namespace std; 5 template <class T> 6 class BinaryTreeNode 7 { 8 public: 9 BinaryTreeNode(); 10 BinaryTreeNode(BinaryTreeNode* node); 11 void setData(const T &value); //設置節點值 12 void setParent(BinaryTreeNode<T>*parent); //設置父節點 13 void setLeftChild(BinaryTreeNode<T>*leftchild); //設置左孩子節點 14 void setRightChild(BinaryTreeNode<T>*rightchild); //設置右孩子節點 15 T& getData(); //獲取節點值 16 BinaryTreeNode<T>* getparent(); //獲取父節點 17 BinaryTreeNode<T>* getLeftChild(); //獲取左孩子節點 18 BinaryTreeNode<T>* getRightChild(); //獲取右孩子節點 19 20 private: 21 T m_value; //存儲值 22 BinaryTreeNode<T>* m_parent; //指向父節點 23 BinaryTreeNode<T>* m_leftChilde; //指向左孩子節點 24 BinaryTreeNode<T>* m_rightChilde; //指向右孩子節點 25 }; 26 27 28 29 30 template <class T> 31 BinaryTreeNode<T>::BinaryTreeNode() 32 { 33 m_parent = NULL; 34 m_leftChilde = NULL; 35 m_rightChilde = NULL; 36 } 37 38 template <class T> 39 BinaryTreeNode<T>::BinaryTreeNode(BinaryTreeNode* node) 40 { 41 m_value = node->getData(); 42 m_parent = node->getparent(); 43 m_leftChilde = node->getLeftChild(); 44 m_rightChilde = node->getRightChild(); 45 } 46 47 template <class T> 48 void BinaryTreeNode<T>::setData(const T &value) 49 { 50 m_value = value; 51 } 52 53 template <class T> 54 void BinaryTreeNode<T>::setParent(BinaryTreeNode<T>*parent) 55 { 56 m_parent = parent; 57 } 58 59 template <class T> 60 void BinaryTreeNode<T>::setRightChild(BinaryTreeNode<T>*rightchild) 61 { 62 m_rightChilde = rightchild; 63 } 64 65 template <class T> 66 void BinaryTreeNode<T>::setLeftChild(BinaryTreeNode<T>*leftchild) 67 { 68 m_leftChilde = leftchild; 69 } 70 71 template <class T> 72 T& BinaryTreeNode<T>::getData() 73 { 74 return m_value; 75 } 76 77 template <class T> 78 BinaryTreeNode<T>* BinaryTreeNode<T>::getparent() 79 { 80 return m_parent; 81 } 82 83 template <class T> 84 BinaryTreeNode<T>* BinaryTreeNode<T>::getRightChild() 85 { 86 return m_rightChilde; 87 } 88 89 template <class T> 90 BinaryTreeNode<T>* BinaryTreeNode<T>::getLeftChild() 91 { 92 return m_leftChilde; 93 }
樹定義
![技術分享圖片](/img/jia.gif)
1 #pragma once 2 #include <iostream> 3 #include <assert.h> 4 #include <stack> 5 #include <queue> 6 #include "binaryTreeNode.h" 7 using namespace std; 8 template <class T> 9 class BinaryTree 10 { 11 public: 12 BinaryTree(T &value); 13 BinaryTree(BinaryTreeNode<T>* node); 14 BinaryTreeNode<T>* getRoot(); //獲取根節點 15 void insertLeftChild(BinaryTreeNode<T>* root, T &value); //插入左孩節點 16 void insertRightChild(BinaryTreeNode<T>* root,T &value); //插入右孩子節點 17 bool isEmpty(); //判斷是否為空 18 //樹的遍歷 19 //前序遍歷 20 void preOrderTraverse1(BinaryTreeNode<T>* root) const; //使用遞歸實現 21 void preOrderTraverse2(BinaryTreeNode<T>* root) const; //使用棧結構實現 22 //中序遍歷 23 void inOrderTraverse1(BinaryTreeNode<T>* root) const; //使用遞歸實現 24 void inOrderTraverse2(BinaryTreeNode<T>* root) const; //使用棧結構實現 25 //後序遍歷 26 void postOrderTraverse1(BinaryTreeNode<T>* root) const; //使用遞歸實現 27 void postOrderTraverse2(BinaryTreeNode<T>* root) const; //使用棧結構實現 28 //層序遍歷 29 void levelOrderTraverse(BinaryTreeNode<T>* root) const; 30 private: 31 BinaryTreeNode<T>* m_root; //根節點 32 }; 33 34 35 36 37 38 //構造函數 39 template <class T> 40 BinaryTree<T>::BinaryTree(T &value) 41 { 42 m_root = new BinaryTreeNode<T>(); 43 m_root->setData(value); 44 } 45 46 template <class T> 47 BinaryTree<T>::BinaryTree(BinaryTreeNode<T>* node) 48 { 49 m_root = new BinaryTreeNode<T>(); //創建一個新的節點 50 m_root = node; 51 } 52 53 //設置子節點函數 54 template <class T> 55 void BinaryTree<T>::insertRightChild(BinaryTreeNode<T>* root, T &value) 56 { 57 BinaryTreeNode<T>* childNode = new BinaryTreeNode<T>(); 58 childNode->setData(value); 59 childNode->setParent(root); 60 root->setRightChild(childNode); 61 } 62 63 template <class T> 64 void BinaryTree<T>::insertLeftChild(BinaryTreeNode<T>* root, T &value) 65 { 66 BinaryTreeNode<T>* childNode = new BinaryTreeNode<T>(); 67 childNode->setData(value); 68 childNode->setParent(root); 69 root->setLeftChild(childNode); 70 } 71 72 //獲取根節點函數 73 template <class T> 74 BinaryTreeNode<T>* BinaryTree<T>::getRoot() 75 { 76 return m_root; 77 } 78 79 template <class T> 80 bool BinaryTree<T>::isEmpty() 81 { 82 return m_root->getparent(); 83 } 84 85 //遍歷函數 86 //1、前序遍歷 87 template <class T> 88 void BinaryTree<T>::preOrderTraverse1(BinaryTreeNode<T>* root) const 89 { 90 if (NULL !=root) 91 { 92 cout << root->getData() << "->"; 93 preOrderTraverse1(root->getLeftChild()); 94 preOrderTraverse1(root->getRightChild()); 95 } 96 } 97 98 template <class T> 99 void BinaryTree<T>::preOrderTraverse2(BinaryTreeNode<T>* root) const 100 { 101 stack<BinaryTreeNode<T>*> s; 102 BinaryTreeNode<T>* p = root; 103 while (!s.empty() || p!=NULL) 104 { 105 while (p) 106 { 107 s.push(p); 108 cout << p->getData() << "->"; 109 p = p->getLeftChild(); 110 } 111 p = s.top(); 112 s.pop(); 113 p = p->getRightChild(); 114 115 } 116 } 117 118 //2、中序遍歷 119 template <class T> 120 void BinaryTree<T>::inOrderTraverse1(BinaryTreeNode<T>* root) const 121 { 122 if (NULL != root) 123 { 124 inOrderTraverse1(root->getLeftChild()); 125 cout << root->getData() << "->"; 126 inOrderTraverse1(root->getRightChild()); 127 } 128 } 129 130 template <class T> 131 void BinaryTree<T>::inOrderTraverse2(BinaryTreeNode<T>* root) const 132 { 133 stack<BinaryTreeNode<T>*> s; 134 BinaryTreeNode<T>*p = root; 135 while (!s.empty() || p != NULL) 136 { 137 while (p) 138 { 139 s.push(p); 140 p = p->getLeftChild(); 141 } 142 p = s.top(); 143 s.pop(); 144 cout << p->getData()<<"->"; 145 p = p->getRightChild(); 146 } 147 } 148 149 //2、後序遍歷 150 template <class T> 151 void BinaryTree<T>::postOrderTraverse1(BinaryTreeNode<T>* root) const 152 { 153 if (NULL!=root) 154 { 155 postOrderTraverse1(root->getLeftChild()); 156 postOrderTraverse1(root->getRightChild()); 157 cout << root->getData() << "->"; 158 } 159 } 160 161 template <class T> 162 void BinaryTree<T>::postOrderTraverse2(BinaryTreeNode<T>* root) const 163 { 164 stack<BinaryTreeNode<T>*> s; 165 BinaryTreeNode<T> *cur; //當前節點 166 BinaryTreeNode<T> *pre = NULL; //上一次訪問的節點 167 s.push(root); 168 while (!s.empty() ) 169 { 170 cur = s.top(); 171 if ((cur->getLeftChild() == NULL) && (cur->getRightChild() == NULL) 172 || (pre != NULL)&&(pre ==cur->getLeftChild()||pre==cur->getRightChild())) 173 { 174 cout << cur->getData() << "->"; //如果當前結點沒有孩子結點或者孩子節點都已被訪問過 175 s.pop(); 176 pre = cur; 177 } 178 else 179 { 180 if (cur->getRightChild() != NULL) 181 { 182 s.push(cur->getRightChild()); 183 } 184 if (cur->getLeftChild() != NULL) 185 { 186 s.push(cur->getLeftChild()); 187 } 188 } 189 190 } 191 192 193 } 194 //層序遍歷 195 template <class T> 196 void BinaryTree<T>::levelOrderTraverse(BinaryTreeNode<T>* root) const 197 { 198 queue<BinaryTreeNode<T>* > q; 199 BinaryTreeNode<T>* p; 200 q.push(root); 201 while (!q.empty()) 202 { 203 p = q.front(); 204 if (p->getLeftChild() != NULL) 205 q.push(p->getLeftChild()); 206 if (p->getRightChild() != NULL) 207 q.push(p->getRightChild()); 208 q.pop(); 209 cout << p->getData() << "->"; 210 } 211 }BinaryTree.h
測試代碼
![技術分享圖片](/img/jia.gif)
1 #include <stdio.h> 2 #include <iostream> 3 #include "BinaryTree.h" 4 #include "binaryTreeNode.h" 5 using namespace std; 6 int main() 7 { 8 char value = ‘A‘; 9 BinaryTree<char> mytree(value); 10 value++; 11 mytree.insertLeftChild(mytree.getRoot(), value); 12 value++; 13 mytree.insertRightChild(mytree.getRoot(), value); 14 value++; 15 mytree.insertLeftChild(mytree.getRoot()->getLeftChild(), value); 16 value++; 17 mytree.insertRightChild(mytree.getRoot()->getLeftChild(), value); 18 value++; 19 mytree.insertLeftChild(mytree.getRoot()->getRightChild(), value); 20 value++; 21 mytree.insertRightChild(mytree.getRoot()->getRightChild(), value); 22 23 cout << mytree.getRoot()->getData() << "\n"; 24 cout << mytree.getRoot()->getLeftChild()->getData() << "\n"; 25 cout << mytree.getRoot()->getRightChild()->getData() << "\n"; 26 cout << mytree.getRoot()->getLeftChild()->getLeftChild()->getData() << "\n"; 27 cout << mytree.getRoot()->getLeftChild()->getRightChild()->getData() << "\n"; 28 cout << mytree.getRoot()->getRightChild()->getLeftChild()->getData() << "\n"; 29 cout << mytree.getRoot()->getRightChild()->getRightChild()->getData() << "\n"; 30 cout <<"前序遍歷遞歸實現"<<endl; 31 mytree.preOrderTraverse1(mytree.getRoot()); 32 cout << endl; 33 cout << "前序遍歷棧實現" << endl; 34 mytree.preOrderTraverse2(mytree.getRoot()); 35 cout << endl; 36 cout << "中序遍歷遞歸實現" << endl; 37 mytree.inOrderTraverse1(mytree.getRoot()); 38 cout << endl; 39 cout << "中序遍歷棧實現" << endl; 40 mytree.inOrderTraverse2(mytree.getRoot()); 41 cout << endl; 42 cout << "後序遍歷遞歸實現" << endl; 43 mytree.postOrderTraverse1(mytree.getRoot()); 44 cout << endl; 45 cout << "後序遍歷棧實現" << endl; 46 mytree.postOrderTraverse2(mytree.getRoot()); 47 cout << endl; 48 cout << "層序遍歷實現" << endl; 49 mytree.levelOrderTraverse(mytree.getRoot()); 50 51 52 return 0; 53 }測試代碼
測試結果
樹的淺析與實現