2018.5.2
平衡二叉树(AVL Tree)是任意结点平衡因子BF(左右子树左右高度差)≤1的二叉搜索树。要想建成AVL树,需要在每一个结点插入时进行判断和调整。调整的方法有四种(左左单旋、右右单旋、左右双旋、右左双旋),四种方式分别根据结点插入时的相对结构判断,如下图Figure1的情况为左左单旋调整情况。
本题要求根据输入顺序建一棵AVL树,并且返回其根节点。思路就是AVL树的基本操作了。需要注意的是,给树的每个结点加一个参数代表树高,当左右子树高度差为2时进行调整,每次对树结构调整后也需要对树高值进行调整。具体操作详见代码。
题目描述:
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.
实现代码:
// Root_of_AVLTree.cpp: 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> using namespace std; typedef int ElementType; class AVLNode { public: AVLNode() { } AVLNode(ElementType data, int Height = 0) :data(data),left(NULL), right(NULL),Height(Height){ } ElementType data; AVLNode* left; AVLNode* right; int Height; //树高 }; typedef AVLNode* AVLTree; int GetHeight(AVLTree A); int Max(int a, int b); AVLTree SingleLeftRotation(AVLTree A); //左左单旋 AVLTree SingleRightRotation(AVLTree A); //右右单旋 AVLTree DoubleLeftRightRotation(AVLTree A); //左右双旋 AVLTree DoubleRightLeftRotation(AVLTree A); //右左双旋 AVLTree Insert(AVLTree tree, ElementType element); int main() { int num; cin >> num; AVLTree tree = NULL; for (int i = 0; i < num; i++) { int element; cin >> element; tree = Insert(tree, element); } cout << tree->data; system("pause"); return 0; } int GetHeight(AVLTree A) { if (A) return Max(GetHeight(A->left), GetHeight(A->right)) + 1; else return 0; } int Max(int a, int b) { return a > b ? a : b; } //左左单旋 AVLTree SingleLeftRotation(AVLTree A) { //注意A必须有一个左子结点B //将A与B做左单旋,更新A与B的高度,返回新的结点B AVLTree B = A->left; A->left = B->right; B->right = A; A->Height = Max(GetHeight(A->left), GetHeight(B->right)) + 1; B->Height = Max(GetHeight(B->left), A->Height) + 1; return B; } //右右单旋 AVLTree SingleRightRotation(AVLTree A) { //注意A必须有一个右子结点B //将A与B做右单旋,更新A与B的高度,返回新的结点B AVLTree B = A->right; A->right = B->left; B->left = A; A->Height = Max(GetHeight(A->right), GetHeight(B->left)) + 1; B->Height = Max(GetHeight(B->right), A->Height) + 1; return B; } //左右双旋 AVLTree DoubleLeftRightRotation(AVLTree A) { //A必须有一个左子结点B,且B必须有一个右子节点C //将A、B与C做两次单旋,返回新的根节点C //将B(A->left)与C做右右单旋,将C作为根节点返回给A左子树 A->left = SingleRightRotation(A->left); //将A与C做左左单旋,将C作为根节点返回 return SingleLeftRotation(A); } //右左双旋 AVLTree DoubleRightLeftRotation(AVLTree A) { //A必须有一个右子结点B,且B必须有一个左子节点C //将A、B与C做两次单旋,返回新的根节点C //将B(A->right)与C做左左单旋,将C作为根节点返回给A左子树 A->right = SingleLeftRotation(A->right); //将A与C做右右单旋,将C作为根节点返回 return SingleRightRotation(A); } AVLTree Insert(AVLTree tree, ElementType element) { //若树为空,则新建一个结点 if (!tree) { tree = new AVLNode(element); } //若元素值大于根节点 else if (element < tree->data) { //递归插入tree的左子树 tree->left = Insert(tree->left, element); //如果需要左旋 if (GetHeight(tree->left) - GetHeight(tree->right) == 2) { //左左单旋 if (element < tree->left->data) { tree = SingleLeftRotation(tree); } //左右双旋 else { tree = DoubleLeftRightRotation(tree); } } } //若元素值小于根节点 else if (element > tree->data) { //递归插入tree的右子树 tree->right = Insert(tree->right, element); //如果需要右旋 if (GetHeight(tree->right) - GetHeight(tree->left) == 2) { //右右单旋 if (element > tree->right->data) { tree = SingleRightRotation(tree); } //右左双旋 else { tree = DoubleRightLeftRotation(tree); } } } //更新树高 tree->Height = Max(GetHeight(tree->left), GetHeight(tree->right)) + 1; return tree; }