#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string>
using namespace std;
/*
问题:实现一个函数,检查二叉树是否平衡。在这个问题中,平衡树的定义如下:任意一个节点,其两颗子树的高度差不超过1.
分析:关于树的大部分问题都是和递归相关。
所以如果一棵树的左子树的高度和右子树各自平衡,且这两颗子树的高度之差不超过1即可。
递归基:
isAVLTree(Tree* head)
{
//如果还树为空,一定是平衡的
if(NULL == head)
{
return true
}
}
这里的关键是需要记录树的高度,最好能做成根据节点就能知道高度
输入:
输入可能包含多个测试样例,输入以EOF结束。
对于每个测试案例,输入的第一行一个整数n(1<=n<=1000, :n代表将要输入的二叉树元素的个数(节点从1开始编号)。接下来一行有n个数字,代表第i个二叉树节点的元素的值。接下来有n行,每行有一个字母Ci。
Ci=’d’表示第i个节点有两子孩子,紧接着是左孩子编号和右孩子编号。
Ci=’l’表示第i个节点有一个左孩子,紧接着是左孩子的编号。
Ci=’r’表示第i个节点有一个右孩子,紧接着是右孩子的编号。
Ci=’z’表示第i个节点没有子孩子。
输出:
样例输入:
6
8 6 5 7 10 9
d 2 5
d 3 4
z
z
l 6
z
9
8 6 5 7 10 9 11 13 15
d 2 5
d 3 4
z
z
d 6 7
l 8
z
r 9
z
样例输出:
Is AVL Tree!
Not AVL Tree!
关键:
1 判断平衡二叉树,可以用: 在判断AVL树的过程中计算左右子树的高度,时间复杂度为O(NlogN)
2 考虑到高度可以用于计算高度,也可以用于判断左右子树是否平衡,
当左右子树高度差>1,此时返回-1表示不平衡;否则返回: 左右子树高度中的较大值+1 作为当前节点的高度
int checkHeight(TreeNode* pHead)
{
if(NULL == pHead)
{
return 0;
}
//获取左子树高度
int leftHeight = checkHeight(pHead->_pLeft);
if(leftHeight == -1)
{
return -1;
}
//获取右子树高度
int rightHeight = checkHeight(pHead->_pRight);
if(rightHeight == -1)
{
return -1;
}
//如果左右子树都分别平衡,那么计算当前节点是否平衡
int heightDiff = abs(rightHeight - leftHeight);
if(heightDiff > 1)
{
return -1;
}
//如果树是平衡的,返回该树的高度 = 左右子树高度的较大值 + 1
else
{
return max(leftHeight , rightHeight) + 1;
}
}
牛逼
*/
typedef struct TreeNode
{
TreeNode():_value(-1),_pLeft(NULL),_pRight(NULL),_pParent(NULL){}
int _value;
//树中肯定包含左子树和右子树,还包括当前节点自身的值
TreeNode* _pLeft;
TreeNode* _pRight;
TreeNode* _pParent; // 父节点,根节点的父节点为空,高度
int _index; //创建的节点的下标
}TreeNode;
//关键就设置一个节点数组
const int MAXSIZE = 1001;
TreeNode g_treeNodeArray[MAXSIZE];
int g_index; //用于标示创建的节点的下标
//创建节点
TreeNode* createNode()
{
//先使节点标记累加,初始化节点中左右孩子的值为NULL
++g_index;
g_treeNodeArray[g_index]._pLeft = g_treeNodeArray[g_index]._pRight = g_treeNodeArray[g_index]._pParent = NULL;
return &g_treeNodeArray[g_index];
}
//获取树的顶点
TreeNode* getTreeHeadNode(TreeNode* pNode)
{
//如果当前传入的节点为空,就直接返回该树的顶点为空
if(NULL == pNode)
{
return NULL;
}
//根据树的顶点没有父节点,因此如果某个节点的父节点为空,该节点就是树的顶点
if(NULL == pNode->_pParent)
{
return pNode;
}
return getTreeHeadNode(pNode->_pParent);
}
int max(int a, int b)
{
return a > b ? a : b;
}
//该函数的作用是:如果pHead为树的顶点的树是平衡的,则返回以pHead为顶点的树的高度;否则,返回-1表示已pHead为顶点的树是不平衡的
int checkHeight(TreeNode* pHead)
{
if(NULL == pHead)
{
return 0;
}
//获取左子树高度
int leftHeight = checkHeight(pHead->_pLeft);
if(leftHeight == -1)
{
return -1;
}
//获取右子树高度
int rightHeight = checkHeight(pHead->_pRight);
if(rightHeight == -1)
{
return -1;
}
//如果左右子树都分别平衡,那么计算当前节点是否平衡
int heightDiff = abs(rightHeight - leftHeight);
if(heightDiff > 1)
{
return -1;
}
//如果树是平衡的,返回该树的高度 = 左右子树高度的较大值 + 1
else
{
return max(leftHeight , rightHeight) + 1;
}
}
bool isAVLTree(TreeNode* head)
{
int height = checkHeight(head);
if(height == -1)
{
return false;
}
else
{
return true;
}
}
int main(int argc, char* argv[])
{
int nodeNum;
int value;
string childFlag;
int leftChild;
int rightChild;
while(cin >> nodeNum)
{
g_index = 0;
//输入n个树节点对应的值,实际上就是创建节点
for(int i = 0 ; i < nodeNum ; i++)
{
cin >> value;
TreeNode* pNode = createNode();
pNode->_value = value;
}
//接下来就是对n个节点的孩子节点进行赋值
for(int i = 1 ; i <= nodeNum ; i++)
{
cin >> childFlag;
if("d" == childFlag)
{
cin >> leftChild >> rightChild;
g_treeNodeArray[i]._pLeft = &g_treeNodeArray[leftChild];
g_treeNodeArray[i]._pRight = &g_treeNodeArray[rightChild];
//注意设置父节点的指向,否则无法从任意节点推算根节点
g_treeNodeArray[leftChild]._pParent = &g_treeNodeArray[i];
g_treeNodeArray[rightChild]._pParent = &g_treeNodeArray[i];
}
else if("l" == childFlag)
{
cin >> leftChild;
g_treeNodeArray[i]._pLeft = &g_treeNodeArray[leftChild];
g_treeNodeArray[leftChild]._pParent = &g_treeNodeArray[i];
}
else if("r" == childFlag)
{
cin >> rightChild;
g_treeNodeArray[i]._pRight = &g_treeNodeArray[rightChild];
g_treeNodeArray[rightChild]._pParent = &g_treeNodeArray[i];
}
//没有孩子节点无需处理
else if("z" == childFlag)
{
}
else
{
cout << "command is error!" << endl;
}
}
//获取树的顶点
TreeNode* pHead = getTreeHeadNode( &g_treeNodeArray[1] );
//高度验证正确后,判断平衡树就可以了
bool isAVL = isAVLTree(pHead);
if(isAVL)
{
cout << "Is AVL Tree!" << endl;
}
else
{
cout << "Not AVL Tree!" << endl;
}
}
getchar();
return 0;
}
程序员面试金典: 9.4树与图 4.1实现一个函数检查二叉树是否平衡——O(N)时间解法
最新推荐文章于 2022-11-03 19:08:28 发布