AVL树的插入操作

本文深入讲解AVL树的概念、平衡条件及其维护方法。探讨了在插入节点时如何通过单旋转和双旋转保持AVL树的平衡,并提供了具体的实现代码。

AVL tree (Adelson-Velskii-Landis tree)

一颗AVL树是其每个节点的左子树和右子树的高度最多差1的二叉查找树。加了额外的平衡条件是为了确保整棵树的深度为O(logN)

在高度为h的AVL树,最少节点数S(h)=S(h-1)+S(h-2)+1.

============================================================

由于只有“插入至根节点”路径上的各节点可能改变平衡状态,因此,只要调整其中最深的那个节点,可使得整棵树重新获得平衡。

平衡破坏的条件是:假设该最深节点为X,X的左右两颗子树的高度相差2。

据此,将平衡被破坏的情况分为4种:

  1. 插入节点位于X的左子节点的左子树——左左
  2. 插入节点位于X的左子节点的右子树——左右
  3. 插入节点位于X的右子节点的右子树——右右
  4. 插入节点位于X的右子节点的左子树——右左

其中,1,3彼此对称,称为外侧插入,可以采用单旋转调整;2,4彼此对称,称为内侧插入,可以采用双旋转完成。

==========================================================================================

单旋中的右旋:可解决左左


TreeNode* right_rotate(TreeNode* y) {
	TreeNode* x =y->left;
	//第一步:
	y->left = x->right;
	if (x->right) {
		x->right->p = y;
	}
	//第二步:将新的根节点与原来的父节点接上,没有父指针时,可忽略
	x->p = y->p;
	if (y->p == nullptr) {
		;
	}else if (y->p->left == y) {
			y->p->left = x;
	}
	else {
			y->p->right = x;
	}
	//第三步:
	x->right = y;
	y->p = x;
	x->height = max(Height(x->left), Height(x->right)) + 1;
	y->height = max(Height(y->left), Height(y->right)) + 1;
	return x;
}

右旋可分为3步:

1. 将y的左子树指向x的右子树

2. 因为这里有父指针,新的根节点x要与y原来的父节点接上,如果原来的y不是root的话;

3. 将x的右孩子指向y.


左右情况的解决:双旋中的先对X的左子树左旋,在对X右旋,这里的X认为是值为5的节点。


#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

struct TreeNode {
	TreeNode* left;
	TreeNode* right;
	TreeNode* p;
	int height;
	int val;
	TreeNode() {
		left = right =p= nullptr;
		val = 0;
		height = 0;
	}
	TreeNode(int v) {
		left = right = p = nullptr;
		val = v;
		height = 0;
	}
};
static int Height(TreeNode* p) {
	if (p == nullptr)
		return -1;
	else return p->height;
}
//中序遍历
void inorder_walk1(TreeNode* root) {
	TreeNode* p = root;
	stack<TreeNode*> s;
	while (p || !s.empty()) {
		while(p) {
			s.push(p);
			p = p->left;
		}
		if (!s.empty()) {
			p = s.top();
			cout <<p ->val << " ";
			s.pop();
			p = p->right;
		}
	}
}
void inorder_walk2(TreeNode* root) {
	
	if (!root) return;
	
	inorder_walk2(root->left);
	cout << root->val << " ";
	inorder_walk2(root->right);
}
//先序遍历
void preorder_walk1(TreeNode* root) {
	TreeNode* p = root;
	stack<TreeNode*> s;
	while (p || !s.empty()) {
		while (p) {
			cout << p->val << " ";
			s.push(p);
			p = p->left;
		}
		if (!s.empty()) {
			p = s.top();
			s.pop();
			p = p->right;
		}
	}
}
void preorder_walk2(TreeNode* root) {

	if (!root) return;
	cout << root->val << " ";
	preorder_walk2(root->left);
	
	preorder_walk2(root->right);
}
//破坏平衡条件,旋转
TreeNode* left_rotate( TreeNode* x) {
	TreeNode* y = x->right;
	x->right = y->left;
	if (y->left) {
		y->left->p = x;
	}

	y->p = x->p;
	if (x->p == nullptr) {
		;
	}
	else if (x->p->left == x) {
		x->left->p = y;
	}
	else {
		x->right->p = y;
	}
	y->left = x;
	x->p = y;
	x->height = max(Height(x->left), Height(x->right)) + 1;
	y->height = max(Height(y->left), Height(y->right)) + 1;
	return y;
}
TreeNode* right_rotate(TreeNode* y) {
	TreeNode* x =y->left;
	//第一步:
	y->left = x->right;
	if (x->right) {
		x->right->p = y;
	}
	//第二步:将新的根节点与原来的父节点接上,没有父指针时,可忽略
	x->p = y->p;
	if (y->p == nullptr) {
		;
	}else if (y->p->left == y) {
			y->p->left = x;
	}
	else {
			y->p->right = x;
	}
	//第三步:
	x->right = y;
	y->p = x;
	x->height = max(Height(x->left), Height(x->right)) + 1;
	y->height = max(Height(y->left), Height(y->right)) + 1;
	return x;
}
TreeNode* double_right_rotate(TreeNode* k3)//左右
{
	 k3->left=left_rotate(k3->left);
	return right_rotate(k3);
}
TreeNode* double_left_rotate(TreeNode* k3)//右左
{
	k3->right = right_rotate(k3->right);
	return left_rotate(k3);
}

//插入新节点
TreeNode* insert_node(TreeNode* root, int v) {
	if (root == nullptr) {
		return new TreeNode(v);
	}
	TreeNode* node = new TreeNode(v);
	if (v < root->val) {
		root->left = insert_node(root->left, v);
		
		
		if (Height(root->left) - Height(root->right) == 2) {//插入后破坏了平衡条件
			if (v < root->left->val)//左左
				root = right_rotate(root);
			else
				root = double_right_rotate(root);
		}
	}
	else if (v > root->val) {
		root->right = insert_node(root->right, v);
		
		if (Height(root->right) - Height(root->left) == 2) {
			if (v > root->right->val)
				root = left_rotate(root);
			else
				root = double_left_rotate(root);
		}
	}
	root->height = max(Height(root->left), Height(root->right)) + 1;
	return root;
}
int main() {
//	int iv[9] = { 22,18,26,14,20,24,12,16 ,15};
	int iv[9] = { 5,2,6,1,3,4 };
	TreeNode* root = nullptr;
	for (int i = 0; i < 6; i++) {
		root = insert_node(root, iv[i]);
	}
	cout << "中序1:";
	inorder_walk1(root); 
	cout << endl;
	cout << "中序2:";
	inorder_walk2(root);
	cout << endl;
	cout << "先序1:";
	preorder_walk1(root);
	cout << endl;
	cout << "先序2:";
	preorder_walk2(root);
	cout << endl;
	system("pause");
}


下面是对左右情况例子的输出




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值