1. 程式人生 > >樹的淺析與實現

樹的淺析與實現

push pty 簡單 之間 存在 .... assert highlight 前序遍歷

一、基本概念

  樹是一種簡單的非線性結構,所有元素之間具有明顯的層次特性。在樹結構中,每一個結點只有一個前驅節點,稱為父結點,沒有前驅節點的結點只有一個,稱為樹的根結點,簡稱樹的根。每一個結點可以有多個後繼節點,稱為該結點的子結點。沒有後繼節點的結點稱為葉子結點。在樹結構中,一個結點所擁有的後件的個數稱為該結點的度,所有結點中最大的度稱為樹的度。樹的最大層次稱為樹的深度。

二、二叉樹

  定義:二叉樹是每個結點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(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)向下取整。

  實現:

樹節點定義

技術分享圖片
 1 #pragma once
 2 #include <iostream>  
 3 #include <assert.h>  
 4
using 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 }
binaryTreeNode.h

樹定義

技術分享圖片
  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

測試代碼

技術分享圖片
 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 }
測試代碼

測試結果

技術分享圖片

樹的淺析與實現