1. 程式人生 > >數據結構--Avl樹的創建,插入的遞歸版本和非遞歸版本,刪除等操作

數據結構--Avl樹的創建,插入的遞歸版本和非遞歸版本,刪除等操作

pop end eem static cout 遞歸 sta div else

AVL樹本質上還是一棵二叉搜索樹,它的特點是:

1.本身首先是一棵二叉搜索樹。 2.帶有平衡條件:每個結點的左右子樹的高度之差的絕對值最多為1(空樹的高度為-1)。 也就是說,AVL樹,本質上是帶了平衡功能的二叉查找樹(二叉排序樹,二叉搜索樹)。 對Avl樹進行相關的操作最重要的是要保持Avl樹的平衡條件。即對Avl樹進行相關的操作後,要進行相應的旋轉操作來恢復Avl樹的平衡條件。 對Avl樹的插入和刪除都可以用遞歸實現,文中也給出了插入的非遞歸版本,關鍵在於要用到棧。 代碼如下:
#include <iostream>
#include<stack>
using namespace std;

struct AvlNode;
typedef struct AvlNode *Position;
typedef struct AvlNode *Avltree;

struct AvlNode    //AVL樹節點
{
   int Element;
   Avltree Left;
   Avltree Right;
   int Hight;
   int Isdelete;  //指示該元素是否被刪除
};


///////////////AVL平衡樹的函數的相關聲明//////////////////////
Avltree MakeEmpty(Avltree T);   //清空一棵樹
static int Height(Position P);  //返回節點的高度
Avltree Insert(int x, Avltree T);   //在樹T中插入元素x
Avltree Insert_not_recursion (int x, Avltree T);  //在樹T中插入元素x,非遞歸版本
Position FindMax(Avltree T);   //查找Avl樹的最大值,和二叉樹一樣
Avltree Delete(int x,Avltree T);   //刪除元素,非懶惰刪除



///////////////AVL平衡樹的函數的相關定義//////////////////////
Avltree MakeEmpty(Avltree T)
{
    if (T != NULL)
   {
      MakeEmpty(T->Left);
      MakeEmpty(T->Right);
     delete T;// free(T);
   }
	return NULL;
}

static int Height(Position P)   //返回節點的高度
{
   if(P == NULL)
	   return -1;
   else
   return P->Hight;
}


static int Element(Position P)   //返回節點的元素
{
   if(P == NULL)
	   return -1000;
   else
	   return P->Element;
}




int Max(int i,int j)    //返回最大值
{
    if(i > j)
	    return i;
	else
		return j;
}


static Position SingleRotateWithLeft (Position k2)   //單旋轉,左子樹高度比較高
{
   Position k1;
   k1 = k2->Left;
   k2->Left = k1->Right;
   k1->Right = k2;
   
   k2->Hight = Max(Height(k2->Left), Height(k2->Right)) + 1;
   k1->Hight = Max(Height(k1->Left), Height(k1->Right)) + 1;

   return k1;  //新的根
}

static Position SingleRotateWithRight (Position k1)   //單旋轉,右子樹的高度比較高
{
   Position k2;
   k2 = k1->Right;
   k1->Right = k2->Left;
   k2->Left = k1;

   k1->Hight = Max(Height(k1->Left), Height(k1->Right)) + 1;
   k2->Hight = Max(Height(k2->Left), Height(k2->Right)) + 1;
   

   return k2;  //新的根
}

static Position DoubleRotateWithLeft (Position k3)   //雙旋轉,當k3有左兒子而且k3的左兒子有右兒子
{
   k3->Left = SingleRotateWithRight(k3->Left);
   return SingleRotateWithLeft(k3);
}



static Position DoubleRotateWithRight (Position k1)   //雙旋轉,當k1有右兒子而且k1的又兒子有左兒子
{
   k1->Right = SingleRotateWithLeft(k1->Right);
   return SingleRotateWithRight(k1);
}

//對Avl樹執行插入操作,遞歸版本
Avltree Insert(int x, Avltree T)
{
   if(T == NULL)  //如果T為空樹,就創建一棵樹,並返回
   {
      T = static_cast<Avltree>(malloc(sizeof(struct AvlNode)));
	  if (T == NULL)
	   {
	     cout << "out of space!!!" << endl;
	   }
	  else                    
	  {
	    T->Element = x;
	    T->Left = NULL;
	    T->Right = NULL;
	    T->Hight = 0;
		T->Isdelete = 0;
	  }
	  
   }
   else   //如果不是空樹
   {
       if(x < T->Element)
	   {
	      T->Left = Insert(x,T->Left);
		  if(Height(T->Left) - Height(T->Right) == 2 )
		  {
		    if(x < T->Left ->Element )
				T = SingleRotateWithLeft(T);
			else
				T = DoubleRotateWithLeft(T);
		  }
	   }
	   else
	   {
	      if(x > T->Element )
		  {
		     T->Right = Insert(x,T->Right );
			 if(Height(T->Right) - Height(T->Left) == 2 )
			 {
			     if(x > T->Right->Element )
					 T = SingleRotateWithRight(T);
				 else
					 T = DoubleRotateWithRight(T);
			 }
		  }
	   }

   }
    T->Hight = Max(Height(T->Left), Height(T->Right)) + 1;
	return T;
}

//對Avl樹進行插入操作,非遞歸版本
Avltree Insert_not_recursion (int x, Avltree T)
{
	stack<Avltree> route; //定義一個堆棧使用

	//找到元素x應該大概插入的位置,但是還沒進行插入
	Avltree root = T;
	while(1)
	{
	   if(T == NULL)  //如果T為空樹,就創建一棵樹,並返回
         {
	      T = static_cast<Avltree>(malloc(sizeof(struct AvlNode)));
		  if (T == NULL) cout << "out of space!!!" << endl;  
		  else                    
		    {
				T->Element = x;
				T->Left = NULL;
				T->Right = NULL;
				T->Hight = 0;
				T->Isdelete = 0;
				route.push (T);
				break;
		    }
		  }
	   else if (x < T->Element)
	   {
	      route.push (T);
		  T = T->Left;
		  continue;
	   }
	   else if (x > T->Element)
	   {
	      route.push (T);
		  T = T->Right;
		  continue;
	   }
	   else
	   {
	      T->Isdelete = 0;
		  return root;
	   }
	}

	//接下來進行插入和旋轉操作
	Avltree father,son;
	while(1)
	{
	   son = route.top ();   
	   route.pop();   //彈出一個元素
	   if(route.empty())
		   return son;   
	   father = route.top ();  
	    route.pop();   //彈出一個元素
		if(father->Element < son->Element )   //兒子在右邊
		{
		   father->Right = son;
		   if( Height(father->Right) - Height(father->Left) == 2)
		   {
			   if(x >  Element(father->Right))
				   father = SingleRotateWithRight(father);
			   else
				   father = DoubleRotateWithRight(father);
		   }
		  
		   route.push(father);
		}
		else if (father->Element > son->Element)    //兒子在左邊
		{
			father->Left = son;
			if(Height(father->Left) - Height(father->Right) == 2)
			{
				if(x < Element(father->Left))
				   father = SingleRotateWithLeft(father);
			   else
				   father = DoubleRotateWithLeft(father);
			}
		
			route.push(father);
                
		}
		father->Hight = max(Height(father->Left),Height(father->Right )) + 1;
	}
	
	

}

Position FindMax(Avltree T)
{
   if(T != NULL)
   {
     while(T->Right != NULL)
     {
        T = T->Right;
     }
   }
   return T;
}

Position FindMin(Avltree T)
{
   if(T == NULL)
   {
      return NULL;
   }
   else
   {
      if(T->Left == NULL)
      {
         return T;
      }
      else
      {
         return FindMin(T->Left );
      }
   }
}

Avltree Delete(int x,Avltree T)    //刪除Avl樹中的元素x
{
	Position Temp;
	if(T == NULL)
		return NULL;
	else if (x < T->Element)   //左子樹平衡條件被破壞
	{
	    T->Left = Delete(x,T->Left );
		if(Height(T->Right) - Height(T->Left) == 2)
		{
		   if(x > Element(T->Right) )
		      T = SingleRotateWithRight(T);
		   else
			  T = DoubleRotateWithRight(T);  
		}
	}
	else if (x > T->Element)   //右子樹平衡條件被破壞
	{
	    T->Right = Delete(x,T->Right );
		if(Height(T->Left) - Height(T->Right) == 2)
		{
		   if(x < Element(T->Left) )
		      T = SingleRotateWithLeft(T);
		   else
			  T = DoubleRotateWithLeft(T);  
		}
	}
	else    //執行刪除操作
	{
	    if(T->Left && T->Right)   //有兩個兒子
		{
		   Temp = FindMin(T->Right);
		   T->Element = Temp->Element;
		   T->Right = Delete(T->Element ,T->Right);
		}
		else  //只有一個兒子或者沒有兒子
		{
		    Temp = T;
			if(T->Left == NULL)
				T = T->Right;
			else if(T->Right == NULL)
			     T = T->Left;
			free(Temp);
		}
	}
	return T;
}

int main ()
{
  Avltree T = NULL;
  
  T = Insert_not_recursion(3, T);  //T一直指向樹根
  T = Insert_not_recursion(2, T);
  T = Insert_not_recursion(1, T);
  T = Insert_not_recursion(4, T);
  T = Insert_not_recursion(5, T);
  T = Delete(1,T);
 // T = Insert_not_recursion(6, T);
 /*  
  T = Insert(3, T);  //T一直指向樹根
  T = Insert(2, T);
  T = Insert(1, T);
  T = Insert(4, T);
  T = Insert(5, T);
  T = Insert(6, T);*/
  cout << T->Right->Right->Element << endl;
   return 0;

}

   遞歸與棧的使用有著不可描述的關系,我覺得如果要把遞歸函數改寫成非遞歸的函數,首先要想到用棧。

唉,夜似乎更深了。

數據結構--Avl樹的創建,插入的遞歸版本和非遞歸版本,刪除等操作