数据结构与算法总结——平衡二叉树(未完待续)

AVL树

  • 一般的二叉树只有在输入完全随机时才能实现nlogn的复杂度,最坏可到达n^2
  • AVL树保证每个子根的左右子树的高度最大相差1,从而保证了nlogn的复杂度
  • 除了插入和删除外,其余操作的实现和普通二叉树无异
  • 主要多的操作就是左右旋转来实现再平衡
  • 和红黑树相比,AVL树的搜索操作更快,但是插入和删除操作更慢
#pragma once
#ifndef AVL_H
#define AVL_H
#include <iostream>

template<typename Comparable>
class AVL
{
	struct Node
	{
		Comparable elements;
		Node* left;
		Node* right;
		size_t height;

		Node(Comparable Elements, Node* Left, Node* Right, size_t Height)
			:elements(Elements), left(Left), right(Right), height(Height) {}
	};

	Node* root;

public:
	AVL();
	void insert(Comparable x);
	void remove(Comparable x);


private:
	void insert(Comparable&& x, Node* & t); //注意要使用引用来改变t
	int height(Node* t);
	int balanceFactor(Node* t);
	void changeHeight(Node* t);
	void balance(Node* t);
	void LLrotation(Node* & t);
	void LRrotation(Node* & t);
	void RRrotation(Node* & t);
	void RLrotation(Node* & t);
	void remove(Comparable&& x, Node* & t);
};

#endif // !AVL_H


#include "AVL.h"

template<typename Comparable>
AVL<Comparable>::AVL() :
	root(nullptr) {}

template<typename Comparable>
void AVL<Comparable>::insert(Comparable x)
{
	insert(std::move(x), root);
}

template<typename Comparable>
void AVL<Comparable>::remove(Comparable x)
{
	remove(std::move(x), root);
}


/*

private function

*/

template<typename Comparable>
void AVL<Comparable>::remove(Comparable&& x, Node* & t)
{
	if (t == nullptr)
		return;

	if (x < t->elements)
		remove(std::move(x), t->left);
	else if (x > t->elements)
		remove(std::move(x), t->right);
	else
	{
		if (t->left == nullptr && t->right == nullptr)
		{
			delete t;
			t = nullptr; //不要忘了这一步
		}
		else if (t->left == nullptr || t->right == nullptr)
		{
			auto temp = t;
			if (t->left == nullptr)
			{
				t = t->right;
				delete temp;
			}
			else
			{
				t = t->left;
				delete temp;
			}
		}
		else 
		{
			auto & repalce = findMax(t->left);
			t->elements = repalce->elements;
			auto temp = repalce;
			repalce = repalce->left;
			delete temp;
		}
	}

	balance(t);
}

template<typename Comparable>
void AVL<Comparable>::insert(Comparable&& x, Node* & t)
{
	if (t == nullptr)
		t = new Node(std::move(x), nullptr, nullptr, 0);//这里必须显示调用std::move,因为虽然x指向一个右值,但是x本身是一个左值
	else if (x < t->elements)
		insert(std::move(x), t->left); //注意这里也要用move
	else if (x > t->elements)
		insert(std::move(x), t->right);
	else
		;

	balance(t);
}

template<typename Comparable>
int AVL<Comparable>::height(Node* t)
{
	if (t == nullptr)
		return -1;
	else
		return t->height;
}

template<typename Comparable>
int AVL<Comparable>::balanceFactor(Node* t)
{
	if (t == nullptr)
		return 0;

	return t->left->height - t->right->height;
}

template<typename Comparable>
void AVL<Comparable>::changeHeight(Node* t)
{
	if (t == nullptr)
		return;

	int left = height(t->left);
	int right = height(t->right);
	t->height = left < right ? right : left;
}

template<typename Comparable>
void AVL<Comparable>::balance(Node* t)
{
	if (t == nullptr)
		return;

	int factor = balanceFactor(t);

	if (factor > 1)
	{
		if (balanceFactor(t->left) >= 0) //>=而不是>的原因在于删除
			LLrotation(t);
		else
			LRrotation(t);
	}
	else if (factor < -1)
	{
		if (balanceFactor(t->right) <= 0)
			RRrotation(t);
		else
			RLrotation(t);
	}
	else
		changeHeight(t);

}

template<typename Comparable>
void AVL<Comparable>::RRrotation(Node* & t)
{
	auto right = t->right;
	auto rightLeft = right->left;
	t->right = rightLeft;
	right->left = t;
	t = right;
	changeHeight(t);
	changeHeight(t->right);
}

template<typename Comparable>
void AVL<Comparable>::LLrotation(Node* & t)
{
	auto left = t->left;
	auto leftRight = left->right;
	t->left = leftRight;
	left->right = t;
	t = left;
	changeHeight(t);
	changeHeight(t->left);
}

template<typename Comparable>
void AVL<Comparable>::RLrotation(Node* & t)
{
	LLrotation(t->left);
	RRrotation(t);
}

template<typename Comparable>
void AVL<Comparable>::LRrotation(Node* & t)
{
	RRrotation(t->right);
	LLrotation(t);
}







标准红黑树

  • 实现原理来自《算法导论》
  • 每个子根的左右子树高度最多相差一倍
  • C++中的STL标准库中的set和map就是用红黑树实现的
    (具体代码待续)

左倾红黑树

  • 实现来自于《算法》第四版
  • 规定红色节点只能为左节点
  • 实现更为简单,但是性能比标准版较差
    (具体代码待续)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值