バランスのとれたツリーの概要

**

バランスのとれたツリーの概要

**
当初から、最近、クラスのバランスの取れたツリーデータ構造の説明と併せて、新しい学習AVL木の初めから、長い時間のために中央をあきらめて、理解していない大きな木のAVL木が回転するためにバランスされているかを理解するために、そして最後に、私は結果の比較を取得するには満足して、図慶功寫真を入れここに画像を挿入説明、ここで間違っているが、神ベンはまた、コメント領域に神のRANで感謝を指摘してください場合、私は、AVLツリーを勉強していたときにいくつかのアイデアをしています。

AVLツリーは、我々は、例えば、平衡二分探索木を確立して、1を超えていないツリーの各非リーフノードのサブツリーの高さです。

次の文は、純粋に個人的な意見です!

  1. RR、RL、LL、LRの回転:個人的に難易度が不均衡を回転しているAVL木のノードということだと思います。
  2. 付加AVL木でより回転動作よりも、任意の通常のツリー異なるではありません。
    その複雑で過回転可能なアクションの完了後にツリーを再作成しますので、私が決定しますので、最適なソリューションを見つけるための直接的な方法は、決定木のバランスがすべてのことを確実にするために、挿入され、その後、直接回転させるかどうか、存在しません挿入ツリーは、バランス係数がアンバランスノード2または-2であることを保証するために、それによって、平衡ツリーです。ここでは、唯一の回転RRおよびRL、LLとLRの類推が可能話し合います。

ここでは、回転AVL木の操作の私の理解のいくつかである:
回転操作を実行するには3、我々は最初の図面のいくつかを置く場所の理解を容易にするために、この場合にはどうするかを理解する必要があります。

ここに画像を挿入説明

ここに画像を挿入説明

ここに画像を挿入説明
ここに画像を挿入説明図はアンバランスであり、非バランス係数2であり、R *回転操作であると判断することができる4つの主ルートノード上に描か。バランス係数が1で両方の後に、次いで不平衡ノードは前者2つのバランス因子の右サブツリーを発見観察-1ので、前者は回転可能後者の二つの回転可能RRの両方のために決定することができることはRLです。(いくつかは、それが最後のノードが一致しないRR及びRL、区別するために、左または右のサブツリーサブツリーに挿入されることが観察されるべきであると思うかもしれ、反例があるコメント欄でそれを歓迎します)。

  1. 下面我们来具体的谈论一下RR旋转的操作。
    为方便理解,在这里先放张图
    ここに画像を挿入説明这个图是上面图1的精简版可以很清楚的看出RR旋转操作的本质—将中间节点上提以达到减少树高的目的。具体操作步骤为1:备份1号节点并用2号节点覆盖1号节点,2:把2号节点的左子树赋值为已备份的一号节点。
    看起来很简单,但实际上有一个问题,如果原本的2号节点有左儿子。上面的图1便是个很好的例子,在这里因为要考虑到二叉检索树的性质(根比左儿子大,比右儿子小)并为了使算法不过分啰嗦,我给出的解决方案是

ここに画像を挿入説明左面看不清看上面图一吧…

如图:依然是将中间的c节点上提,原本是C节点的左子树的D节点变成了A节点的右子树。这样写保证了二叉检索树的性质。同时因为C节点上提A的右子树一定为空。所以将D节点放在A的右子树上合情合理。所以完整的RR旋转的步骤1:备份根节点和根的右儿子的左儿子节点并用根的右儿子覆盖根节点,2:把覆盖过的根节点的左子树赋值为已备份的前根节点。3:把前根节点的右儿子赋值为已备份的根的右儿子的左儿子节点(好拗口)。
下面是具体的代码实现

void rr(node *&root)     //root 指的是非平衡节点即上图的A节点
{
	node *t=root;
	root=root->rson;
	node *tt=root->lson;
	root->lson=t;
	root->lson->rson=tt;
	root->lson->r_h=root->l_h;                                  //**********
	//	root->l_h=max(root->lson->l_h,root->lson->r_h)+1;       
	root->l_h=root->r_h;										//**********
}

其中root->l_h=root->r_h;这句是我观察出的规律….即在原本是平衡树上插入一个节点导致不平衡再进行RR旋转操作之后原本的非平衡节点的平衡因子一定为0。

2つの目的の星はバランス係数を更新することで、我々は(神が....私はバグを発見したどのくらいの時間を知っている)カモT_Tに覚えておく必要があります。
3. 特定の操作RLの回転についてましょう話
同様に図の理解を容易
ここに画像を挿入説明
この図3 Liteは明らか回転操作RRの性質を確認することができ上面図である- 。難しいような場合に、このような状況に対処するためには、RRの回転解けるが処理されています。1の詳細な動作:3バックアップノード、ノードIII及びノード2 IIで覆わ:IIバックアップノード番号3に割り当てられたノードの右サブツリー。

ノード番号2の特殊なケースであるような操作右サブツリーの存在を有するものRRの回転も同様に図2の場合である。3、アカウントに二分探索木の性質を取るために、我々は、以下の処理を行います

ここに画像を挿入説明
図の空想3の左側参照
RR回転にノードAを行うために、次に及び。
比旋光ステップ類似RRを

void rl(node * &root) //root为非平衡节点的右儿子
{
	node *t=root;
	node *tt=root->lson->rson; 
	root=root->lson;
	root->rson=t;
	root->rson->lson=tt;
	root->rson->l_h=root->r_h;					  //*******************
	root->r_h=max(root->rson->l_h,root->rson->r_h)+1;//*******************
}

同じことが...いくつかの星を打つことを忘れないでください...

ここでは完全なコードです

#include <iostream>
#include <queue>
#include <algorithm>
#include <cstdlib>
#include <time.h>
using namespace std;

struct node{
	int date;
	int c;
	int l_h;
	int r_h;
	node *lson;
	node *rson;
	node(int _date=0,int _c=0)
	{
		lson=NULL;
		rson=NULL;
		date=_date;
		c=_c;
		l_h=0;
		r_h=0;
	}
};

void rr(node *&root)
{
	node *t=root;
	root=root->rson;
	node *tt=root->lson;
	root->lson=t;
	root->lson->rson=tt;
	root->lson->r_h=root->l_h;                                  //**********
	//	root->l_h=max(root->lson->l_h,root->lson->r_h)+1;       
	root->l_h=root->r_h;										//**********
}

void rl(node * &root)
{
	node *t=root;
	node *tt=root->lson->rson; 
	root=root->lson;
	root->rson=t;
	root->rson->lson=tt;
	root->rson->l_h=root->r_h;						 //*******************
	root->r_h=max(root->rson->l_h,root->rson->r_h)+1;//*******************
}

void ll(node *&root)
{
	node *t=root;
	node *tt=root->lson->rson;
	root=root->lson;
	root->rson=t;
	root->rson->lson=tt;
	root->rson->l_h=root->r_h;    //*************
	root->r_h=root->l_h;          //*************
}

void lr(node *&root)
{
	node *t=root;
	node *tt=root->rson->lson;
	root=root->rson;
	root->lson=t;
	root->lson->rson=tt;
	root->lson->r_h=root->l_h;
	root->l_h=max(root->lson->l_h,root->lson->r_h)+1;
}

int search(node *root)
{
	if(root->l_h-root->r_h==-2)
	{
		if(root->rson->l_h-root->rson->r_h<0)
		return 1;
		else
		return 2;
	}
	else if(root->l_h-root->r_h==2)
	{
		if(root->lson->l_h - root->lson->r_h>0)
		return 3;
		else
		return 4;
	}
	return 0;
}
void show(node *root)
{
	queue<node *> que;
	que.push(root);
	while(!que.empty())
	{
		node *t=que.front();
		cout<<t->date<<" l_h:"<<t->l_h<<" r_h:"<<t->r_h<<endl;
		que.pop();
		if(t->lson!=NULL)
		que.push(t->lson);
		if(t->rson!=NULL)
		que.push(t->rson);
	}
}

void insert(node* &root,int e,int _c=0)
{
	if(root==NULL)
	{
		root=new node(e,_c);
		return ;
	}
	if(e>root->date)
	{
		insert(root->rson,e,_c+1);
		root->r_h=max(root->rson->l_h,root->rson->r_h)+1;
		int k;
		while(k=search(root))
		{
			if(k==1)
			rr(root);
			else if(k==2)
			rl(root->rson);
			else if(k==3)
			ll(root);
			else
			lr(root->lson);
		}
	}
	else if(e<root->date)
	{
		insert(root->lson,e,_c+1);
		root->l_h=max(root->lson->l_h,root->lson->r_h)+1;
		int k;
		while(k=search(root))
		{
			if(k==1)
			rr(root);
			else if(k==2)
			rl(root);
			else if(k==3)
			ll(root);
			else
			lr(root->lson);
		}
	}
	else
	{
		cout<<"error: have the same date"<<endl;
		return ;
	}
}

void z_show(node *root) 
{
	if(root!=NULL)
	{
		if(root->lson!=NULL)
		z_show(root->lson);
		cout<<root->date<<" ";
		if(root->rson!=NULL)
		z_show(root->rson);
	}
}
int main()
{
	srand((unsigned)time(NULL));
	node *head=NULL;
	int n=1000;
	while(n--)
	{
		insert(head,rand()%4000);
	}
	show(head);
	z_show(head);
	return 0;
}

見てくれてありがとう

公開された30元の記事 ウォンの賞賛9 ビュー1307

おすすめ

転載: blog.csdn.net/Zhang_sir00/article/details/103552355