平衡二叉树(AVL)
AVL树是基于二叉搜索树的,它要求它的左右子树的高度差绝对值不超过1。
AVL树主要用在对一颗二叉搜索树进行插入时,如何保证树的平均查找长度最小?
这就需要在插入时进行相应的调整,使AVL树的左右高度差不超过1。
代码如下:
//AVL.h /************************************************************* 平衡二叉树,是建立在二叉搜索树上,在旋转调整 过程中一定要注意,要满足二叉搜索树的定义。 设A为平衡被破坏节点,B为A的儿子,C为B的儿子 单旋转:LL和RR俩种, 左单旋(LL,顺时针): 若: B = A->Left, C =B->Right 则: B ->Right = A , A ->Left = C; 最后把B挂在A原来的父亲后面 右单旋(RR,逆时针):若:B =A-Right, C =B->Left 则:B ->Left = A, A->Right = C; 最后把B挂在A原来的父亲后面 双旋转:LR和RL两种, LR: 先RR调整后LL调整。大致情况如下: 条件: B = A->Left, C =B->Right; 则: B ->Right =C->Left , C ->Left= B A->Left = C->Right, C->Right = A RL:先LL后RR. 条件: B=A->Right, C =B->Left; 则:B->Left = C->Right , C->Right =B; A->Right =C->Left ,C = C ->Left = C; 注意理解旋转,左单旋顺时针,右单旋逆时针。 *****************************************************************/ typedef struct AVLNode *Position; typedef Position AVLTree; struct AVLNode{ int Data; AVLTree Left; AVLTree Right; int Height; }; int GetHeight(AVLTree); AVLTree SingleLeftRotation(AVLTree); AVLTree SingleRightRotation(AVLTree); AVLTree DoubleLeftRightRotation(AVLTree); AVLTree DoubleRightLeftRotation(AVLTree); AVLTree Insert(AVLTree, int); void PreOrderTraversal(AVLTree); AVLTree BuildTree();
//.cpp #include <stdio.h> #include <stdlib.h> #include "AVL.h" int Max(int a, int b) { return a > b ? a : b; } /********************************************** 用后序遍历改编,即用递归先找到 叶子节点,然后每退一次 高度就加一; ***********************************************/ int GetHeight(AVLTree A) { int MaxH, HR, HL; if (A){ HL = GetHeight(A->Left); HR = GetHeight(A->Right); MaxH = (HL > HR) ? HL : HR; return MaxH+1; } return -1; //如果树为空树高为 -1,叶子节点为0; } /*LL旋转*/ AVLTree SingleLeftRotation(AVLTree A) { AVLTree B = A->Left; A->Left = B->Right; B->Right = A; A->Height = Max(GetHeight(A->Left), GetHeight(A->Right)) + 1; B->Height = Max(GetHeight(B->Left), A->Height) + 1; return B; } /*RR旋转*/ AVLTree SingleRightRotation(AVLTree A) { AVLTree B = A->Right; A->Right = B->Left; B->Left = A; A->Height = Max(GetHeight(A->Left), GetHeight(A->Right)) + 1; B->Height = Max(A->Height, GetHeight(B->Right)) + 1; return B; } /*LR旋转*/ AVLTree DoubleLeftRightRotation(AVLTree A) { A->Left = SingleRightRotation(A->Left); return SingleLeftRotation(A); } /*RL旋转*/ AVLTree DoubleRightLeftRotation(AVLTree A) { A->Right = SingleLeftRotation(A->Right); return SingleRightRotation(A); } AVLTree Insert(AVLTree T, int x) { if (!T){ T = (AVLTree)malloc(sizeof(struct AVLNode)); T->Data = x; T->Height = 0; T->Left = T->Right = NULL; } else { //x 插在左边 if (x < T->Data){ T->Left = Insert(T->Left, x); if (GetHeight(T->Left) - GetHeight(T->Right) == 2){ if (x<T->Left->Data) //判断x在T的左儿子那边 T = SingleLeftRotation(T); else T = DoubleLeftRightRotation(T); } } //x插在右边 else if (x>T->Data){ T->Right = Insert(T->Right, x); if (GetHeight(T->Left) - GetHeight(T->Right) == -2){ if (x > T->Right->Data) T = SingleLeftRotation(T); else T = DoubleRightLeftRotation(T); } } } //加1更新高度 T->Height = Max(GetHeight(T->Left), GetHeight(T->Right)) + 1; return T; } void PreOrderTraversal(AVLTree A) { if (A){ printf("value =%d height=%d\n", A->Data, A->Height); PreOrderTraversal(A->Left); PreOrderTraversal(A->Right); } } AVLTree BuildTree() { AVLTree A = NULL; int n; while (scanf_s("%d", &n) != EOF) A = Insert(A,n); return A; } int main() { AVLTree A; A = BuildTree(); PreOrderTraversal(A); putchar('\n'); printf("请输入你要插入的数 \n"); int n; while (scanf_s("%d", &n) != EOF){ Insert(A, n); PreOrderTraversal(A); printf("Next number:\n"); } return 0; }
推荐:VisuAlgo(https://visualgo.net/en) 可视化工具
坚持!!!!!!!!!!!!

浙公网安备 33010602011771号