AVL树的插入与删除

AVL树中,为了避免每次计算左右子树的高度,我们可以采用balancefactor来判断,我们将balancefactor定义为左子树的高度减去右子树的高度;

---------------------------------------------------------

---------------------------插入---------------------------

---------------------------------------------------------

1在插入的过程中,我们可以先通过普通二叉树的插入方法将节点p插入到合适的位置,然后对于检查其父母current

    1. 如果currentkey小于pkey,那么证明pcurrent的 右儿子,那么currentbalancefactor应该减1

    2. 如果currentkey大于pkey,那么证明pcurrent的右儿子,那么currentbalancefactor应该加1

    3. 如果current等于NULL或者currentfactor等于0,停止

否则,current指向其父节点。

这个时候我开始有点担心会不会出现以下这种情况:


在插入55的过程中,

45factor会不会变呢?

其实是不会的,因为我们在(3)中检查了currentfacotr是否为0,如果为0,就停止循环。


2在此过程中,我们还要检查插入后是否仍然满足AVL树的性质,那么我们可以这样检查:

1)如果currentfactor等于2,那么证明p插入到了current的左儿子上t,那么tfactor只能有两种情况,一种是1,一种是-1(显然不可能为2,而为0的就已经停止循环了),

如果tfactor1,那么证明p插入到了leftsubtree of left

child.此时应对current用一次右旋转。

如果tfactor-1,那么证明p插入到了rightsubtree of left child。此时应先对t进行一次左旋转,在对current进行一次右旋转。

2)如果currentfactor等于-2,则情况与上述情况类似,只不过左右的情况相反。

3在旋转过程中,我们也许要对balancefactor进行调整:



显然只有xyfactor会受到影响。

对于左旋转:αβϒ

旋转前:x->bf=α – 1 - max(β,ϒ)

y->bf= β-ϒ

旋转后:x->bf= α-β

y->bf= 1 + max(α,β) - ϒ

那么显然:

如果y->bf大于等于0,即β>ϒ,那么旋转后

x->bf= x->bf + 1;

否则

x->bf= x->bf – y->bf + 1;

总结即是:

++x->bf-= y->bf >= 0 ? 0 : y->bf;

同理,++y->bf+= x->bf > 0 ? x->bf : 0;

对于右旋转:

同理:--(y->bf)-= x->bf > 0?x->bf:0;

--(x->bf)+= y->bf < 0?y->bf :0;

-------------------------------删除---------------------------


对于插入来说,其实只有在balancefactor的调整上和插入略有不同, 如果删除的节点是左儿子,那么该节点的factor就要减1,如果是右儿子,就要加1.其他关于不满足AVL树时的调整和插入一样的。


------------------------------------------代码---------------------------------------

#include <iostream>
#include <string>
#include <fstream>
#define p y->parent
#define q p?((p->left == y)? p->left : p->right):root
using namespace std;

class Node
{
  public:
	  friend class AVLtree;
	  Node();
	  string getdata()
	  {
         return data;
	  }
      void set(int, string);
  private:
	  int key;
	  string data;
      Node *parent;
	  Node *left;
	  Node *right;
	  int factor;
};
class AVLtree
{
  public:
	  AVLtree()
	  {
       root = NULL;
	  }
	  Node * get()
	  {
        return root;
	  }
	  void insert(int , string );
      void deletenode(int );
	  void preorder(Node *x);
	  Node * search(int );
	  Node * successor(int );
	  Node * leftRotate(Node *);
	  Node * rightRotate(Node *);
  private:
	  Node* root;
};

AVLtree tree;
ofstream output;


int main()
{
   output.open("output.txt");
   ifstream input;
   input.open("input.txt");
   int n;

   while(input>>n)
   {
	 int m;
	 string s;
     if(n == 0)
	 {
	  if(tree.get() == NULL)
	  output<<"-1"<<endl;
	  else
	  tree.preorder(tree.get());
	 }
	 else if(n == 1)
	 {
       input>>m>>s;
       tree.insert(m,s);
	 }
	 else if(n == 2)
	 {
       input>>m;
	   tree.deletenode(m);
	 }
	 else
	 {
       input>>m;
	   output<<m<<","<<(tree.search(m))->getdata()<<endl;
	 }

   }

   input.close();
   output.close();
   return 0;

}


Node::Node()
{
   parent = NULL;
   left = NULL;
   right = NULL;
   factor = 0;
}

void Node::set(int m,string s )
{
   key = m;
   data = s;
}

Node* AVLtree::search(int m)
{
   Node *temp = new Node;
   temp = root;

   while(temp != NULL)
   {
     if(temp->key > m)
	   temp = temp->left;
	 else if(temp->key < m)
	   temp = temp->right;
     else
	 {
       return temp;
	 }
   }
}

Node * AVLtree::successor(int m)
{
  Node *temp = new Node;
  temp = search(m);
  
  if(temp->right != NULL)
  {
    temp = temp->right;
	while(temp->left != NULL)
	{
     temp = temp->left;
	}
    
	return temp;
  }
  else 
  {
    while(temp->parent!= NULL && temp == (temp->parent)->left)
	{
       temp = temp->parent;
	}

	return temp;
  }
}


void AVLtree::insert(int m,string s)
{
   Node *x = new Node;
   x->set(m,s);

   Node *temp = new Node;
   temp = root;

   Node *y = new Node;
   y = NULL;
   while(temp != NULL)
   {
	 y = temp;
     if(temp->key < m)
	   temp = temp->right;
	 else if(temp->key > m)
	   temp = temp->left;
   }
   
   if(y == NULL)
	 root = x;
   else 
   {
     x->parent = y;
	 if(m < y->key)
     y->left = x;
	 else
	 y->right = x;
   }
   
   while(y!= NULL)
   {
     y->factor += (y->key > m ? 1 : -1);
	 if(y->factor == -2)
	 {
       if((y->right)->factor == 1)
		 rightRotate(q->right);
	
	    y = leftRotate(q);
	   
	
	 }
	 else if(y->factor == 2)
	 {
       if((y->left)->factor == -1)
         leftRotate(q->left);

	    y =  rightRotate(q);   
	 }
    
	 if(y->factor == 0)
	   break;
	 m = y->key;
	 y = y->parent;
   }

}

Node * AVLtree::leftRotate(Node *x)
{
   Node *y = new Node;
   y = x->right;

   x->right = y->left;
   if(y->left != NULL)
	 (y->left)->parent = x;
   
   y->parent = x->parent;
   if(x->parent == NULL)
   {
     root = y;
   }
   else if(x == (x->parent)->left)
   {
     (x->parent)->left = y;
   }
   else
	 (x->parent)->right = y;

   y->left = x;
   x->parent = y;
   
   x->factor -= y->factor < 0 ? y->factor : 0;
   (x->factor)++;

   y->factor += x->factor > 0? x->factor : 0;
   (y->factor)++;
   return y;
}

Node * AVLtree::rightRotate(Node *x)
{
  Node *y = new Node;
  y = x->left;

  x->left = y->right;
  
  if(y->right != NULL)
   (y->right)->parent = x;

  y->parent = x->parent;

  if(x->parent == NULL)
	root = y;
  else if(x == (x->parent)->left)
    (x->parent)->left = y;
  else
	(x->parent)->right = y;

  y->right = x;
  x->parent = y;

  x->factor -= y->factor > 0 ? y->factor : 0;
  (x->factor)--;

  y->factor += x->factor < 0 ? x->factor : 0;
  (y->factor)--;

  return y;
}


void AVLtree::preorder(Node *x)
{
  if(x == NULL)
	  return;
  else
  {
    output<<x->key<<","<<x->data<<endl;
	preorder(x->left);
	preorder(x->right);
  }

}

void AVLtree::deletenode(int x)
{
   Node *temp = new Node;
   Node *z = new Node;
   Node *a = new Node;
   temp = search(x);

   if(temp->left == NULL ||temp->right == NULL)
	 z = temp;
   else
	 z = successor(x);

   if(z->left != NULL)
	 a = z->left;
   else
	 a = z->right;

   if(a != NULL)
	 a->parent = z->parent;
   
   if(z->parent == NULL)
	 root = a;
   else if(z == z->parent->left)
	 z->parent->left = a;
   else
	 z->parent->right = a;
   if(z->key != temp->key)
   {
     temp->key = z->key;
     temp->data = z->data;
   }

   Node *y = new Node;
   y = z->parent;
   int m = z->key;
  
   while(y != NULL)
   {
     y->factor -= (y->key > m)? 1 : -1;

	 if(y->factor == -2)
	 {
		Node *temp;
        if(y->right->factor == 1)
		 temp =  rightRotate(q->right);

	    y = leftRotate(q);
	 }
	 else if(y->factor == 2)
	 {
        Node *temp;

		if(y->left->factor == -1)
		  temp = leftRotate(q->left);
      

		y = rightRotate(q);
	 }
    
	 if(y->factor == 0)
	   break;
     m = y->key;
	 y = y->parent;
   }

}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值