1. 程式人生 > >c++二叉樹

c++二叉樹

wall hide esp new 改變 左右 ostream 最小 ace

技術分享
 1 #ifndef _TREE_H_
 2 #define _TREE_H_
 3 
 4 //此類用shared_ptr來管理節點內存,所以要包含<memory>頭文件,不需要手動釋放內存
 5 #include <memory>
 6 #include <iostream>
 7 
 8 using namespace std;
 9 
10 struct Node{
11     int key;
12     shared_ptr<Node> parent;
13     shared_ptr<Node> left;
14     shared_ptr<Node> right;
15 Node(int k = 0) :key(k), parent(), left(), right() {} 16 }; 17 18 19 typedef shared_ptr<Node> Pnode; 20 21 //遍歷節點 22 void showNode(Pnode current); 23 24 25 class Tree 26 { 27 private: 28 Pnode root; 29 //返回以current為根節點的所有節點個數 30 size_t __nodeSize(Pnode current) const; 31 //返回以current為根節點的葉節點(沒有左右節點)個數
32 size_t __leafSize(Pnode current) const; 33 //返回以current為根節點樹的深度 34 size_t __depth(Pnode current) const; 35 //返回k值節點的地址 36 const Pnode * __getNodeAddress(int k) const; 37 //返回current節點下的最大值的節點 38 Pnode __maxNode(Pnode current) const; 39 //返回current節點下的最小值節點 40 Pnode __minNode(Pnode current) const
; 41 public: 42 Tree() :root() {} 43 //將k插入樹 44 void insert(int k); 45 //刪除值為k的節點 46 void delNode(int k); 47 //判斷是否存在值為k的節點 48 bool isExist(int k); 49 //樹中節點個數 50 size_t nodeSize() const; 51 //樹中葉節點的個數 52 size_t leafSize() const; 53 //樹的深度 54 size_t depth() const; 55 //樹的寬度 56 size_t width() const; 57 //樹的最大值 58 int maxVal() const; 59 //樹的最小值 60 int minVal() const; 61 //打印所有節點 62 void showAll() const; 63 }; 64 65 #endif
tree.h

技術分享
  1 #include "tree.h"
  2 
  3 //求樹的寬度要用到隊列
  4 #include <queue>
  5 
  6 using namespace std;
  7 
  8 void showNode(Pnode current)
  9 {
 10     if (current.get() == NULL)
 11         return;
 12     showNode(current->left);
 13     cout << current->key << " ";
 14     showNode(current->right);
 15 }
 16 
 17 void Tree::showAll() const
 18 {
 19     showNode(root);
 20     cout << endl;
 21 }
 22 
 23 void Tree::insert(int k)
 24 {
 25     //智能指針shared_ptr變量的初始化方式
 26     Pnode new_node(new Node(k));
 27     Pnode current = root;
 28     Pnode save = root;    
 29     while (current)
 30     {
 31         save = current;
 32         if (k < current->key)
 33             current = current->left;
 34         else current = current->right;
 35     }
 36     new_node->parent = save;
 37     if (!save)
 38         root = new_node;
 39     else if (k < save->key)
 40         save->left = new_node;
 41     else save->right = new_node;
 42 }
 43 
 44 void Tree::delNode(int k)
 45 {
 46     //__getNodeAddress返回的是帶有頂層const類型的指針,
 47     //後面要改變指針指向的值,所以要先解除const限制.
 48     Pnode * pdel = const_cast<Pnode *>(__getNodeAddress(k));
 49     if (!pdel)
 50     {
 51         cout << k << " is not exist!\n";
 52         return;
 53     }
 54     //save保存被刪節點的父節點
 55     Pnode save = (*pdel)->parent;
 56     //被刪節點沒有子樹
 57     if (!(*pdel)->left.get() && !(*pdel)->right.get())
 58         *pdel = NULL;
 59     //被刪節點左子樹為空
 60     else if (!(*pdel)->left.get())
 61     {
 62         *pdel = (*pdel)->right;
 63         (*pdel)->parent = save;
 64     }
 65     //被刪節點右子樹為空
 66     else if (!(*pdel)->right.get())
 67     {
 68         *pdel = (*pdel)->left;
 69         (*pdel)->parent = save;
 70     }
 71     //被刪節點有左右子樹
 72     else {
 73         //successor為被刪節點的後繼
 74         Pnode successor = __minNode((*pdel)->right);
 75         successor->left = (*pdel)->left;
 76         *pdel = (*pdel)->right;
 77         (*pdel)->parent = save;
 78     }
 79 }
 80 
 81 bool Tree::isExist(int k)
 82 {
 83     return __getNodeAddress(k) != NULL;
 84 }
 85 
 86 size_t Tree::__nodeSize(Pnode current) const
 87 {
 88     if (!current)
 89         return 0;
 90     return 1 + __nodeSize(current->left) + __nodeSize(current->right);
 91 }
 92 
 93 size_t Tree::nodeSize() const
 94 {
 95     return __nodeSize(root);
 96 }
 97 
 98 size_t Tree::__leafSize(Pnode current) const
 99 {
100     if (current.get() == NULL)
101         return 0;
102     if (current->left.get() == NULL && current->right.get() == NULL)
103         return 1;
104     return __leafSize(current->left) + __leafSize(current->right);
105 }
106 
107 size_t Tree::leafSize() const
108 {
109     return __leafSize(root);
110 }
111 
112 size_t Tree::__depth(Pnode current) const
113 {
114     if (!current)
115         return 0;
116     size_t leftSize = 1 + __depth(current->left);
117     size_t rightSize = 1 + __depth(current->right);
118     return leftSize > rightSize ? leftSize: rightSize;
119 }
120 
121 size_t Tree::depth() const
122 {
123     return __depth(root);
124 }
125 
126 size_t Tree::width() const
127 {
128     if (!root)
129         return 0;
130     Pnode current = root;
131     int maxNode = 1;
132     int ct = 0;
133     queue<Pnode> qu;
134     qu.push(current);
135     while (qu.size() != 0)
136     {
137         ct = qu.size();
138         for (int i = 0; i < ct; i++)
139         {
140             current = qu.front();
141             qu.pop();
142             if (current->left.get() != NULL)
143                 qu.push(current->left);
144             if (current->right.get() != NULL)
145                 qu.push(current->right);
146         }
147         maxNode = maxNode > qu.size() ? maxNode : qu.size();
148     }
149     return maxNode;
150 }
151 
152 
153 //此處返回指針是考慮到方便delNode調用,內存本身的地址和內存指向的值會帶來很大困惑,要仔細品味,
154 //此前寫delNode方法從節點本身來考慮,反復建立節點關系,寫下的代碼長度大概
155 //是現在delNode長度的2倍,效率也會打折扣.
156 const Pnode  * Tree::__getNodeAddress(int k) const
157 {
158     Pnode ret = root;
159     Pnode save = {};
160     if (root->key == k)
161         return &root;
162     while (1)
163     {
164         save = ret;
165         if (k < ret->key)
166         {
167             if (!(ret = ret->left).get())
168                 break;
169             if (ret->key == k)
170                 return &(save->left);
171         }
172         else {
173             if(!(ret = ret->right).get())
174                 break;
175             if (ret->key == k)
176                 return &(save->right);
177         }
178     }
179     return NULL;
180 }
181 
182 Pnode Tree::__maxNode(Pnode current) const
183 {
184     
185     while (current->right.get() != NULL)
186         current = current->right;
187     return current;
188 }
189 
190 Pnode Tree::__minNode(Pnode current) const
191 {
192     while (current->left.get() != NULL)
193         current = current->left;
194     return current;
195 }
196 
197 int Tree::maxVal() const
198 {
199     if (root.get() == NULL)
200         return 0x80000000;
201     return __maxNode(root)->key;
202 }
203 
204 int Tree::minVal() const
205 {
206     if (root.get() == NULL)
207         return 0x7FFFFFFF;
208     return __minNode(root)->key;
209 }
tree.cpp

技術分享
 1 #include <iostream>
 2 #include "Tree.h"
 3 
 4 using namespace std;
 5 
 6 void showArray(int * arr, int n);
 7 void loadArrayToTree(Tree & t, int * arr, int n);
 8 
 9 const int ASIZE = 13;
10 
11 int main()
12 {
13     int arr[ASIZE] = { 54,19,18,39,76,15,80,70,25,41,83,79,71 };
14     cout << "show array: \n";
15     showArray(arr, ASIZE);
16     Tree t;
17     loadArrayToTree(t, arr, ASIZE);
18     cout << "show Tree: \n";
19     t.showAll();
20     cout << "nodeSize() = " << t.nodeSize() << endl;
21     cout << "leafSize() = " << t.leafSize() << endl;
22     cout << "depth() = " << t.depth() << endl;
23     cout << "width() = " << t.width() << endl;
24     cout << "isExist(41) = " << t.isExist(41) << endl;
25     t.delNode(41);
26     t.showAll();
27     cout << "nodeSize() = " << t.nodeSize() << endl;
28     cout << "isExist(41) = " << t.isExist(41) << endl;
29     cout << "isExist(80) = " << t.isExist(80) << endl;
30 
31 
32     return 0;
33 }
34 
35 void showArray(int * arr, int n)
36 {
37     for (int i = 0; i < n; i++)
38         cout << arr[i] << " ";
39     cout << endl;
40 }
41 
42 void loadArrayToTree(Tree & t, int * arr, int n)
43 {
44     for (int i = 0; i < n; i++)
45         t.insert(arr[i]);
46 }
treeMain.cpp測試代碼

c++二叉樹