C语言实现AVL树的判定问题

问题描述

  给定一个二叉树(存储结构采用二叉链表表示),试设计算法判断该二叉树 是否为 AVL 树。

AVL树的概念

  AVL树是一种平衡二叉搜索树,AVL树有一个特点,所有节点的平衡因子的绝对值不能大于1,即所有节点的左子树与右子树的深度差只能为-1,0,1。

需求分析

  判断AVL树的思路很简单,只要判断是否是二叉搜索树,再判断是否带有平衡条件
在这里插入图片描述

代码实现

(1)结构体、全局变量的定义

typedef struct btree{
	int data ;
	struct btree* lchild;
	struct btree* rchild;
}BTree,*Root;

int a[10];//全局变量,用于中序遍历存放节点
int n=0;//全局变量,用于记录每棵二叉树的节点数,并在下次建树前重新归0

(2)AVL树的判断

//判断二叉树是否是AVL树,两个条件:1是搜索树 2.是平衡树
bool isAVL(Root T){
	if(isBST(T) && isBalance(T))
		return true;
	return false;
}

(3)判断二叉树是否是搜索树

  二叉搜索树的概念是所有节点的左孩子都比它小,右孩子都比它大。所以显而易见如果将一棵二叉树以中序遍历输出,那么得到的节点序列就是按照升序排列,依照这个规律就可以判断二叉树是否是搜索树。

bool isBST(Root root){
	InOrder(root);//中序遍历到数组a中
	return isOrdered(a,n);//调用isOrdered函数判断二叉树的中序遍历是否是升序的,如果是,那么此二叉树就是二叉搜索树
}

(4)判断二叉树是否满足平衡条件

  先判断二叉树是否是空,如果是则直接返回true。内部通过递归计算出左子树和右子树的高度,并计算两者差的绝对值。最后通过递归返回所有节点的平衡因子小于等于1的bool值,当且仅当所有节点的平衡因子都满足条件则函数返回true。

//判断二叉树是否是二叉平衡树
bool isBalance(Root root){
	if(!root)
		return true;
	int ldepth=getDepth(root->lchild);
	int rdepth=getDepth(root->rchild);
	int abs_depth=abs(ldepth-rdepth);
	return abs_depth<=1 && isBalance(root->lchild) && isBalance(root->rchild);
}

源代码

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

typedef struct btree{
	int data ;
	struct btree* lchild;
	struct btree* rchild;
}BTree,*Root;

int a[10];//全局变量,用于中序遍历存放节点
int n=0;//全局变量,用于记录每棵二叉树的节点数,并在下次建树前重新归0

Root CreateTree();
void InOrder(Root T);
bool isOrdered(int a[],int length);
bool isBST(Root root);
int getDepth(Root root);
bool isBalance(Root root);
bool isAVL(Root T);
void output();

int main(){
	char c;
	Root T;
	printf("********************AVL树判定程序**************************\n");
	printf("********              注意事项:                  *********\n");
	printf("********          1.以先序遍历输入二叉树          *********\n");
	printf("********          2.空节点用0代替                 *********\n");
	printf("********          3.叶子节点的左右孩子用0代替     *********\n");
	printf("********          4.每输入一个节点后按回车        *********\n");
	printf("***********************************************************\n");
	do{
		printf("***********************************************************\n");
		printf("         Input:\n");
		T = CreateTree();
		getchar();
		printf("         Ouput:\n");
		bool YN=isAVL(T);
		printf("                  此二叉树的中序遍历结果为:");
		output();
		if(YN)
			printf("                  此二叉树是AVL树\n");
		else{
			printf("                  此二叉树不是AVL树\n");
			if(isBST(T))
				printf("                  原因:存在平衡因子超过1的节点\n");
			else 
				printf("                  原因:此二叉树不是二叉搜索树\n");
		}
		n=0;//归零,用于下次判定
		printf("    任意键继续,按0结束程序:");
		c=getchar();
		if(c=='0')
			printf("                     程序结束!\n");
	}while(c!='0');
	return 0;
}

//先序遍历建树
Root CreateTree() {
	Root T;
	int x;
	printf("                  请输入节点:");
	scanf("%d",&x);

	if(x == 0){
		T = NULL;
	}
	else{
		T = (Root)malloc(sizeof(BTree));
		T->data = x; 
		T->lchild = CreateTree();
		T->rchild = CreateTree();
	}
	return T;
}

//判断二叉树是否是AVL树,两个条件:1是搜索树 2.是平衡树
bool isAVL(Root T){
	if(isBST(T) && isBalance(T))
		return true;
	return false;
}

//判断二叉树是否是二叉搜索树
bool isBST(Root root){
	InOrder(root);//中序遍历到数组a中

	return isOrdered(a,n);//调用isOrdered函数判断二叉树的中序遍历是否是升序的,如果是,那么此二叉树就是二叉搜索树
}

//判断二叉树是否是二叉平衡树
bool isBalance(Root root){
	if(!root)
		return true;
	int ldepth=getDepth(root->lchild);
	int rdepth=getDepth(root->rchild);
	int abs_depth=abs(ldepth-rdepth);
	return abs_depth<=1 && isBalance(root->lchild) && isBalance(root->rchild);
}

//以中序遍历的顺序将节点的值的放入数组中
void InOrder(Root T){
	if(T){
		InOrder(T->lchild);
		a[n++]=T->data;//将节点值放入数组中
		InOrder(T->rchild);			
	}
}

//判断数组是否是升序
bool isOrdered(int a[],int length){
	for(int i=0;i<length-1;i++)
		if(a[i]>=a[i+1])
			return false;
	return true;
}

//计算树的深度,isBalance需要的函数
int getDepth(Root root){
	int ldepth,rdepth;
	if(!root)
		return 0;
	else{
		ldepth=getDepth(root->lchild);
		rdepth=getDepth(root->rchild);
		return ldepth>rdepth ? ldepth+1 : rdepth+1;
	}
}
//遍历数组
void output(){
	for(int j=0;j<n;j++)
		printf("%d ",a[j]);
	printf("\n");
}

猜你喜欢

转载自blog.csdn.net/Supreme7/article/details/106639698