树表的查找

目录

一、基本概念

二、二叉排序树 

 插入

建立二叉排序树 

查找 

查找父结点 

三、 二叉排序树的删除结点

 演示

删除(用直接后继替代)

 删除(用直接前驱替代)

 完整代码

 四、平衡二叉树

 4种调整情况

1.LL型调整

右单旋演示 

 代码

2.RR型调整

 左单旋

 代码

3.LR型调整

先左旋后右旋转

代码 

4.RL型调整

先右旋后左旋转 

 代码

 完整代码


一、基本概念

  • 以二叉树或树作为表的组织形式,称为树表。树表在进行插入或删除操作时,可以方便地维护表的有序性,不需要移动表中的元素,从而减少因移动元素引起的额外时间开销。
  • 常见的树表有二叉排序树、平衡二叉树、B树和B+树。

二、二叉排序树 

  • 二叉排序树(简称BST)的定义为二叉排序树或空树,或者是满足以下性质的二叉树。
  • 若它的左子树非空,则左子树上的所有元素的值均小于根元素的值
  • 若它的右子树非空,则右子树上的所有元素的值均大于根元素的值
  • 左右子树本身又是一棵二叉排序树 
  • 二叉排序树的特性:左子树结点值<根结点值<右子树结点值
  •  插入

//若原二叉树为空,则直接插入结点;若存在相同关键字k则退出;若k小于根结点的值,则插入到左子树;
//若k大于根结点的值,则插入到右子树
bool BSTInsert(BSTree& s, ElemType k)//插入结点
{
	if (s == NULL)//如果原树为空
	{
		s = (BSTNode*)malloc(sizeof(BSTNode));
		if (!s)//开辟空间失败,直接退出
			exit(0);
		else
		{
			s->key = k;
			s->lchild = s->rchild = NULL;
				return true;
		}
	}
	else if (k == s->key)//树中存在相同的结点,返回false
		return false;
	else
	{
		if (k < s->key)
			BSTInsert(s->lchild, k);//插入root的左子树中
		else
			BSTInsert(s->rchild, k);//插入root的右子树中
	}
	return true;
}
  • 建立二叉排序树 

bool CreatBST(BSTree &root, int* data, int n)//创建二叉排序树
{
	root = NULL;
	int i = 0;
	while (i < n)
	{
		BSTInsert(root, data[i]);
		i++;
	}
	return true;
}
  • 查找 

BSTNode* BSTSearch(BSTree root, ElemType Key)//基于二叉排序树树的查找
{
	if (root == NULL)
		return NULL;
	else if (Key < root->key)
	{
		return(BSTSearch(root->lchild, Key));//左子树递归查找
	}
	else if (Key > root->key)
	{
		return(BSTSearch(root->rchild, Key));//有子树递归查找
	}
	else
	{
		return root;//查找成功
	}
}
  • 查找父结点 

bool SearchParent(BSTree root,BSTNode* &s ,ElemType Key)//基于二叉排序树查找父结点
{
	if (root == NULL)
		return NULL;
	else if (Key < root->key)
	{
		s = root;
		SearchParent(root->lchild,s,Key);//左子树递归查找
		
	}
	else if (Key > root->key)
	{
		s = root;
		SearchParent(root->rchild,s,Key);//有子树递归查找
	}
	else
	{
		return s;//查找成功
	}
}

三、 二叉排序树的删除结点

  • 二叉排序树的删除(删除结点p)
  • 情况1:若结点p是叶子结点,则直接删除,不会破坏二叉树的性质。
  • 情况2:若结点p只有一棵左子树,此时只需将p的左子树直接作为双亲结点f的左子树,即可
  • 情况3:若结点p只有一棵右子树,此时只需将p的右子树直接作为双亲结点f的右子树,即可
  • 情况4:若结点p有左、右两棵子树,则让p的直接后继(或者直接前驱)替代p,然后从二叉排序树中删去这个直接后继(或者直接前驱),这样就转换成了前三种情况
     
  •  演示

  • 删除(用直接后继替代)

void DeleteBST(BSTree &root, ElemType key)//删除
{
	BSTNode*p=BSTSearch(root, key);//结点p存有key
	BSTNode* s;
	SearchParent(root, s, key);//查找p的父结点s
	if (p->lchild == NULL && p->rchild == NULL)//p为叶子结点
	{
		if (s->lchild == p)//如果删除的p是s的左孩子结点
		{
			s->lchild = NULL;
			free(p);
		}
		else//p是s的右孩子
		{
			s->rchild = NULL;
			free(p);
		}
	}
	else if (p->lchild == NULL )//p的左子树为空
	{
		BSTNode* q = p->rchild;//q为p的右子树
		if (s->lchild == p)//如果删除的p是s的左孩子结点
		{
			s->lchild = q;//让p的右子树替代称为s的子树
			free(p);
		}
		else
		{
			s->rchild = q;
			free(p);
		}
	}
	else if (p->rchild == NULL)//p的右子树为空
	{
		BSTNode* q = p->lchild;
		if (s->lchild == p)
		{
			s->lchild = q;
			free(p);
		}
		else
		{
			s->rchild = q;
			free(p);
		}
	}
	else
	{
		BSTNode* q = p->rchild;
		BSTNode* Q = p;
		while (q->lchild != NULL)
		{
			Q = q;
			q = q->lchild;
		}
		p->key = q->key;//将p的后继结点q(也就是p右子树最左下结点,该结点一定没有左子树)的值复制给要删除的结点
		Q->lchild = q->rchild;//将q的右子树连在q的父结点的左子树上
		free(q);
	}
}
  •  删除(用直接前驱替代)

void DeleteBST2(BSTree& root, ElemType key)
{
	BSTNode* p = BSTSearch(root, key);//结点p存有key
	BSTNode* s;
	SearchParent(root, s, key);//查找p的父结点s
	if (p->lchild == NULL && p->rchild == NULL)//p为叶子结点
	{
		if (s->lchild == p)//如果删除的p是s的左孩子结点
		{
			s->lchild = NULL;
			free(p);
		}
		else//p是s的右孩子
		{
			s->rchild = NULL;
			free(p);
		}
	}
	else if (p->lchild == NULL)//p的左子树为空
	{
		BSTNode* q = p->rchild;//q为p的右子树
		if (s->lchild == p)//如果删除的p是s的左孩子结点
		{
			s->lchild = q;//让p的右子树替代称为s的子树
			free(p);
		}
		else
		{
			s->rchild = q;
			free(p);
		}
	}
	else if (p->rchild == NULL)//p的右子树为空
	{
		BSTNode* q = p->lchild;
		if (s->lchild == p)
		{
			s->lchild = q;
			free(p);
		}
		else
		{
			s->rchild = q;
			free(p);
		}
	}
	else
	{
		BSTNode* Q = p;
		BSTNode* q = p->lchild;
		while (q->rchild != NULL)
		{
			Q = q;//用于保存父结点
			q = q->rchild;
		}
		p->key = q->key;//将p的前驱结点(也就是p的左子树中最右下的结点,该节点一定没有右子树)
		Q->lchild = q->lchild;//将q的左子树连在q的父结点的右孩子上
		free(q);

	}
}
  •  完整代码

#include<iostream>
#include<stdio.h>
#include<malloc.h>
#include<stdbool.h>
using namespace std;
#define MAX 100
typedef int ElemType;
typedef struct BSTNode
{
	ElemType key;
	struct BSTNode* lchild, * rchild;
}BSTNode, * BSTree;
//int i = 0;
//若原二叉树为空,则直接插入结点;若存在相同关键字k则退出;若k小于根结点的值,则插入到左子树;
//若k大于根结点的值,则插入到右子树
bool BSTInsert(BSTree& s, ElemType k)//插入结点
{
	if (s == NULL)//如果原树为空
	{
		s = (BSTNode*)malloc(sizeof(BSTNode));
		if (!s)//开辟空间失败,直接退出
			exit(0);
		else
		{
			s->key = k;
			s->lchild = s->rchild = NULL;
			return true;
		}
	}
	else if (k == s->key)//树中存在相同的结点,返回false
		return false;
	else
	{
		if (k < s->key)
			BSTInsert(s->lchild, k);//插入root的左子树中
		else
			BSTInsert(s->rchild, k);//插入root的右子树中
	}
	return true;
}

bool CreatBST(BSTree& root, int* data, int n)//创建二叉排序树
{
	root = NULL;
	int i = 0;
	while (i < n)
	{
		BSTInsert(root, data[i]);
		i++;
	}
	return true;
}
BSTNode* BSTSearch(BSTree root, ElemType Key)//基于二叉排序树的查找
{
	if (root == NULL)
		return NULL;
	else if (Key < root->key)
	{
		return(BSTSearch(root->lchild, Key));//左子树递归查找
	}
	else if (Key > root->key)
	{
		return(BSTSearch(root->rchild, Key));//有子树递归查找
	}
	else
	{
		return root;//查找成功
	}
}
bool SearchParent(BSTree root, BSTNode*& s, ElemType Key)//基于二叉排序树查找父结点
{
	if (root == NULL)
		return NULL;
	else if (Key < root->key)
	{
		s = root;
		SearchParent(root->lchild, s, Key);//左子树递归查找

	}
	else if (Key > root->key)
	{
		s = root;
		SearchParent(root->rchild, s, Key);//有子树递归查找
	}
	else
	{
		return s;//查找成功
	}
}
void DeleteBST(BSTree& root, ElemType key)//删除
{
	BSTNode* p = BSTSearch(root, key);//结点p存有key
	BSTNode* s;
	SearchParent(root, s, key);//查找p的父结点s
	if (p->lchild == NULL && p->rchild == NULL)//p为叶子结点
	{
		if (s->lchild == p)//如果删除的p是s的左孩子结点
		{
			s->lchild = NULL;
			free(p);
		}
		else//p是s的右孩子
		{
			s->rchild = NULL;
			free(p);
		}
	}
	else if (p->lchild == NULL)//p的左子树为空
	{
		BSTNode* q = p->rchild;//q为p的右子树
		if (s->lchild == p)//如果删除的p是s的左孩子结点
		{
			s->lchild = q;//让p的右子树替代称为s的子树
			free(p);
		}
		else
		{
			s->rchild = q;
			free(p);
		}
	}
	else if (p->rchild == NULL)//p的右子树为空
	{
		BSTNode* q = p->lchild;
		if (s->lchild == p)
		{
			s->lchild = q;
			free(p);
		}
		else
		{
			s->rchild = q;
			free(p);
		}
	}
	else
	{
		BSTNode* q = p->rchild;
		BSTNode* Q = p;
		while (q->lchild != NULL)
		{
			Q = q;
			q = q->lchild;
		}
		p->key = q->key;//将p的后继结点q(也就是p右子树最左下结点,该结点一定没有左子树)的值复制给要删除的结点
		Q->lchild = q->rchild;//将q的右子树连在q的父结点的左子树上
		free(q);
	}
}
void DeleteBST2(BSTree& root, ElemType key)
{
	BSTNode* p = BSTSearch(root, key);//结点p存有key
	BSTNode* s;
	SearchParent(root, s, key);//查找p的父结点s
	if (p->lchild == NULL && p->rchild == NULL)//p为叶子结点
	{
		if (s->lchild == p)//如果删除的p是s的左孩子结点
		{
			s->lchild = NULL;
			free(p);
		}
		else//p是s的右孩子
		{
			s->rchild = NULL;
			free(p);
		}
	}
	else if (p->lchild == NULL)//p的左子树为空
	{
		BSTNode* q = p->rchild;//q为p的右子树
		if (s->lchild == p)//如果删除的p是s的左孩子结点
		{
			s->lchild = q;//让p的右子树替代称为s的子树
			free(p);
		}
		else
		{
			s->rchild = q;
			free(p);
		}
	}
	else if (p->rchild == NULL)//p的右子树为空
	{
		BSTNode* q = p->lchild;
		if (s->lchild == p)
		{
			s->lchild = q;
			free(p);
		}
		else
		{
			s->rchild = q;
			free(p);
		}
	}
	else
	{
		BSTNode* Q = p;
		BSTNode* q = p->lchild;
		while (q->rchild != NULL)
		{
			Q = q;//用于保存父结点
			q = q->rchild;
		}
		p->key = q->key;//将p的前驱结点(也就是p的左子树中最右下的结点,该节点一定没有右子树)
		Q->lchild = q->lchild;//将q的左子树连在q的父结点的右孩子上
		free(q);

	}
}
void InOrder(BSTree root, int data[])//中序遍历
{
	int i = 0;
	if (root != NULL)
	{
		InOrder(root->lchild, data);
		data[i++] = root->key;
		InOrder(root->rchild, data);
	}
}
void show(BSTree& root)//层次遍历
{
	BSTNode* b[MAX];
	int front = 0, rear = 0;//初始队头指针,队尾指针
	b[rear] = root;//根结点入队
	rear++;//队尾指针指向下一个入队的位置
	while (front != rear)
	{
		BSTNode* s = b[front];//队头结点出队
		cout << s->key << " ";
		front = (front + 1) % MAX;
		if (s->lchild != NULL)
		{
			b[rear] = s->lchild;
			rear = (rear + 1) % MAX;
		}
		if (s->rchild != NULL)
		{
			b[rear] = s->rchild;
			rear = (rear + 1) % MAX;
		}
	}

}
int main()
{
	int a[] = { 50,30,20,80,40,35,90,85,88,32 };
	int size = sizeof(a) / sizeof(a[0]);
	BSTree T = NULL;
	CreatBST(T, a, size);//建立二叉排序树
	//                      50
	//                   /     \
	//                  30      80
	//              /     \       \
	//            20       40      90
	//                   /         /
	//                  35        85
	//                  /           \
	//                 32            88
	cout << "层序遍历:";
	show(T);//层次遍历二叉排序树
	cout << endl;

	DeleteBST(T, 30);
	cout << "层序遍历:";
	show(T);//层次遍历二叉排序树
	cout << endl;
	//                      50
	//                   /     \
	//                  32      80
	//               /     \       \
	//             20       40      90
	//                     /        /
	//                   35        85
	//                              \
	//                              88
	DeleteBST2(T, 32);
	cout << "层序遍历:";
	show(T);//层次遍历二叉排序树
	cout << endl;
	//                      50
	//                   /     \
	//                  20      80
	//                   \       \
	//                   40      90
	//                   /       /
	//                  35      85
	//                           \
	//                            88	
	return 0;
}

 四、平衡二叉树

  • 平衡二叉树:又称AVL树,它或是一棵空树,或是左子树和右子树都是平衡二叉树且左右子树的高度之差的绝对值不超过1的二叉树
  • 注意:二叉排序树不一定是平衡二叉树
  • 平衡因子:某结点的左子树高度减去其右子树高度。平衡二叉树上的所有结点的平衡因子只可能是-1,0或1
  •  4种调整情况

  • 1.LL型调整

  • 是因在A结点的左孩子(B结点)的左子树插入结点,使得A结点的平衡因子由1变为2而引起的不平衡
  • LL型失衡的特点:结点A的平衡因子是2,结点B的平衡因子是1

  • 右单旋演示 

  •  代码

AVLTree RotateRight(AVLTree T)//右单旋(LL型调整)
{
    if (T == NULL || T->Left == NULL)//T为空树或者没有左孩子
        return NULL;
    AVLTree tmp = T->Left;
    T->Left = tmp->Right;
    tmp->Right = T;
    return tmp;
}
  • 2.RR型调整

  • 是因在A结点的右孩子(B结点)的右子树插入结点,使得A结点的平衡因子由1变为2而引起的不平衡
  • RR型失衡的特点:A结点的平衡因子是-2,B结点的平衡因子是-1

  •  左单旋

  •  代码

AVLTree RotateLeft(AVLTree T)//左单旋(RR型调整)
{
    if (T == NULL || T->Right == NULL)//T为空树或者没有右孩子
        return NULL;
    AVLTree tmp = T->Right;
    T->Right = tmp->Left;
    tmp->Left = T;
    return tmp;
}
  • 3.LR型调整

  • 是因在A结点的左孩子(B结点)的右子树插入结点,使得A结点的平衡因子由1变为2而引起的不平衡
  • LR型失衡的特点:A结点的平衡因子是2,B结点的平衡因子是-1

  • 先左旋后右旋转

  • 代码 

AVLTree RotateLeftRight(AVLTree T)//先左旋后右双旋转(LR型调整)
{
    if (T == NULL || T->Left == NULL || T->Left->Right == NULL)
        //T为空树或者T没有左孩子或者T的左孩子没有右子树结点
        return NULL;
  
    AVLTree tmp = RotateLeft(T->Left);//先对B,C进行左单旋
    return RotateRight(T);//再对C,A进行右单旋
}
  • 4.RL型调整

  • 是因在A结点的右孩子(B结点)的左子树插入结点,使得A结点的平衡因子由1变为2而引起的不平衡
  • RL型失衡的特点:A结点的平衡因子是-2,B结点的平衡因子是1

  

 

  • 先右旋后左旋转 

  •  代码

AVLTree RotateRightLeft(AVLTree T)//先右旋后左双旋转(RL型调整)
{
    if (T == NULL || T->Right == NULL || T->Left)
        return NULL;
    AVLTree tmp = RotateRight(T->Right);//先对B,C进行右单旋
    return RotateLeft(T);//在对C,A进行左单旋
}
  •  完整代码

    #include<iostream>
    #include<stdio.h>
    #include<malloc.h> 
    #include<stdbool.h>
    using namespace std;
    typedef int ElemType;
    #define MAX 100
    typedef struct AVLTreeNode {
        ElemType data;
        struct AVLTreeNode* Left;
        struct AVLTreeNode* Right;
        int balance;
    }AVLTreeNode, * AVLTree;
    
    int AVLHeight(AVLTree T);//求二叉树的高度
    AVLTree RotateRight(AVLTree T);//右单旋(LL型调整)
    AVLTree RotateLeft(AVLTree T);//左单旋(RR型调整)
    AVLTree RotateLeftRight(AVLTree T);//先左旋后右双旋转(LR型调整)
    AVLTree RotateRightLeft(AVLTree T);//先右旋后左双旋转(RL型调整)
    bool Insert(AVLTree& T, ElemType x);//插入(按照中序插入可得到一棵平衡二叉排序树)
    AVLTree Delete(AVLTree T, ElemType x);//删除
    void show(AVLTree T);//层次遍历
    
    int AVLHeight(AVLTree T)//求二叉树的高度
    {
        int ldepth = 0, rdepth = 0;//左,右子树高度
        if (T == NULL)
            return 0;//空树高度为0
        else
        {
            ldepth = AVLHeight(T->Left);//求左子树高度
            rdepth = AVLHeight(T->Right);//求右子树高度
            return (ldepth > rdepth) ? (ldepth + 1) : rdepth + 1;
        }
    }
    AVLTree RotateRight(AVLTree T)//右单旋(LL型调整)
    {
        if (T == NULL || T->Left == NULL)//T为空树或者没有左子树
            return NULL;
        AVLTree tmp = T->Left;
        T->Left = tmp->Right;
        tmp->Right = T;
    
    
    	//修改平衡因子
    	tmp->balance = AVLHeight(tmp->Left) - AVLHeight(tmp->Right);//B
    	tmp->Right->balance= AVLHeight(tmp->Right->Left) - AVLHeight(tmp->Right->Right);//A
        return tmp;
    }
    AVLTree RotateLeft(AVLTree T)//左单旋(RR型调整)
    {
        if (T == NULL || T->Right == NULL)//T为空树或者没有右子树
            return NULL;
        AVLTree tmp = T->Right;
        T->Right = tmp->Left;
        tmp->Left = T;
    
    	//修改平衡因子
    	tmp->balance = AVLHeight(tmp->Left) - AVLHeight(tmp->Right);//B
    	tmp->Left->balance = AVLHeight(tmp->Left->Left) - AVLHeight(tmp->Left->Right);//A
        return tmp;
    }
    AVLTree RotateLeftRight(AVLTree T)//先左旋后右双旋转(LR型调整)
    {
        if (T == NULL || T->Left == NULL || T->Left->Right == NULL)
            //T为空树或者T没有左子树或者T的左子树没有右孩子结点
            return NULL;
      
        AVLTree tmp = RotateLeft(T->Left);//先对B,C进行左单旋
    	T= RotateRight(T);//再对C,A进行右单旋
    
    	//修改平衡因子
    	T->Right->balance = AVLHeight(T->Right->Left) - AVLHeight(T->Right->Right);//A
    	T->Left->balance = AVLHeight(T->Left->Left) - AVLHeight(T->Left->Right);//B
    	return T;
    }
    AVLTree RotateRightLeft(AVLTree T)//先右旋后左双旋转(RL型调整)
    {
        if (T == NULL || T->Right == NULL || T->Left)
            return NULL;
        AVLTree tmp = RotateRight(T->Right);//先对B,C进行右单旋
    	T= RotateLeft(T);//在对C,A进行左单旋
    
    	//修改平衡因子
    	T->Right->balance = AVLHeight(T->Right->Left) - AVLHeight(T->Right->Right);//B
    	T->Left->balance = AVLHeight(T->Left->Left) - AVLHeight(T->Left->Right);//A
    	return T;
    }
    bool Insert(AVLTree& T, ElemType x)//插入(按照中序插入可得到一棵平衡二叉排序树)
    {
        if (T == NULL)
        {
            T = (AVLTree)malloc(sizeof(AVLTree));
            if (T == NULL)//开辟空间失败直接退出
                exit(0);
            else
            {
                T->data = x;
                T->Left = T->Right = NULL;
                T->balance = 0;
            }
        }
        else if (x < T->data)
        {
            Insert(T->Left, x);//x插入到左孩子中
            if (AVLHeight(T->Left) - AVLHeight(T->Right) == 2)
            {
                if (x < T->Left->data)//插入到T的左孩子的左子树中
                {
                    T = RotateRight(T);//右单旋
                }
                else//插入到T的左孩子的右子树中
                {
                    T = RotateLeftRight(T);//先左旋转后右旋转
                }
            }
        }
        else if (x > T->data)
        {
            Insert(T->Right, x);//插入到右孩子中
            if (AVLHeight(T->Left) - AVLHeight(T->Right) == -2)
            {
                if (x > T->Right->data)//插入到T的右孩子的右子树中
                {
                    T = RotateLeft(T);//左单旋
                }
                else//插入到T的右孩子的左子树中
                {
                    T = RotateRightLeft(T);//先右旋转后左旋转
                }
            }
        }
    	else//插入的数据和当前结点数据一样大的时候,不进行插入操作
    	{
    		;
    	}
        T->balance = AVLHeight(T->Left) - AVLHeight(T->Right);
        return true;
    }
    
    bool Insert2(AVLTree& T, ElemType x)//插入(方法二) 
    {
    	AVLTreeNode* s = (AVLTreeNode*)malloc(sizeof(AVLTreeNode));
    	if (s == NULL)
    		return false;
    	if (T == NULL)//T原本是一棵空树
    	{
    		T = (AVLTree)malloc(sizeof(AVLTree));
    		if (T == NULL)//开辟空间失败直接退出
    			exit(0);
    		else
    		{
    			T->data = x;
    			T->Left = T->Right = NULL;
    			T->balance = 0;
    		}
    	}
    	else//找失去平衡的最小子树
    	{
    		s->data = x;//结点s用于保存x的值
    		s->Left = s->Right = NULL;
    		s->balance = 0;
    		if (T == NULL)
    		{
    			T = s;
    		}
    		else//首先查找s的插入位置,同时记录s的插入位置最近的且平衡因子不等于0(等于-1或1)的结点A,A为可能失衡的点
    		{
    			AVLTreeNode* A = T;//用A表示失去平衡的最小子树的根结点
    			AVLTreeNode* p = T;//p用于查找x插入的位置
    			AVLTreeNode* f = (AVLTreeNode*)malloc(sizeof(AVLTreeNode));//f用于保存x能插入的位置(p的父结点)
    			if (f == NULL)
    				exit(0);
    			while (p != NULL)//寻找x能插入的位置
    			{
    				if (p->balance != 0)
    				{
    					A = p;
    				}
    				f = p;
    				if (x < p->data)//x小于当前结点的值
    				{
    					p = p->Left;//转到当前结点的左子树找
    				}
    				else if(x>p->data)//x大于当前结点的值
    				{
    					p = p->Right;//转到当前结点的右子树找
    				}
    				else//x等于当前结点的值,不进行插入操作
    				{
    					return false;
    				}
    			}
    			//插入x
    			if (x < f->data)//x小于f的值,插入到左边
    			{
    				f->Left = s;
    			}
    			else//x大于f的值,插入到左边
    			{
    				f->Right = s;
    			}
    
    			//确定B
    			AVLTreeNode* B = (AVLTreeNode*)malloc(sizeof(AVLTreeNode));
    			if (B == NULL)
    				exit(0);
    			if (x < A->data)
    			{
    				B = A->Left;
    				A->balance = AVLHeight(A->Left)-AVLHeight(A->Right);//修改A的平衡因子
    				//或者A->balance =A->balance+1;
    			}
    			else
    			{
    				B = A->Right;
    				A->balance = AVLHeight(A->Left) - AVLHeight(A->Right);//修改A的平衡因子
    				//或者A->balance =A->balance-1;
    			}
    
    			//修改B到s结点路径上的各结点的平衡因子(原值均为0)
    			p = B;
    			while (p != s)
    			{
    				if (x < p->data)
    				{
    					p->balance = AVLHeight(p->Left) - AVLHeight(p->Right);
    					//或者p->balance=1;
    					p = p->Left;
    				}
    				else
    				{
    					p->balance = AVLHeight(p->Left) - AVLHeight(p->Right);
    					//或者p->balance=-1
    					p = p->Right;
    				}
    			}
    
    			//判断失衡类型并且调整
    			if (A->balance == 2 && B->balance == 1)//(LL型调整)
    			{
    				A = RotateRight(A);//右旋转
    			}
    
    			else if (A->balance == -2 && B->balance == -1)//(RR型调整)
    			{
    				A= RotateLeft(A);//左旋转
    			}
    
    			else if (A->balance == 2 && B->balance == -1)//(LR型调整)
    			{
    				A = RotateLeftRight(A);//先左旋后右旋
    			}
    			else if (A->balance == -2 && B->balance == 1)//(RL型调整)
    			{
    				A= RotateRightLeft(A);//先右后左旋
    			}
    		}
    	}
    	return true;
    }
    
    AVLTree Delete(AVLTree T, ElemType x)//删除
    {
    	if (T == NULL)
    		return NULL;
    	else
    	{
    		if (x < T->data)
    			T->Left = Delete(T->Left, x);
    		else if (x > T->data)
    			T->Right = Delete(T->Right, x);
    		else
    		{
    			if (T->Left != NULL && T->Right != NULL)//该结点有左右两棵子树
    			{
    				AVLTreeNode* tmp = T->Right;//寻找删除结点的直接后继
    				AVLTreeNode* f = T;//f用于保存tmp(删除结点)的父结点
    				while (tmp->Left != NULL)
    				{
    					f = tmp;
    					tmp = tmp->Left;
    				}
    				T->data = tmp->data;
    				f->Left = NULL;
    				T->Right = Delete(T->Right, tmp->data);//删除tmp->data
    				if (AVLHeight(T->Left) - AVLHeight(T->Right) == 2)//删除的元素在右子树,此时判断左子树与右子树的高度差
    				{
    					if (T->Left->Right != NULL && AVLHeight(T->Left->Right) > AVLHeight(T->Left->Left))
    					{
    						RotateLeftRight(T);
    					}
    					else
    					{
    						RotateRight(T);
    					}
    				}
    			}
    			else//有一棵子树或者没有子树
    			{
    				AVLTreeNode* t = T;
    				if (T->Left == NULL)
    				{
    					T = T->Right;
    				}
    				else if (T->Right == NULL)
    				{
    					T = T->Left;
    				}
    				free(t);
    			}
    		}
    	}
    	return T;
    }
    void show(AVLTree T)//层次遍历
    {
    	AVLTreeNode* b[MAX];
    	int front = 0, rear = 0;//初始队头指针,队尾指针
    	b[rear] = T;//根结点入队
    	rear++;//队尾指针指向下一个入队的位置
    	while (front != rear)
    	{
            AVLTreeNode* s = b[front];//队头结点出队
    		cout << s->data << " ";
    		front = (front + 1) % MAX;
    		if (s->Left != NULL)
    		{
    			b[rear] = s->Left;
    			rear = (rear + 1) % MAX;
    		}
    		if (s->Right != NULL)
    		{
    			b[rear] = s->Right;
    			rear = (rear + 1) % MAX;
    		}
    	}
    	
    }
    
    int main()
    {
        AVLTree T;
        T = NULL;
    	Insert2(T, 5);//插入5
    	Insert2(T, 2);//插入2
    	Insert2(T, 6);//插入6
    	Insert2(T, 1);//插入1
    	Insert2(T, 7);//插入7
    	Insert2(T, 3);//插入3
    	Insert2(T, 4);//插入4
    	show(T);//层序遍历
    	cout << endl;
    	T=Delete(T, 7);
    	show(T);//层序遍历
    	cout << endl;
        return 0;
    }
    
    //                      5
    //                  /       \
    //                 2         6
    //              /     \        \
    //             1       3        7
    //                      \
    //                       4
    //
    
    

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值