1. 程式人生 > >平衡二叉樹(AVL樹)建立、查詢、插入操作 《大話資料結構》 c++實現程式碼

平衡二叉樹(AVL樹)建立、查詢、插入操作 《大話資料結構》 c++實現程式碼

//平衡二叉樹,或者稱為AVL樹
#include<iostream>

using namespace std;

typedef int status;

#define true 1
#define false 0

#define LH +1   //左高
#define EH 0     //等高
#define RH -1     //右高


//二叉連結串列結點結構定義
typedef struct Bitnode
{
	int data;
	int bf;    //儲存結點的平衡因子
	struct Bitnode *left,*right;
}Bitnode,*Bitree;


   //操作
void R_rotate(Bitree *p);
void L_rotate(Bitree *p);
void Leftbalance(Bitree *T);
void Rightbalance(Bitree *T);
status Insertavl(Bitree *T,int e,status *taller);
void Createavl(Bitree *T,int a[],int n);
void Showbst(Bitree T);       //中序遍歷輸出二叉樹
   

//f指向T的雙親,當T指向根節點時,因此f的初始呼叫值為Null
//查詢成功,指標p指向該資料元素的結點,返回TRUE
//查詢失敗,P指向查詢路徑上訪問的最後一個元素,返回false
Bitree Searchavl(Bitree T,int key)
{
	if (!T) 
		return NULL;

    //搜尋到  
    if (key==T->data)
        return T;
    else if (key<T->data)
    {
        //在左子樹中搜索  
        return Searchavl(T->left,key);
    }
    else
    {
        //在右子樹中搜索  
        return  Searchavl(T->right,key);
    }
}


//對以p為根的二叉排序樹做右旋處理。處理之後p指向新的樹根節點
//即旋轉之前的左子樹的根節點
void R_rotate(Bitree *p)
{
	Bitree L;
	L=(*p)->left;
	(*p)->left=L->right;
	L->right=*p;
	*p=L;
}

//對以p為根的二叉排序樹做左旋處理。處理之後p指向新的樹根節點
//即旋轉之前的左子樹的根節點
void L_rotate(Bitree *p)
{
	Bitree R;
	R=(*p)->right;
	(*p)->right=R->left;
	R->left=*p;
	*p=R;
}
//對以T為根的二叉排序樹做左旋平衡處理
//處理之後T指向新的樹根節點
void Leftbalance(Bitree *T)
{
	Bitree L,Lr;
	L=(*T)->left;  //L指向T的左子樹根結點
	switch(L->bf)
	{
		//檢查T左子樹的平衡度,並做相應的處理
	case LH:  //新節點插入在T的左孩子的左子樹上,要做單右旋處理
		(*T)->bf=L->bf=EH;
		R_rotate(T);
		break;
    case RH:    //新節點插入在T的左孩子的右子樹上,要做單右旋處理
		Lr=L->right;  //Lr指向T的左孩子的右子樹根
		switch(Lr->bf)
		{
		case LH: 
			(*T)->bf=RH;
			L->bf=EH;
			break;
		case EH:
			(*T)->bf=L->bf=RH;
			break;
		case RH:
			(*T)->bf=EH;
			L->bf=LH;
			break;
		}
		Lr->bf=EH;
		L_rotate(&(*T)->left);
		R_rotate(T);
	}
}


//T 的右邊高,不平衡,使其平衡,左旋轉,左旋轉前先檢查R->bf
//如果為LH,R要先進行右旋轉,使T->rchild->bf和T->bf一致
void Rightbalance(Bitree *T)
{
    Bitree R,Rl;
    R = (*T)->right;
    Rl = R->left;
    switch(R->bf)
    {
        case RH:
            R->bf = (*T)->bf = EH;
            L_rotate(T);
            break;
        case LH:
            switch(R->bf)
            {
                case LH:
                    R->bf = RH;
                    (*T)->bf = EH;
                    break;
                case EH:
                    R->bf = (*T)->bf = EH;
                    break;
                case RH:
                    R->bf = EH;
                    (*T)->bf = LH;
                    break;
            }
            Rl->bf = EH;
            R_rotate(&R);
            L_rotate(T);
            break;
    }
}

//若在平衡的二叉排序樹T中不存在和e有相同關鍵字的結點,則插入一個
//資料元素為e的新節點並返回1,否則返回0
//若因插入使得二叉樹失去平衡,則做平衡旋轉,布林變數taller反映T長高與否
status Insertavl(Bitree *T,int e,status *taller)
{
	if(!*T)
	{
		//插入新節點,樹長高,taller為true
		*T=(Bitree)malloc(sizeof(Bitnode));
		(*T)->data=e;
		(*T)->left=(*T)->right=NULL;
		(*T)->bf=EH;
		*taller=true;
	}
	else
	{
		if(e==(*T)->data)
		{
			//樹中存在和e有相同關鍵字的結點將不再插入
			*taller=false;
			return false;
		}
		if(e<(*T)->data)
		{
			//應繼續在t的左子樹中進行搜尋
			if(!Insertavl(&(*T)->left,e,taller))
				return false;
			if(*taller)
			{
				switch((*T)->bf)
				{
				case LH:
					Leftbalance(T);
					*taller=false;
					break;
				case EH:
					(*T)->bf=LH;
					*taller=true;
					break;
				case RH:
					(*T)->bf=EH;
					*taller=false;
					break;
				}
			}
		}
		else
		{
			if(!Insertavl(&(*T)->right,e,taller))
				return false;
			if(*taller)
			{
				switch((*T)->bf)
				{
				case LH:
					(*T)->bf=EH;
					*taller=false;
					break;
				case EH:
					(*T)->bf=RH;
					*taller=true;
					break;
				case RH:
					Rightbalance(T);
					*taller=false;
					break;
				}
			}
		}
	}
	return true;
}

void Createavl(Bitree *T,int a[],int n)
{
	int i;
	status taller;
	for(i=0;i<n;i++)
	{
		Insertavl(T,a[i],&taller);
	}
}


void Showbst(Bitree T)
{
	if(T)
	{
		Showbst(T->left);
		cout<<T->data<<" ";
		Showbst(T->right);
	}
}

int main()
{
	int a[]={62,88,58,47,35,73,51,99,37,93};

	Bitree T=NULL;
	status taller=0;

	//建立二叉排序樹
	Createavl(&T,a,10);
	cout<<"中序遍歷的結果為:"<<endl;
	Showbst(T);
	cout<<endl;


	//在二叉排序樹中插入56
	Insertavl(&T,56,&taller);
	cout<<"中序遍歷的結果為:"<<endl;
	Showbst(T);
	cout<<endl;


	int b=58;  //需要查詢的值
	Bitree p=NULL;
	T=Searchavl(T,b);
	cout<<"查詢結果為:\n"<<"指標:"<<T<<endl
		<<"指標的值為:"<<T->data<<endl;


	system("pause");
	return 0;
}