数据结构之完全二叉树

一 概述

完全二叉树是指除了最后一层之外,其他每一层的每个节点都是同时含有左右子树。当最后一层的每个节点也都含有左右子树的时候,则为满二叉树,同时也是完全二叉树。如果最后一层不满的时候,非满结点(即没有满足同时拥有左右子树的结点)的子树全部集中在左子树的时候,那也是一个完全二叉树。

二 二叉树的类型图示

满二叉树完全二叉树非完全二叉树非完全二叉树

三 代码实现完全二叉树的判断

补充知识:叶子结点,一棵树中当没有子结点(即度为0)的结点为叶子结点。

思路:

判断完全二叉树的
1.如果树为空,直接返回错误; 
2.如果树非空,层序遍历二叉树; 
3.如果一个结点左右孩子均Not NULL时,则pop该结点,将其左右孩子入队列;
4.如果遇到一个结点,左孩子为空,而右孩子非空,则一定不为完全二叉树;
5.如果遇到一个结点,左孩子不为空,而右孩子为空;或者是左右孩子均为空,则结点之后的队列的结点都为叶子结点;
满足以上条件则为完全二叉树,否则不是完全二叉树。 

Java实现完全二叉树判断的主要代码:

AllBinTreeNode:

package algorithm;

public class AllBinTreeNode {
	
	//二叉树的每个子节点也可以看作为一棵树
	AllBinTreeNode left = null;
	AllBinTreeNode right = null;
	
	public AllBinTreeNode() {
		
	}

	public AllBinTreeNode(AllBinTreeNode left,AllBinTreeNode right) {
		this.left = left;
		this.right = right;
	}
    
	//重写toString方法,eclipse的快捷键为Alt+Shift+S
	@Override
	public String toString() {
		return "AllBinTreeNode [left=" + left + ", right=" + right + "]";
	}
}

CheckAllBinTree:

package algorithm;

import java.util.LinkedList;
import java.util.Queue;

public class CheckAllBinTree {
	
	public boolean check(AllBinTreeNode root) {
		
		Queue<AllBinTreeNode> allBinTreeNode = new LinkedList<AllBinTreeNode>();
		
		//判断是否为叶子结点,默认为true
		boolean isLeaf = true;
		
		AllBinTreeNode left;
		AllBinTreeNode right;
		
		allBinTreeNode.add(root);

		while(!allBinTreeNode.isEmpty()) {
			
			root = allBinTreeNode.poll();

			left = root.left;
			right = root.right;
			
			if(left != null || right != null) {	
				isLeaf = false;
			}
			
			/*leaf == true表示叶子结点,这时候如果存在左右结点时,直接返回false
			 *leaf == false表示非叶子结点,这时候如果存在左右结点中的右结点,
             *但没有左边结点时,直接返回false */
			if((isLeaf && ( left != null || right != null))||( left == null && right != null)) {
				return false;
			}
			
			if(left != null) {
				allBinTreeNode.offer(root.left);
			}
			
			if(right != null) {
				allBinTreeNode.offer(root.right);
			}else {
				isLeaf = true;//如果当前结点没有右孩子的时候,那么之后层遍历的结点一定为叶子结点。
			}
		}
		return true;
	}
}

C++代码实现完全二叉树判断的主要代码:

参考:https://baike.baidu.com/item/%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91
#include <iostream>
#include <queue>
 
using namespace std;
 
template <class T>
struct TreeNode
{
    T data;
    TreeNode<T> *left;
    TreeNode<T> *right;
    TreeNode(const T &x) : data(x),left(NULL),right(NULL) {}
};
template <class T>
bool IsComplete(TreeNode<T> *root)
{
    //1.树为空,返回错误
    if (root == NULL)
    {
        return false;
    }
    //2.树不为空
    queue<TreeNode<T> *> q;
    q.push(root);
    while (!q.empty())
    {
        TreeNode<T> *top = q.front();
        //2.1如果该节点两个孩子都有,则直接pop
        if (top->left && top->right)
        {
            q.pop();
            q.push(top->left);
            q.push(top->right);
        }
        //2.2如果该节点左孩子为空,右孩子不为空,则一定不是完全二叉树
        if (top->left == NULL && top->right)
        {
            return false;
        }
        //2.3如果该节点左孩子不为空,右孩子为空或者该节点为叶子节点,
        //则该节点之后的所有结点都是叶子节点
        if ((top->left && top->right == NULL) || (top->left == NULL && top->right == NULL)){
                        if (NULL != top->left && NULL == top->right) 
                        {
                            q.push(top->left);    
                        }
            q.pop(); //则该节点之后的所有结点都是叶子节点
            while (!q.empty())
            {
                top = q.front();
                if (top->left == NULL && top->right == NULL)
                {
                    q.pop();
                }
                else
                {
                    return false;
                }
            }
            return true;
        }
    }
    return true;
}
 
//满二叉树
void test1()
{
    //    1
    //  2   3
    //4  5 6  7
    TreeNode<int> *node1 = new TreeNode<int>(1);
    TreeNode<int> *node2 = new TreeNode<int>(2);
    TreeNode<int> *node3 = new TreeNode<int>(3);
    TreeNode<int> *node4 = new TreeNode<int>(4);
    TreeNode<int> *node5 = new TreeNode<int>(5);
    TreeNode<int> *node6 = new TreeNode<int>(6);
    TreeNode<int> *node7 = new TreeNode<int>(7);
    node1->left = node2;
    node1->right = node3;
    node2->left = node4;
    node2->right = node5;
    node3->left = node6;
    node3->right = node7;
    cout << IsComplete<int>(node1)<< endl;
}
 
//二叉树为空
void test2()
{
    cout << IsComplete<int>(NULL) << endl;
}
 
//3.二叉树不为空,也不是满二叉树,遇到一个结点左孩子为空,右孩子不为空。
void test3()
{
    //    1
    //  2   3
    //4  5    7
    TreeNode<int> *node1 = new TreeNode<int>(1);
    TreeNode<int> *node2 = new TreeNode<int>(2);
    TreeNode<int> *node3 = new TreeNode<int>(3);
    TreeNode<int> *node4 = new TreeNode<int>(4);
    TreeNode<int> *node5 = new TreeNode<int>(5);
    TreeNode<int> *node7 = new TreeNode<int>(7);
    node1->left = node2;
    node1->right = node3;
    node2->left = node4;
    node2->right = node5;
    node3->right = node7;
    cout << IsComplete<int>(node1) << endl;
}
 
//4.二叉树不为空,也不是满二叉树,遇到叶子节点,
//则该叶子节点之后的所有结点都为叶子节点。
void test4()
{
    //        1
    //    2       3
    // 4    5
    TreeNode<int> *node1 = new TreeNode<int>(1);
    TreeNode<int> *node2 = new TreeNode<int>(2);
    TreeNode<int> *node3 = new TreeNode<int>(3);
    TreeNode<int> *node4 = new TreeNode<int>(4);
    TreeNode<int> *node5 = new TreeNode<int>(5);
    node1->left = node2;
    node1->right = node3;
    node2->left = node4;
    node2->right = node5;
    cout << IsComplete<int>(node1) << endl;
}
 
//4.二叉树不为空,也不是满二叉树,遇到左孩子不为空,
//右孩子为空的结点,则该节点之后的所有结点都为叶子节点。
void test5()
{
    //        1
    //    2       3
    // 4    5   6
    TreeNode<int> *node1 = new TreeNode<int>(1);
    TreeNode<int> *node2 = new TreeNode<int>(2);
    TreeNode<int> *node3 = new TreeNode<int>(3);
    TreeNode<int> *node4 = new TreeNode<int>(4);
    TreeNode<int> *node5 = new TreeNode<int>(5);
    TreeNode<int> *node6 = new TreeNode<int>(6);
    node1->left = node2;
    node1->right = node3;
    node2->left = node4;
    node2->right = node5;
    node3->left = node6;
    cout << IsComplete<int>(node1) << endl;
}
 
int main()
{
    test1();
    /*test2();*/
    /*test3();*/
    /*test4();*/
    /*test5();*/
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值