#数据结构与算法学习笔记#剑指Offer37:是否平衡二叉树/AVL树 + 测试用例(Java、C/C++)

2018.11.3     《剑指Offer》从零单刷个人笔记整理(66题全)目录传送门​​​​​​​

关于AVL树/平衡二叉树的原理和实现可以见之前写过的#数据结构与算法学习笔记#PTA13:平衡二叉搜索树的根 Root of AVL Tree(C/C++)。这道题要求判断是否是一棵AVL树(不要求平衡)。

前几天有用递归实现了二叉树的深度#数据结构与算法学习笔记#剑指Offer36:二叉树的深度(Java),因此可以对每个结点先序遍历进行一次平衡验证,只要确定每个结点都是平衡的,那就可以说明这是一棵平衡二叉树。

不过这样就会对多个结点重复遍历多次。还有一种方法可以对每个结点只遍历一次。

将检查平衡的遍历方式改为后序遍历,可以做到对每个结点只进行一次访问。设定非平衡返回标志值-1,一旦发现不平衡结点立即返回至根节点,可以对算法进行剪枝处理。


题目描述

输入一棵二叉树,判断该二叉树是否是平衡二叉树。


Java实现:

/**
 * 
 * @author ChopinXBP
 * 输入一棵二叉树,判断该二叉树是否是平衡二叉树。
 * 
 */

public class IsBalancedTree_37 {

	public static class TreeNode {
	    int val = 0;
	    TreeNode left = null;
	    TreeNode right = null;

	    public TreeNode(int val) {
	        this.val = val;

	    }

	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TreeNode root1 = new TreeNode(2);
		TreeNode root2 = new TreeNode(1);
		TreeNode root3 = new TreeNode(0);
		TreeNode root4 = new TreeNode(3);
		TreeNode root5 = new TreeNode(4);
		root1.left = root2;
		root2.left = root3;
		//root3.right = root4;
		root1.right = root5;
		System.out.println(IsBalanced_Solution2(root1));
	}

	
	///////////////对每个结点计算深度的方法,重复遍历了结点///////////////////////
    public static boolean IsBalanced_Solution(TreeNode root) {  
    	if(root == null) return true;
        if(Math.abs(GetDepth(root.left) - GetDepth(root.right)) > 1) return false;
        
        //return isSearchTree(root);
        return true;
    }
    
    private static int GetDepth(TreeNode root){
    	if(root == null)return 0;
    	return Math.max(GetDepth(root.left), GetDepth(root.right)) + 1;
    }
    /*
    //判断搜索树
    private static boolean isSearchTree(TreeNode root){
    	if(root == null) return true;
    	boolean rootflag = true;
    	if(root.left != null && root.val < root.left.val)rootflag = false;
    	if(root.right != null && root.val > root.right.val)rootflag = false;
    	
    	return rootflag && isSearchTree(root.left) && isSearchTree(root.right);
    }
    */
    
    ///////////////对每个结点只遍历一次,并且进行剪枝处理///////////////////////
    public static boolean IsBalanced_Solution2(TreeNode root) {  
    	if(getTreeDepth(root) == -1)return false;
        return true;
    }
    
    private static int getTreeDepth(TreeNode root){
    	if(root == null)return 0;
    	int leftdepth = getTreeDepth(root.left);
    	if(leftdepth == -1)return -1;		//剪枝处理,一旦出现不平衡,直接返回-1至初始
    	int rightdepth = getTreeDepth(root.right);
    	if(rightdepth == -1)return -1;
    	
    	if(Math.abs(leftdepth - rightdepth) <= 1){
    		return Math.max(leftdepth, rightdepth) + 1;
    	}else{
    		return  -1;		//-1代表不平衡
    	}
    }
}

C++实现示例:

//后续遍历二叉树,遍历过程中求子树高度,判断是否平衡
class Solution {
public:
    bool IsBalanced(TreeNode *root, int & dep){
        if(root == NULL){
            return true;
        }
        int left = 0;
        int right = 0;
        if(IsBalanced(root->left,left) && IsBalanced(root->right, right)){
            int dif = left - right;
            if(dif<-1 || dif >1)
                return false;
            dep = (left > right ? left : right) + 1;
            return true;
        }
        return false;
    }
    bool IsBalanced_Solution(TreeNode* pRoot) {
        int dep = 0;
        return IsBalanced(pRoot, dep);
    }
};

测试代码:

// ====================测试代码====================
void Test(char* testName, BinaryTreeNode* pRoot, bool expected)
{
    if(testName != NULL)
        printf("%s begins:\n", testName);

    printf("Solution1 begins: ");
    if(IsBalanced_Solution1(pRoot) == expected)
        printf("Passed.\n");
    else
        printf("Failed.\n");

    printf("Solution2 begins: ");
    if(IsBalanced_Solution2(pRoot) == expected)
        printf("Passed.\n");
    else
        printf("Failed.\n");
}

// 完全二叉树
//             1
//         /      \
//        2        3
//       /\       / \
//      4  5     6   7
void Test1()
{
    BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);
    BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
    BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
    BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
    BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
    BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
    BinaryTreeNode* pNode7 = CreateBinaryTreeNode(7);

    ConnectTreeNodes(pNode1, pNode2, pNode3);
    ConnectTreeNodes(pNode2, pNode4, pNode5);
    ConnectTreeNodes(pNode3, pNode6, pNode7);

    Test("Test1", pNode1, true);

    DestroyTree(pNode1);
}

// 不是完全二叉树,但是平衡二叉树
//             1
//         /      \
//        2        3
//       /\         \
//      4  5         6
//        /
//       7
void Test2()
{
    BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);
    BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
    BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
    BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
    BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
    BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
    BinaryTreeNode* pNode7 = CreateBinaryTreeNode(7);

    ConnectTreeNodes(pNode1, pNode2, pNode3);
    ConnectTreeNodes(pNode2, pNode4, pNode5);
    ConnectTreeNodes(pNode3, NULL, pNode6);
    ConnectTreeNodes(pNode5, pNode7, NULL);

    Test("Test2", pNode1, true);

    DestroyTree(pNode1);
}

// 不是平衡二叉树
//             1
//         /      \
//        2        3
//       /\         
//      4  5        
//        /
//       6
void Test3()
{
    BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);
    BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
    BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
    BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
    BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
    BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);

    ConnectTreeNodes(pNode1, pNode2, pNode3);
    ConnectTreeNodes(pNode2, pNode4, pNode5);
    ConnectTreeNodes(pNode5, pNode6, NULL);

    Test("Test3", pNode1, false);

    DestroyTree(pNode1);
}


//               1
//              /
//             2
//            /
//           3
//          /
//         4
//        /
//       5
void Test4()
{
    BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);
    BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
    BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
    BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
    BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);

    ConnectTreeNodes(pNode1, pNode2, NULL);
    ConnectTreeNodes(pNode2, pNode3, NULL);
    ConnectTreeNodes(pNode3, pNode4, NULL);
    ConnectTreeNodes(pNode4, pNode5, NULL);

    Test("Test4", pNode1, false);

    DestroyTree(pNode1);
}

// 1
//  \
//   2
//    \
//     3
//      \
//       4
//        \
//         5
void Test5()
{
    BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);
    BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
    BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
    BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
    BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);

    ConnectTreeNodes(pNode1, NULL, pNode2);
    ConnectTreeNodes(pNode2, NULL, pNode3);
    ConnectTreeNodes(pNode3, NULL, pNode4);
    ConnectTreeNodes(pNode4, NULL, pNode5);

    Test("Test5", pNode1, false);

    DestroyTree(pNode1);
}

// 树中只有1个结点
void Test6()
{
    BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);
    Test("Test6", pNode1, true);

    DestroyTree(pNode1);
}

// 树中没有结点
void Test7()
{
    Test("Test7", NULL, true);
}

int _tmain(int argc, _TCHAR* argv[])
{
    Test1();
    Test2();
    Test3();
    Test4();
    Test5();
    Test6();
    Test7();

    return 0;
}

#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

你可能感兴趣的:(C/C++,JAVA,数据结构与算法)