1. 程式人生 > >AVL樹(考研的同學需要注意其定義)的判定(某公司2012年校園招聘筆試題目)

AVL樹(考研的同學需要注意其定義)的判定(某公司2012年校園招聘筆試題目)

       平衡二叉樹又叫AVL(人名的簡稱)樹,在不同的教材中,對AVL樹的定義是不同的。考研指定的教材是嚴奶奶編寫的教材,我們來看看該書上(P233)是如何定義的:

       AVL樹或者是一棵空樹,或者滿足以下條件:

      (1). 其左子樹和右子樹都為AVL樹

      (2). 左子樹和右子樹的高度之差的絕對值不超過1

       然而,有很多教材不是這麼定義的,而是把AVL樹定義在BST基礎之上,比如在李春葆的2012版的《資料結構聯考輔導教程》中(P174)就定義在BST基礎之上,但是,該書第184頁碼的judgeAVL函式就沒有考慮AVL樹的BST性質。

       在這裡,我們依然按照嚴奶奶的定義來辦事。

       下面對AVL樹進行判定:

#include <iostream>
using namespace std;

typedef struct node
{
	int key;
	struct node *lChild, *rChild;
}Node;

// 生成一個結點
Node *createNode(int i)
{
	Node * q = new Node;
	q->lChild = NULL;
	q->rChild = NULL;
	q->key = i;

	return q;
}

// 非AVL樹
Node *createNotAVLTree()
{
	Node *p1 = createNode(1);
	Node *p2 = createNode(2);
	Node *p3 = createNode(3);
	Node *p4 = createNode(4);

	p1->lChild = p2;
	p1->rChild = NULL;
	
	p2->lChild = p3;
	p2->rChild = p4;

	p3->lChild = p3->rChild = NULL;
	p4->lChild = p4->rChild = NULL;

	return p1;
}

// AVL樹
Node *createAVLTree()
{
	Node *p1 = createNode(1);
	Node *p2 = createNode(2);
	Node *p3 = createNode(3);
	Node *p4 = createNode(4);

	p1->lChild = p2;
	p1->rChild = p4;
	
	p2->lChild = p3;
	p2->rChild = NULL;

	p3->lChild = p3->rChild = NULL;
	p4->lChild = p4->rChild = NULL;

	return p1;
}

void AVLTest(Node *T, int &isAVL, int &height)
{
	int bLeft, bRight;
	int hLeft, hRight;
	if(NULL == T)
	{
		height = 0;
		isAVL = 1;
	}
	else if(NULL == T->lChild && NULL == T->lChild)
	{
		height = 1;
		isAVL = 1;
	}
	else
	{
		AVLTest(T->lChild, bLeft, hLeft);
		AVLTest(T->rChild, bRight, hRight);
		height = (hLeft < hRight ? hRight : hLeft) + 1; // 樹高
		if(abs(hLeft - hRight) < 2) // AVL樹的要求
		{
			isAVL = bLeft & bRight; // 同時為1才是AVL樹
		}
		else
		{
			isAVL = 0;
		}

	}	
}

bool isAVLTree(Node *T)
{
	int isAVL = 0;
	int height = 0;
	AVLTest(T, isAVL, height);

	if(1 == isAVL)
		return true;

	return false;
}

void printJudge(Node *T)
{
	if(isAVLTree(T))
		cout << "yes" << endl;
	else
		cout << "no" << endl;
}

int main()
{
	Node *T = NULL;
	printJudge(T);  // yes

	T = createNotAVLTree();
	printJudge(T);  // no

	T = createAVLTree();
	printJudge(T);  // yes

	return 0;
}
      上面的程式比較巧妙,需要好好體會。另外,需要感嘆一下:在寫程式的時候,經常把lChild和rChild寫錯(寫反),所以,在以後的程式中,儘量把lChild寫成leftChild, 把rChild寫成rightChild.