BST—AVL树——数据结构

7-1 Root of AVL Tree (25 分)
An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.

Now given a sequence of insertions, you are supposed to tell the root of the resulting AVL tree.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤20) which is the total number of keys to be inserted. Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:
For each test case, print the root of the resulting AVL tree in one line.

Sample Input 1:
5
88 70 61 96 120
Sample Output 1:
70
Sample Input 2:
7
88 70 61 96 120 90 65
Sample Output 2:
88
作者: 陈越
单位: 浙江大学
时间限制: 400 ms
内存限制: 64 MB
代码长度限制: 16 KB
可以看到上面这个题是一个非常非常非常明显的AVL树,据学长说AVL树是鼻祖平衡树,那么还有什么样子的平衡呢?我也不知道,我也没见过,我就做过这一个平衡树,遇到别的,咱以后再说,下面咱们分析分析这个代码。
AVL树的原理其实就是那四种变化,left_left_rotation right_right_rotation left_right_rotation right_left_rotation. 那么具体是怎么rotation的咱就不说了,我觉得这个代码难得不是出在怎么rotation得,是对高度系统和函数返回值得问题上(我所出现得问题),下面我就我出现得问题做一些注释。

#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std;
struct node
{
	int data;
	struct node* left;
	struct node* right;
	int height;
};
typedef struct node* avl;
int get_height(avl T)
{
	if(!T) return -1;
	else return T->height;//那么我们可以看到,这里有个指针不是空,就直接返回高度,这是因为,我们只有在执行完插入操作之后才会调用get——height()函数,执行完之后我们会对新节点进行赋值,然后一层一层的往回倒,倒车的过程中我们更新路径中每一个节点的高度值,那么有些人可能有疑问,那你更新是最后更新,中间的操作怎么办,那我们现在调到create函数
};//其次我想说的是有关于高度系统的介绍,关于树的深度高度的这些名词定义,不一样的书上也不一样的叫法,所以看着不爽的人你也别跟我巴巴,我是个祖安人,你也别挑战我,你就听我说就行了,这里的高度,我们定义为取左子树或右子树高度的最大值加一,这就是根节点的高度。
avl llr(avl k1)
{
	avl k2 = k1->left;
	k1->left = k2->right;
	k2->right = k1;
	k1->height = max(get_height(k1->left),get_height(k1->right))+1;//原来的根节点变成了右子树,所以先确定子树的高度,才能确定根的高度 
	k2->height = max(get_height(k2->left),get_height(k2->right))+1;
	return k2; 
};
avl rrr(avl k1)
{
	avl k2 = k1->right;
	k1->right = k2->left;
	k2->left = k1;
	k1->height = max(get_height(k1->left),get_height(k1->right))+1;
	k2->height = max(get_height(k2->left),get_height(k2->right))+1;
	return k2;
}
avl lrr(avl k1)
{
	k1->left = rrr(k1->left);
	return llr(k1);
}
avl rlr(avl k1)
{
	k1->right = llr(k1->right);
	return rrr(k1);
}
avl create(int x,avl T)
{
	if(T == NULL)
	{
		T = (avl)malloc(sizeof(struct node));
		T->data = x;
		T->left = T->right = NULL;
		T->height = 0;//我们可以看到,再调用之后,也就是在那四种操作中,又会更新高度,所以我们不必担心
	}
	else
	{
		if(x < T->data)
		{
			T->left = create(x,T->left);
			if(get_height(T->left) - get_height(T->right) == 2)
			{
				if(x < T->left->data)
					T = llr(T);
				else
					T = lrr(T);
			}
				
		}
		else
		{
			T->right = create(x,T->right);
			if(get_height(T->right) - get_height(T->left) == 2)
			{
				if(x > T->right->data)
					T = rrr(T);
				else
					T = rlr(T);
			}
		}
	}
	T->height = max(get_height(T->left),get_height(T->right))+1;//这一步是因为,如果插入之后依旧是平衡的,那么我们依然要更新路径上的高度,如果没有,平衡的树的高度就不会更新
	return T;
}
int main()
{
	int n;
	avl T = NULL;
	cin>>n;
	for(int i = 0;i < n; i++)
	{
		int x;
		cin>>x;
		T = create(x,T);//首先,我想说一下关于这个create函数的返回值问题,我们知道,avl树是建立在BST之上的,在BST的建立过程中,我们可以有返回值,参数只是放value,返回的是node类型的指针,也可以没有返回值,那么我们需要使用&引用符号,加一个引用类型的node指针参数,那么我们在创建AVl树时,因为在函数中需要用到node所以我们必须在参数中加一个node类型的指针
	}
	cout<<T->data<<endl;
	return 0;
}
发布了35 篇原创文章 · 获赞 0 · 访问量 946

猜你喜欢

转载自blog.csdn.net/ACM_Cmy/article/details/103124785