平衡二叉树(AVL树)
来源:互联网 发布:网络摄像机哪个好 编辑:程序博客网 时间:2024/06/06 04:12
平衡二叉树是在二叉搜索树的基础上增加了限制:
①:树的深度为logN。
②:每个节点的左子树和右子树的高度最多差一的二叉搜索树。
基本操作:调整!!!
引入平衡因子:左右子树的高度差。
当平衡因子绝对值大于等于2的时候,就需要调整。
单旋转比较简单,直接把被破坏节点下一个节点提上去,然后再根据二叉搜索树的特点进行换儿子即可。如下图:
实现:
#include<stdio.h>#include<stdlib.h>#define ElementType inttypedef struct BiNode{ ElementType Data; int Height; struct BiNode* Left; struct BiNode* Right;} BiNode, *BinTree,*Position;int Height(Position P){ if(!p)return 0; else return P->Height;}//为什么非要用这个函数?直接用结构体中的不行吗?---NULL!!!Position Single_Rotate_With_Left(Position K2)//把k2的左儿子k1提上去,k2当k1的右儿子。{Position K1 = K2->Left;K2->Left = K1->Right;//换儿子K1->Right = K2;//提上去K2->Height = max(Height(K2->Left), Height(K2->Right)) + 1;K1->Height = max(Height(K1->Left), Height(K1->Right)) + 1;return K1;}Position Single_Rotate_With_Right(Position K2){Position K1 = K2->Right;K2->Right = K1->Left;K1->Left = K2;K2->Height = max(Height(K2->Left), Height(K2->Right)) + 1;K1->Height = max(Height(K1->Left), Height(K1->Right)) + 1;return K1;}
双旋转是“麻烦节点”在左儿子的右边,或者右儿子的左边。如下图:这时候是把麻烦节点提上去,然后再进行儿子的交换即可。
实现:可以通过两次单旋转进行完成,避免了换儿子的过程。
Position Double_Rotate_With_Left(Position K3){K3->Left = Single_Rotate_With_Right(K3->Left);return Single_Rotate_With_Left(K3);}Position Double_Rotate_With_Right(Position K3){K3->Right = Single_Rotate_With_Left(K3->Right);return Single_Rotate_With_Right(K3);}Position Double_Rotate_With_Left(Position K3){ Position K2=K3->Left->Right,K1=K3->Left; K3->Left=K2->Right;//换儿子 K2->Right=K3;//提 K1->Right=K2->Left;//换儿子 K2->Left=K1;//提}
AVL树的插入,在二叉搜索树插入的基础上,增添调整就可以!
注意这里有递归回溯。(拓展GCD有没有)。
至于删除,我的思路是假设是删除左边了,这时候要看根节点右边的树高是否比左边树高大于等于2,然后进而根据右子树对应的左树高和右树高,右大于左,那就要对根节点进行RR旋转,否则RL旋转。(网上都是引入的平衡因子,也就是高度差,我这种想法的正确与否,考完期末再写个例子进行检验~!插入的历程是正确的(直接在黑书上拿来的。))。
BinTree Insert( ElementType X, BinTree BST )if( !BST ){ BST = (Bintree)malloc(sizeof(struct TreeNode)); BST->Data = X; BST->Left = BST->Right = NULL; BST->Height=1;}else if( X < BST->Data ){ BST->Left = Insert( X, BST->Left); if(Height(BST->Left)-Height(BST->Right)==2)//自底向上回溯 if(X<BST->Left->Data) BST=Single_Rotate_With_Left(BST); else BST=Position Double_Rotate_With_Left(BST);}else if( X > BST->Data ){ BST->Right = Insert( X, BST->Right); if(Height(BST->Right)-Height(BST->Left)==2) if(X>BST->Right->Data) BST=Single_Rotate_With_Right(BST); else BST=Double_Rotate_With_Right(BST);}/* else X已经存在,什么都不做 */BST->Height=max(Height(BST->left),Height(BST->Right))+1;//更新树高return BST;}BinTree Delete( ElementType X, BinTree BST ){ Position Tmp; if( !BST ) printf("要删除的元素未找到"); else if( X < BST->Data ) { BST->Left = Delete( X, BST->Left); /* 左子树递归删除 */ if(Height(BST->Right)-Height(BST->Left)==2) if(Height(BST->Right->Right)>=Height(BST->Right->Left)) Single_Rotate_With_Right(BST); else Double_Rotate_With_Right(BST); } else if( X > BST->Data ) { BST->Right = Delete( X, BST->Right); if(Height(BST->Left)-Height(BST->Right)==2) if(Height(BST->Left->Left)>=Height(BST->Left->Right)) Single_Rotate_With_Left(BST); else Double_Rotate_With_Left(BST); }/* 右子树递归删除 */ else /*找到要删除的结点 */ if( BST->Left && BST->Right ) { /*被删除结点有左右两个子结点 */ Tmp = FindMin( BST->Right ); /*在右子树中找最小的元素填充删除结点*/ BST->Data = Tmp->Data; BST->Right = Delete( BST->Data, BST->Right); /*在删除结点的右子树中删除最小元素*/ if(Height(BST->Right)-Height(BST->Left)==2) if(Height(BST->Right->Right)>=Height(BST->Right->Left)) Single_Rotate_With_Right(BST); else Double_Rotate_With_Right(BST); } else { /*被删除结点有一个或无子结点*/ Tmp = BST; if( !BST->Left ) /* 有右孩子或无子结点*/ BST = BST->Right; else if( !BST->Right ) /*有左孩子或无子结点*/ BST = BST->Left; free( Tmp ); } BST->Height=max(Height(BST->left),Height(BST->Right))+1;//更新树高 return BST;}
阅读全文
0 0
- 平衡二叉树(AVL)
- 平衡二叉树(AVL)
- 平衡二叉树(AVL)
- AVL 平衡二叉树
- 平衡二叉树(AVL)
- 平衡二叉树(AVL)
- AVL 平衡二叉树
- avl平衡二叉树
- 二叉平衡树AVL
- 平衡二叉树(AVL)
- 平衡二叉树(AVL)
- 平衡二叉树 AVL
- 平衡二叉树(AVL)
- 平衡二叉树(AVL)
- 平衡二叉树(AVL)
- 平衡二叉树(AVL)
- 平衡二叉树(AVL)
- 二叉平衡树AVL
- 浅析HashMap
- 浅析ArrayList
- SSM项目从零开始到入门009-使用mybatis提供的动态代理
- Java多线程原理及使用探讨
- webstrom识别 React语法
- 平衡二叉树(AVL树)
- 文档处理Spire 热门控件介绍
- TCP缓冲区
- Android WebView + ProgressBar Loading
- 基本工具使用
- java--多线程/并发--概述
- 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
- NSURL的一些属性
- python面向对象详解