1. 问题.
判断二叉树是否为完全二叉树。
完全二叉树的定义是,前n-1层都是满的,第n层如有空缺,则是缺在右边,即第n层的最右边的节点,它的左边是满的,右边是空的。
2.以3层二叉树为例,以下情况为完全二叉树
3. 原理
这个问题的描述已经提示了解法,采用广度优先遍历,从根节点开始,入队列,如果队列不为空,循环。
遇到第一个没有左儿子或者右儿子的节点,设置标志位,如果之后再遇到有左/右儿子的节点,那么这不是一颗完全二叉树。
即一旦找一个不含有子节点或者只含有一个左子节点之后,那么后续的所有节点都必须是叶子节点。否则,该树就不是完全二叉树。
4. 方法一
//二叉树结点定义
typedef struct Node
{
int data;
struct Node* left;
struct Node* right;
}Node;
//实现广度遍历需要队列
Queue<Node*> queue;
//第n层最右节点标志
bool leftMost = false;
bool ProcessChild(Node* child)
{
if (child)
{
if (!leftMost)
{
queue.push(child);
}
else
{
return false;
}
}
else
{
leftMost = true;
}
return true;
}
bool IsCompleteBinaryTree(Node* root)
{
//空树也是完全二叉树
if (!root)
return true;
//首先根节点入队列
queue.push(root);
while(!queue.empty())
{
Node* node = queue.pop();
//处理左节点
if (!ProcessChild(node->left))
return false;
//处理右节点
if (!ProcessChild(node->right))
return false;
}
//广度优先遍历完毕,此乃完全二叉树
return true;
}
5.方法二
1.#include <stdlib.h>
2. #include <stdio.h>
3.
4. class TreeNode{
5. public:
6. int value;
7. TreeNode *left;
8. TreeNode *right;
9. TreeNode(int v) : value(v) {
10. left = NULL;
11. right = NULL;
12. }
13. ~TreeNode() {
14. if (left != NULL) {
15. delete left;
16. left = NULL;
17. }
18. if (right != NULL) {
19. delete right;
20. right = NULL;
21. }
22. }
23. };
24.
25. struct QueueNode {
26. TreeNode *data;
27. QueueNode *next;
28. };
29.
30. //用链表的方式实现队列
31. class Queue {
32. private:
33. QueueNode *head; //队列的投指针
34. QueueNode *tail; //队列的尾指针
35. public:
36. Queue()
37. {
38. head = NULL;
39. tail = NULL;
40. }
41. void enqueue(TreeNode *node) { //入队列
42. QueueNode *q = new QueueNode();
43. q->data = node;
44. q->next = NULL;
45. if(head == NULL) {
46. head = q;
47. tail = q;
48. } else {
49. tail->next = q;
50. tail = q;
51. }
52. }
53. //判断队列是否是空
54. bool isEmpty(){
55. return head == NULL;
56. }
57. //出队列
58. TreeNode * dequeue(){
59. if(head == NULL) return NULL;//如果当前队列是空,直接返回null.
60. QueueNode *p = head;
61. TreeNode *ptree = p->data;
62. head = head->next;
63. if (head==NULL) { //如果出队列之后,队列为空了,则修改tail为空
64. tail == NULL;
65. }
66. p->next = NULL;
67. delete p; //删除队列节点
68. return ptree;
69. }
70. ~Queue(){
71. QueueNode *p = head, *q;
72. while(p != NULL) {
73. q = p;
74. p = p->next;
75. delete q;
76. }
77. }
78. };
79. /*
80. 判断一个二叉树是否是完全二叉树
81. 广度优先搜索整个二叉树,一旦找一个节点只不含有子节点或者子含有一个左子节点,
82. 那么后续的所有节点都必须是叶子节点。否则,该树就不是完全二叉树。
83. */
84. bool isCompBinTree(TreeNode *root)
85. {
86.
87. if(root == NULL) return true;
88. Queue qu;
89. bool last = false; //判断当前是否已经找到了第一个不含有两个子节点的节点。
90. bool isCompBTree = true;
91. TreeNode *p;
92. qu.enqueue(root);
93. while( ! qu.isEmpty()) {
94. p = qu.dequeue();
95. if(! last) { //前面所有的节点都含有两个子节点
96. if (p->left != NULL && p->right !=NULL) { //当前节点也含有两个子节点
97. qu.enqueue(p->left);
98. qu.enqueue(p->right);
99. } else if (p->left != NULL && p->right==NULL) { //当前节点只含有左子节点,则在其后面的所有节点都必须是叶子节点
100. last = true;
101. qu.enqueue(p->left);
102. } else if (p->left == NULL && p->right!=NULL) { //当前节点只含有右子节点,该树不是完全的。
103. last = true;
104. isCompBTree = false;
105. break;
106. } else { //当前节点不含有任何的子节点。
107. last = true;
108. }
109. }
110. else
111. {
112. //已经找到了第一个不含有两个子节点的节点,当前扫描的节点必须是叶子节点。
113. if ( p->left!=NULL || p->right != NULL) {
114. isCompBTree = false;
115. break;
116. }
117. }
118. }
119. if (isCompBTree) {
120. printf("是完全二叉树.\n");
121. } else {
122. printf("不是完全二叉树.\n");
123. }
124. return isCompBTree;
125. }
126. /*
127. 1 1
128. 2 3 2 3
129. 4 5 4 5 6
130.
131.
132. */
133. void clear(TreeNode *ele[], int n) {
134. for(int i=0; i<n; i++) {
135. ele[i]->left = NULL;
136. ele[i]->right = NULL;
137. }
138. }
139. int main()
140. {
141. TreeNode *ele[10];
142. TreeNode *root, *p, *q;
143. for(int i=0; i<10; i++) {
144. ele[i] = new TreeNode(i+1);
145. }
146.
147. printf("Case 1: ");
148. root = ele[0];
149. root->left = ele[1]; root->right=ele[2];
150. root->left->left=ele[3]; root->left->right=ele[4];
151. isCompBinTree(root);
152.
153. printf("Case 2: ");
154. clear(ele, 10);
155. root = ele[0];
156. root->left = ele[1]; root->right=ele[2];
157. root->left->right=ele[3]; root->right->left=ele[4]; root->right->right=ele[5];
158. isCompBinTree(root);
159.
160. /*
161. 1
162. */
163. printf("Case 3: ");
164. clear(ele, 10);
165. root = ele[0];
166. isCompBinTree(root);
167.
168. /*
169. 1
170. 2
171. 3
172. */
173. printf("Case 4: ");
174. clear(ele, 10);
175. root = ele[0];
176. root->left = ele[1];
177. root->left->left = ele[2];
178. isCompBinTree(root);
179.
180. /*
181. 1
182. 2
183. */
184. printf("Case 5: ");
185. clear(ele, 10);
186. root = ele[0];
187. root->left = ele[1];
188. isCompBinTree(root);
189.
190. /*
191. 1
192. 2 3
193. 4 5
194. */
195. printf("Case 6: ");
196. clear(ele, 10);
197. root = ele[0];
198. root->left = ele[1]; root->right=ele[2];
199. root->right->left = ele[3]; root->right->right = ele[4];
200. isCompBinTree(root);
201.
202. clear(ele, 10);
203. for(int i=0; i<10; i++) {
204. delete ele[i];
205. }
206. system("pause");
207. return 0;
208. }
参考文献:
[1]http://blog.chinaunix.net/uid-1844931-id-3047710.html 博主:liubird
[2]http://blog.csdn.net/lilypp/article/details/6158699/ 博主:lilypp
1.#include <stdlib.h>
2. #include <stdio.h>
3.
4. class TreeNode{
5. public:
6. int value;
7. TreeNode *left;
8. TreeNode *right;
9. TreeNode(int v) : value(v) {
10. left = NULL;
11. right = NULL;
12. }
13. ~TreeNode() {
14. if (left != NULL) {
15. delete left;
16. left = NULL;
17. }
18. if (right != NULL) {
19. delete right;
20. right = NULL;
21. }
22. }
23. };
24.
25. struct QueueNode {
26. TreeNode *data;
27. QueueNode *next;
28. };
29.
30. //用链表的方式实现队列
31. class Queue {
32. private:
33. QueueNode *head; //队列的投指针
34. QueueNode *tail; //队列的尾指针
35. public:
36. Queue()
37. {
38. head = NULL;
39. tail = NULL;
40. }
41. void enqueue(TreeNode *node) { //入队列
42. QueueNode *q = new QueueNode();
43. q->data = node;
44. q->next = NULL;
45. if(head == NULL) {
46. head = q;
47. tail = q;
48. } else {
49. tail->next = q;
50. tail = q;
51. }
52. }
53. //判断队列是否是空
54. bool isEmpty(){
55. return head == NULL;
56. }
57. //出队列
58. TreeNode * dequeue(){
59. if(head == NULL) return NULL;//如果当前队列是空,直接返回null.
60. QueueNode *p = head;
61. TreeNode *ptree = p->data;
62. head = head->next;
63. if (head==NULL) { //如果出队列之后,队列为空了,则修改tail为空
64. tail == NULL;
65. }
66. p->next = NULL;
67. delete p; //删除队列节点
68. return ptree;
69. }
70. ~Queue(){
71. QueueNode *p = head, *q;
72. while(p != NULL) {
73. q = p;
74. p = p->next;
75. delete q;
76. }
77. }
78. };
79. /*
80. 判断一个二叉树是否是完全二叉树
81. 广度优先搜索整个二叉树,一旦找一个节点只不含有子节点或者子含有一个左子节点,
82. 那么后续的所有节点都必须是叶子节点。否则,该树就不是完全二叉树。
83. */
84. bool isCompBinTree(TreeNode *root)
85. {
86.
87. if(root == NULL) return true;
88. Queue qu;
89. bool last = false; //判断当前是否已经找到了第一个不含有两个子节点的节点。
90. bool isCompBTree = true;
91. TreeNode *p;
92. qu.enqueue(root);
93. while( ! qu.isEmpty()) {
94. p = qu.dequeue();
95. if(! last) { //前面所有的节点都含有两个子节点
96. if (p->left != NULL && p->right !=NULL) { //当前节点也含有两个子节点
97. qu.enqueue(p->left);
98. qu.enqueue(p->right);
99. } else if (p->left != NULL && p->right==NULL) { //当前节点只含有左子节点,则在其后面的所有节点都必须是叶子节点
100. last = true;
101. qu.enqueue(p->left);
102. } else if (p->left == NULL && p->right!=NULL) { //当前节点只含有右子节点,该树不是完全的。
103. last = true;
104. isCompBTree = false;
105. break;
106. } else { //当前节点不含有任何的子节点。
107. last = true;
108. }
109. }
110. else
111. {
112. //已经找到了第一个不含有两个子节点的节点,当前扫描的节点必须是叶子节点。
113. if ( p->left!=NULL || p->right != NULL) {
114. isCompBTree = false;
115. break;
116. }
117. }
118. }
119. if (isCompBTree) {
120. printf("是完全二叉树.\n");
121. } else {
122. printf("不是完全二叉树.\n");
123. }
124. return isCompBTree;
125. }
126. /*
127. 1 1
128. 2 3 2 3
129. 4 5 4 5 6
130.
131.
132. */
133. void clear(TreeNode *ele[], int n) {
134. for(int i=0; i<n; i++) {
135. ele[i]->left = NULL;
136. ele[i]->right = NULL;
137. }
138. }
139. int main()
140. {
141. TreeNode *ele[10];
142. TreeNode *root, *p, *q;
143. for(int i=0; i<10; i++) {
144. ele[i] = new TreeNode(i+1);
145. }
146.
147. printf("Case 1: ");
148. root = ele[0];
149. root->left = ele[1]; root->right=ele[2];
150. root->left->left=ele[3]; root->left->right=ele[4];
151. isCompBinTree(root);
152.
153. printf("Case 2: ");
154. clear(ele, 10);
155. root = ele[0];
156. root->left = ele[1]; root->right=ele[2];
157. root->left->right=ele[3]; root->right->left=ele[4]; root->right->right=ele[5];
158. isCompBinTree(root);
159.
160. /*
161. 1
162. */
163. printf("Case 3: ");
164. clear(ele, 10);
165. root = ele[0];
166. isCompBinTree(root);
167.
168. /*
169. 1
170. 2
171. 3
172. */
173. printf("Case 4: ");
174. clear(ele, 10);
175. root = ele[0];
176. root->left = ele[1];
177. root->left->left = ele[2];
178. isCompBinTree(root);
179.
180. /*
181. 1
182. 2
183. */
184. printf("Case 5: ");
185. clear(ele, 10);
186. root = ele[0];
187. root->left = ele[1];
188. isCompBinTree(root);
189.
190. /*
191. 1
192. 2 3
193. 4 5
194. */
195. printf("Case 6: ");
196. clear(ele, 10);
197. root = ele[0];
198. root->left = ele[1]; root->right=ele[2];
199. root->right->left = ele[3]; root->right->right = ele[4];
200. isCompBinTree(root);
201.
202. clear(ele, 10);
203. for(int i=0; i<10; i++) {
204. delete ele[i];
205. }
206. system("pause");
207. return 0;
208. }