AVL树的实现(C++)

首先定义节点:

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

class Node
{
public:
	Node(int d);
	Node(Node* other);
	int data;
	int height;
	int distance;
	Node* leftChild;
	Node* rightChild;
	Node* father;
	int calculateDistance();
	int calculateheight();
};

Node::Node(int d)
{
	this->data = d;
	father = NULL;
	leftChild = NULL;
	rightChild = NULL;
	height = 1;
	distance = 0;
}

Node::Node(Node* other)
{
	this->data = other->data;
	this->distance = other->distance;
	this->father = other->father;
	this->height = other->height;
	this->leftChild = other->leftChild;
	this->rightChild = other->rightChild;
}

int Node::calculateDistance()
{
	int leftHeight;
	int rightHeight;

	leftHeight = leftChild == NULL? 0 : leftChild->height;
	rightHeight = rightChild == NULL? 0 : rightChild->height;

	return leftHeight-rightHeight;
}

int Node::calculateheight()
{
	int leftHeight;
	int rightHeight;

	leftHeight = leftChild == NULL? 0 : leftChild->height;
	rightHeight = rightChild == NULL? 0 : rightChild->height;

	if(leftHeight > rightHeight)
		return leftHeight+1;
	else
		return rightHeight+1;
}

这里有计算左右子树高度差的函数,左子树高度-右子树的高度。

还有计算该节点在树中的高度,在左右子树的更高者的基础上加1。

然后定义二叉平衡树:

#include"Node.h"

class Tree
{
public:
	Tree();
	void insert(int data);
	bool delete_node(int data);
	int size();
	void display();
private:
	void right_rotate(Node* target);
	void left_rotate(Node* target);
	void pre_order(Node* cur);
	Node* root;
	int count;
};

Tree::Tree()
{
	root = NULL;
	count = 0;
}

void Tree::insert(int data)
{
	if(root == NULL)
		root = new Node(data);
	else
	{
		Node* current = root;
		Node* pre = NULL;
		while(current != NULL)
		{
			pre = current;
			if(data <= current->data)
				current = current->leftChild;
			else
				current = current->rightChild;
		}
		Node* newNode = new Node(data);
		if(data <= pre->data)
			pre->leftChild = newNode;
		else
			pre->rightChild = newNode;  
		newNode->father = pre;
		Node* fatherNode = pre;
		current = newNode;
		while(pre != NULL)
		{
			pre->height = pre->calculateheight();
			pre->distance = pre->calculateDistance();
			if(pre->distance == 2)
			{
				if(pre->leftChild->distance == 1)
				{
					right_rotate(pre);
					pre = pre->father;
				}
				if(pre->leftChild->distance == -1)
				{
					left_rotate(pre->leftChild);
					right_rotate(pre);
					pre = pre->father;
				}
			//	pre = pre->father;
			}
			if(pre->distance == -2)
			{
				if(pre->rightChild->distance == -1)
				{
					left_rotate(pre);
					pre = pre->father;
				}
				if(pre->rightChild->distance == 1)
				{
					right_rotate(pre->rightChild);
					left_rotate(pre);
					pre = pre->father;
				}
				
			}
			current = pre;
			pre = pre->father;
		}
		
	}

	count++;
}

void Tree::left_rotate(Node* target)
{
	Node* tempUp = target->rightChild;
	Node* tempLeft2Right = tempUp->leftChild;

	Node* top = target->father;
	Node* up = new Node(tempUp);
	if(tempUp->leftChild != NULL)
		tempUp->leftChild->father = up;
	if(tempUp->rightChild != NULL)
		tempUp->rightChild->father = up;

	Node* left2right;
	if(tempLeft2Right != NULL)
	{
		left2right = new Node(tempLeft2Right);
		if(tempLeft2Right->leftChild != NULL)
			tempLeft2Right->leftChild->father = left2right;
		if(tempLeft2Right->rightChild != NULL)
			tempLeft2Right->rightChild->father = left2right;
	}
	else
		left2right = NULL;

	if(top != NULL)
	{
		if(top->leftChild == target)
			top->leftChild = up;
		else
			top->rightChild = up;
	}
	up->father = top;
	up->leftChild = target;
	target->father = up;
	target->rightChild = left2right;
	if(left2right != NULL)
		left2right->father = target;

	target->height = target->calculateheight();
	target->distance = target->calculateDistance();
	up->height = up->calculateheight();
	up->distance = up->calculateDistance();
	top->height = top->calculateheight();
	top->distance = top->calculateDistance();

	delete(tempUp);
	delete(tempLeft2Right);

//	target = target->father;

}

void Tree::right_rotate(Node* target)
{
	Node* tempUp = target->leftChild;
	Node* tempRight2Left = tempUp->rightChild;

	Node* top = target->father;
	Node* up = new Node(tempUp);

	if(tempUp->leftChild != NULL)
		tempUp->leftChild->father = up;
	if(tempUp->rightChild != NULL)
		tempUp->rightChild->father = up;
	Node* right2left;

	if(tempRight2Left != NULL)
	{
		right2left = new Node(tempRight2Left);
		if(tempRight2Left->leftChild != NULL)
			tempRight2Left->leftChild->father = right2left;
		if(tempRight2Left->rightChild != NULL)
			tempRight2Left->rightChild->father = right2left;
	}
	else
		right2left = NULL;

	if(top != NULL)
	{
		if(top->leftChild == target)
			top->leftChild = up;
		else
			top->rightChild = up;
	}
	up->father = top;
	up->rightChild = target;
	target->father = up;
	target->leftChild = right2left;
	if(right2left != NULL)
		right2left->father = target;

	target->height = target->calculateheight();
	target->distance = target->calculateDistance();
	up->height = up->calculateheight();
	up->distance = up->calculateDistance();
	top->height = top->calculateheight();
	top->distance = top->calculateDistance();

	delete(tempUp);
	delete(tempRight2Left);

}

int Tree::size()
{
	return count;
}

void Tree::display()
{
	pre_order(root);
}

void Tree::pre_order(Node* cur)
{
	if(cur != NULL)
	{
		pre_order(cur->leftChild);
		printf("%d\n", cur->data);
		pre_order(cur->rightChild);
	}
}

二叉平衡树的关键是,它能够在插入所有元素之后保持平衡,左右子树的高度差不会超过1。所以在每次插入完元素后,检查二叉平衡树是否平衡。只要从插入点开始检查,一直往树的根端检查即可。(其实只需检查一个点)然后确定需要哪种旋转,是单旋转还是双旋转。这里,我用了新的指针来代表旋转所得的新位置。注意指针的指向的改变。

    原文作者:AVL树
    原文地址: https://blog.csdn.net/kuangwanjing626/article/details/8025732
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞