判断二叉树是否是完全二叉树

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. }


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值