zoukankan      html  css  js  c++  java
  • AVL




    /*
    ① 如果树 T 是 AVL 树,那么它的左右子树都是 AVL 树; ② T 的左右子树高度差小于等于 1。 高度是 O(logn) 平衡因子 = 每个结点的左子树高度 - 右子树高度 AVL 搜索树的搜索和二叉排序树搜索的算法一样, 但插入操作和删除操作就不能完全按照二叉排序树的插入和删除来进行 当在插入路径上存在不平衡点时,把离插入点最近的不平衡点称为A 节点 1) 插入前 A 节点平衡因子为-1,插入节点在 A 节点的左子树中,不影响树的平衡。 2) 插入前 A 节点平衡因子为 1,插入节点在 A 节点的右子树中,不影响树的平衡。 3) 插入前 A 节点平衡因子为 1,插入节点在 A 节点的左子树中,影响树的平衡。 4) 插入前 A 节点平衡因子为-1,插入节点在 A 节点的右子树中,影响树的平衡。 前面两种情况只要调整从 A 节点到插入节点路径上的平衡因子即可。 通常把第三种情况称为 L 型,如果插入在 A 节点的左子树的左子树中称为 LL 型, 插入在 A 节点的左子树的右子树中称为 LR 型。 同理,可以将第四种情况分为 RL 型和 RR 型两种 */ #include <stdlib.h> #include <stdio.h> #include <Windows.h> #define CAPI_SUCCESS 0 #define CAPI_FAILED 1 #define CAPI_NO_MEMORY 2 #define CAPI_NOT_FOUND 3 typedef struct BINTREEBASENODE_ST { int Magic; int NodeData; struct BINTREEBASENODE_ST *LeftNode; struct BINTREEBASENODE_ST *RightNode; struct BINTREEBASENODE_ST *ParentNode; } BINTREEBASENODE; typedef BINTREEBASENODE AVLTREENODE; typedef struct AVLTREE_ST { UINT NodeCount; /* AVL树的节点个数 */ AVLTREENODE *Root; /* AVL树的根节点 */ } AVLTREE; AVLTREE *AVLTree_Create(); void AVLTreeNode_Destroy(AVLTREENODE *TreeNode); void AVLTree_Destroy(AVLTREE *Tree); void *AVLTree_Find(AVLTREE *Tree, int Data); void AVLTree_FixBalance(AVLTREENODE *StartNode, int Data); void AVLTree_RotateLeft(AVLTREE *Tree, AVLTREENODE *StartNode); void BinTree_RotateLeft(BINTREEBASENODE *StartNode, BINTREEBASENODE **Root); void AVLTree_RotateRight(AVLTREE *Tree, AVLTREENODE *StartNode); void BinTree_RotateRight(BINTREEBASENODE *StartNode, BINTREEBASENODE **Root); void AVLTree_RotateLeftRight(AVLTREENODE **Root, AVLTREENODE *StartNode); void AVLTree_RotateRightLeft(AVLTREENODE **Root, AVLTREENODE *StartNode); int AVLTree_Insert(AVLTREE *Tree, int Data); int AVLTreeNode_Insert(AVLTREENODE **RootNode, int Data); void AVLTree_AdjustBalanceForDelete(AVLTREENODE **Root, AVLTREENODE *DeleteNode, int Data); int AVLTree_Delete(AVLTREE *Tree, int Data); int AVLTreeNode_Delete(AVLTREENODE **Root, int Data); void AVLTree_haha_1(AVLTREENODE* pNode) //测试函数 { if (pNode) { AVLTree_haha_1(pNode->LeftNode); printf("%d ", pNode->NodeData); AVLTree_haha_1(pNode->RightNode); } } int main() { AVLTREE* TreeRoot = AVLTree_Create(); //AVLTREENODE* TempNode; for (int i = 0; i < 5; i++) { AVLTree_Insert(TreeRoot, i); } for (int i = 30; i > 25; i--) { AVLTree_Insert(TreeRoot, i); } printf("%d ", TreeRoot->NodeCount); AVLTree_haha_1(TreeRoot->Root); AVLTree_Delete(TreeRoot, 3); printf(" %d ", TreeRoot->NodeCount); AVLTree_haha_1(TreeRoot->Root); AVLTree_Insert(TreeRoot, 5); printf(" %d ", TreeRoot->NodeCount); AVLTree_haha_1(TreeRoot->Root); AVLTree_Destroy(TreeRoot); getchar(); getchar(); return 0; } AVLTREE *AVLTree_Create() { AVLTREE* AvlTree; AvlTree = (AVLTREE *)malloc(sizeof(AVLTREE)); if (AvlTree != NULL) { AvlTree->Root = NULL; AvlTree->NodeCount = 0; } return AvlTree; } /* AVL 树的释放函数,将以某个指定节点为根节点的 AVL 树及树中的全部节点都释放, 采用后序遍历的方法释放 */ void AVLTreeNode_Destroy(AVLTREENODE *TreeNode) { if (TreeNode != NULL) { if (TreeNode->LeftNode != NULL) { AVLTreeNode_Destroy((AVLTREENODE*)TreeNode->LeftNode); } if (TreeNode->RightNode != NULL) { AVLTreeNode_Destroy((AVLTREENODE*)TreeNode->RightNode); } if (TreeNode != NULL) { free(TreeNode); TreeNode = NULL; } } } /*AVL 树的释放函数,将一颗 AVL 树释放*/ void AVLTree_Destroy(AVLTREE *Tree) { if (Tree != NULL) { AVLTreeNode_Destroy(Tree->Root); free(Tree); Tree = NULL; } return; } /*AVL 树的查找函数,调用了二叉搜索树的查找函数进行查找*/ void *AVLTree_Find(AVLTREE *Tree, int Data) { BINTREEBASENODE *TempNode; TempNode = Tree->Root; while (TempNode != NULL) { int v1 = Data - TempNode->NodeData; if (v1 < 0) { TempNode = TempNode->RightNode; } else if (v1 > 0) { TempNode = TempNode->LeftNode; } else { return TempNode; } } return NULL; } /* AVL树的调整平衡函数,主要是调整插入操作时的平衡 */ void AVLTree_FixBalance(AVLTREENODE *StartNode,int Data) { AVLTREENODE *TempNode; AVLTREENODE *SearchNode; int Result; TempNode = StartNode; while (TempNode != NULL) { SearchNode = TempNode; Result = TempNode->NodeData - Data; if (Result < 0) { TempNode = TempNode->RightNode; SearchNode->Magic -= 1; } else if (Result > 0) { TempNode = TempNode->LeftNode; SearchNode->Magic += 1; } else { /* 找到相同关键词的节点, 中止 */ break; } } return; } /* AVL树的左旋函数 */ void AVLTree_RotateLeft(AVLTREE *Tree, AVLTREENODE *StartNode) { BinTree_RotateLeft((BINTREEBASENODE *)StartNode, &(Tree->Root)); } /** 二叉排序树的左旋操作函数 @param BINTREEBASENODE *StartNode - 要旋转的基节点 @param BINTREEBASENODE **Root - 二叉排序树的根节点 @return void - 无 */ void BinTree_RotateLeft(BINTREEBASENODE *StartNode, BINTREEBASENODE **Root) { BINTREEBASENODE *BNode; /* B节点指针 */ BNode = StartNode->RightNode; /* 将B节点的左节点变成A节点的右节点 */ StartNode->RightNode = BNode->LeftNode; if (BNode->LeftNode != NULL) { BNode->LeftNode->ParentNode = StartNode; } /* 修改A节点的父指针和B节点的关系 */ BNode->ParentNode = StartNode->ParentNode; if (StartNode == *Root) { *Root = BNode; } else if (StartNode == StartNode->ParentNode->LeftNode) { StartNode->ParentNode->LeftNode = BNode; } else { StartNode->ParentNode->RightNode = BNode; } /* 将A节点变成B节点的左节点 */ BNode->LeftNode = StartNode; StartNode->ParentNode = BNode; } /* AVL树的右旋函数 */ void AVLTree_RotateRight(AVLTREE *Tree, AVLTREENODE *StartNode) { BinTree_RotateRight((BINTREEBASENODE *)StartNode, &(Tree->Root)); } /** 二叉排序树的右旋操作函数 @param BINTREEBASENODE *StartNode - 要旋转的基节点 @param BINTREEBASENODE **Root - 二叉排序树的根节点 @return void - 无 */ void BinTree_RotateRight(BINTREEBASENODE *StartNode, BINTREEBASENODE **Root) { BINTREEBASENODE *BNode; /* B节点指针 */ BNode = StartNode->LeftNode; /* 将B节点的右节点变成A节点的左节点 */ StartNode->LeftNode = BNode->RightNode; if (BNode->RightNode != NULL) { BNode->RightNode->ParentNode = StartNode; } /* 修改A节点的父指针和B节点的关系 */ BNode->ParentNode = StartNode->ParentNode; if (StartNode == *Root) { *Root = BNode; } else if (StartNode == StartNode->ParentNode->RightNode) { StartNode->ParentNode->RightNode = BNode; } else { StartNode->ParentNode->LeftNode = BNode; } /* 将A节点变成B节点的左节点 */ BNode->RightNode = StartNode; StartNode->ParentNode = BNode; } /** AVL树的双旋转操作函数,先左旋再右旋 @param AVLTREENODE **Root - AVL树的根节点指针 @param AVLTREENODE *StartNode - 要旋转的节点 @return void - 无 */ void AVLTree_RotateLeftRight(AVLTREENODE **Root, AVLTREENODE *StartNode) { AVLTREENODE* ANode; AVLTREENODE* BNode; AVLTREENODE* CNode; int Ret; Ret = 0; ANode = StartNode; BNode = ANode->LeftNode; CNode = BNode->RightNode; BinTree_RotateLeft(BNode, Root); BinTree_RotateRight(ANode, Root); switch (CNode->Magic) { case 1: /* 插入在C节点左子树的情况 */ ANode->Magic = -1; BNode->Magic = 0; break; case -1: /* 插入在C节点右子树的情况 */ ANode->Magic = 0; BNode->Magic = 1; break; default: /* C节点就是插入点的情况 */ ANode->Magic = 0; BNode->Magic = 0; break; } CNode->Magic = 0; } /** AVL树的双旋转函数 @param AVLTREENODE **Root - AVL树根节点指针 @param AVLTREENODE *StartNode - 要旋转的节点指针 @return void - 无 */void AVLTree_RotateRightLeft(AVLTREENODE **Root, AVLTREENODE *StartNode) { AVLTREENODE *ANode; AVLTREENODE *BNode; AVLTREENODE *CNode; int Ret; Ret = 0; ANode = StartNode; BNode = ANode->RightNode; CNode = BNode->LeftNode; BinTree_RotateRight(BNode, Root); BinTree_RotateLeft(ANode, Root); switch (CNode->Magic) { case 1: /* 插入在C节点左子树的情况 */ ANode->Magic = 0; BNode->Magic = -1; break; case -1: /* 插入在C节点右子树的情况 */ ANode->Magic = 1; BNode->Magic = 0; break; default: /* C节点就是插入点的情况 */ ANode->Magic = 0; BNode->Magic = 0; break; } CNode->Magic = 0; } /** AVL树的插入操作函数 @param AVLTREE *Tree - AVL树 @param int Data - 要插入的数据指针 */ int AVLTree_Insert(AVLTREE *Tree, int Data) { INT nRet; if (Tree == NULL) { return CAPI_FAILED; } nRet = AVLTreeNode_Insert(&(Tree->Root), Data); if (nRet != CAPI_FAILED) { Tree->NodeCount += 1; } return nRet; } /** AVL树的插入数据函数,将一个数据插入到AVL树中 @param AVLTREENODE **RootNode - 要插入的AVL树根节点指针 @param int Data - 要插入的数据 @return INT - CAPI_SUCCESS表示插入成功,CAPI_FAILED表示失败,失败的原因有 内存分配失败和已存在相同关键词数据两种情况 */ int AVLTreeNode_Insert(AVLTREENODE **RootNode, int Data) { AVLTREENODE *TempNode; AVLTREENODE *ANode; AVLTREENODE *NewNode; AVLTREENODE *SearchNode; AVLTREENODE *BNode; AVLTREENODE *CNode; int Ret; Ret = 0; ANode = NULL; SearchNode = NULL; /* 查找要插入的节点位置,并且在查找过程中要记录最后一个不平衡的节点 */ TempNode = *RootNode; while (TempNode != NULL) { SearchNode = TempNode; if (SearchNode->Magic == -1 || SearchNode->Magic == 1) { ANode = SearchNode; } Ret = TempNode->NodeData - Data; if (Ret < 0) { TempNode = TempNode->RightNode; } else if (Ret > 0) { TempNode = TempNode->LeftNode; } else { /* 找到相同关键词的节点,插入失败 */ return CAPI_FAILED; } } NewNode = (AVLTREENODE *)malloc(sizeof(AVLTREENODE)); if (NewNode == NULL) { return CAPI_FAILED; } NewNode->NodeData = Data; NewNode->LeftNode = NULL; NewNode->RightNode = NULL; NewNode->ParentNode = SearchNode; NewNode->Magic = 0; if (SearchNode == NULL) { *RootNode = NewNode; return CAPI_SUCCESS; } if (Ret < 0) { SearchNode->RightNode = NewNode; } else { SearchNode->LeftNode = NewNode; } /* 不存在不平衡的节点,直接插入后再修改平衡因子即可 */ if (ANode == NULL) { /* 修改从根节点到插入节点的平衡因子 */ AVLTree_FixBalance(*RootNode, Data); return CAPI_SUCCESS; } Ret = ANode->NodeData - Data; /* 以下处理存在不平衡节点的情况 */ if ((ANode->Magic == 1 && Ret < 0) || (ANode->Magic == -1 && Ret > 0)) { /* A节点平衡因子为1且插入节点插入在右子树的情况 * 以及A节点平衡因子为-1且插入在左子树的情况 * 这两种情况插入后还是平衡树,只需修改相关节点平衡因子 */ AVLTree_FixBalance(ANode, Data); } else if (ANode->Magic == 1 && Ret > 0) { if ((ANode->LeftNode->NodeData - Data) > 0) { /* LL型不平衡, 插入在A节点的左子树的左子树中 */ BNode = ANode->LeftNode; BinTree_RotateRight(ANode, RootNode); AVLTree_FixBalance(BNode, Data); ANode->Magic = 0; BNode->Magic = 0; } else { int RetVal; /* LR型不平衡, 插入在A节点的左子树的右子树中 */ BNode = ANode->LeftNode; CNode = BNode->RightNode; RetVal = CNode->NodeData - Data; if (RetVal > 0) { CNode->Magic += 1; } else if (RetVal < 0) { CNode->Magic -= 1; } AVLTree_RotateLeftRight(RootNode, ANode); if (RetVal > 0) { AVLTree_FixBalance(BNode, Data); } else if (RetVal < 0) { AVLTree_FixBalance(ANode, Data); } else { } } } else /* pANode->nMagic == -1 && nRet < 0 的情况*/ { if ((ANode->RightNode->NodeData - Data) > 0) { int RetVal; /* RL型不平衡, 插入在A节点的右子树的左子树中 */ BNode = ANode->RightNode; CNode = BNode->LeftNode; RetVal = CNode->NodeData - Data; if (RetVal > 0) { CNode->Magic += 1; } else if (RetVal < 0) { CNode->Magic -= 1; } AVLTree_RotateRightLeft(RootNode, ANode); if (RetVal > 0) { AVLTree_FixBalance(ANode, Data); } else if (RetVal < 0) { AVLTree_FixBalance(BNode, Data); } else { } } else { /* RR型不平衡, 插入在A节点的右子树的右子树中 */ BNode = ANode->RightNode; BinTree_RotateLeft(ANode, RootNode); AVLTree_FixBalance(BNode, Data); ANode->Magic = 0; BNode->Magic = 0; } } return CAPI_SUCCESS; } /* AVL树的删除操作调整平衡函数,由删除函数调用 @param AVLTREENODE **Root - 指向AVL树的根节点指针的指针 @param AVLTREENODE *Node - 要调整平衡的节点 @param int Data - 删除的数据指针 @return void - 无 */ void AVLTree_AdjustBalanceForDelete(AVLTREENODE **Root, AVLTREENODE *DeleteNode,int Data) { AVLTREENODE *ANode; AVLTREENODE *ParentNode; AVLTREENODE *BNode; ANode = DeleteNode; while (ANode != NULL) { switch (ANode->Magic) { case 0: if (ANode == *Root) { /* pANode为根节点,高度减少了1,但左右子树高度相等,无需调整 */ break; } else { ParentNode = ANode->ParentNode; if (ANode == ParentNode->LeftNode) { ParentNode->Magic -= 1; } else { ParentNode->Magic += 1; } /* 将pANode 指向它的父节点,继续调整它的父节点的不平衡情况 */ ANode = ParentNode; continue; } case -1: case 1: /* pANode原来的平衡因子为0,删除操作发生后,高度未改变,因此不需要 * 再调整,退出即可 */ break; case -2: /* L型不平衡情况 */ BNode = ANode->RightNode; if (BNode->Magic == 0) { /* L0型不平衡情况 */ BinTree_RotateLeft(ANode, Root); ANode->Magic = -1; BNode->Magic = 1; break; } else if (BNode->Magic == -1) { /* L-1型不平衡情况 */ ParentNode = ANode->ParentNode; if (ParentNode != NULL) { if (ANode == ParentNode->LeftNode) { ParentNode->Magic -= 1; } else { ParentNode->Magic += 1; } } BinTree_RotateLeft(ANode, Root); ANode->Magic = 0; BNode->Magic = 0; /* 将pANode 指向它的父节点,继续调整它的父节点的不平衡情况 */ ANode = ParentNode; } else /* pBNode->nMagic == 1的情况 */ { /* L1型的情况 */ ParentNode = ANode->ParentNode; if (ParentNode != NULL) { if (ANode == ParentNode->LeftNode) { ParentNode->Magic -= 1; } else { ParentNode->Magic += 1; } } AVLTree_RotateRightLeft(Root, ANode); /* 将pANode 指向它的父节点,继续调整它的父节点的不平衡情况 */ ANode = ParentNode; } continue; /* 继续while() 循环 */ case 2: /* R型不平衡情况 */ BNode = ANode->LeftNode; if (BNode->Magic == 0) { /* R0型不平衡情况 */ BinTree_RotateRight(ANode, Root); ANode->Magic = 1; BNode->Magic = -1; break; } else if (BNode->Magic == -1) { /* R-1型不平衡情况 */ ParentNode = ANode->ParentNode; if (ParentNode != NULL) { if (ANode == ParentNode->LeftNode) { ParentNode->Magic -= 1; } else { ParentNode->Magic += 1; } } AVLTree_RotateLeftRight(Root, ANode); /* 将pANode 指向它的父节点,继续调整它的父节点的不平衡情况 */ ANode = ParentNode; } else /* pBNode->nMagic == 1的情况 */ { /* R1型的情况 */ ParentNode = ANode->ParentNode; if (ParentNode != NULL) { if (ANode == ParentNode->LeftNode) { ParentNode->Magic -= 1; } else { ParentNode->Magic += 1; } } BinTree_RotateRight(ANode, Root); ANode->Magic = 0; BNode->Magic = 0; /* 将pANode 指向它的父节点,继续调整它的父节点的不平衡情况 */ ANode = ParentNode; } continue; /* 继续while() 循环 */ default: break; } /* switch ( pANode->nMagic ) */ break; } } /* AVL树的删除操作函数 @param AVLTREE *pTree - AVL树指针 @param void *pData - 要删除的数据指针 @return INT - CAPI_FAILED表示失败,CAPI_SUCCESS表示成功 */ int AVLTree_Delete(AVLTREE *Tree, int Data) { if (Tree->Root == NULL) { return CAPI_FAILED; } if (AVLTreeNode_Delete(&(Tree->Root), Data) != CAPI_NOT_FOUND) { Tree->NodeCount -= 1; } return CAPI_SUCCESS; } /** AVL树的删除节点函数 @param AVLTREENODE **ppRoot - 指向AVL树根节点指针的指针 @param int pData - 要删除的数据 @return INT - CAPI_FAILED表示失败,CAPI_SUCCESS表示成功 */ int AVLTreeNode_Delete(AVLTREENODE **Root, int Data) { AVLTREENODE *Node; AVLTREENODE *ANode; AVLTREENODE *DelNode; int DelData; int Ret = 0; Node = *Root; while (Node != NULL) { Ret = Node->NodeData - Data; if (Ret < 0) { Node = Node->RightNode; } else if (Ret > 0) { Node = Node->LeftNode; } else { break; } } if (Node == NULL) { return CAPI_NOT_FOUND; } DelData = Node->NodeData; if (Node->LeftNode != NULL && Node->RightNode != NULL) { /* 处理查找到的Node有两个子节点的情况 */ DelNode = Node->LeftNode; while (DelNode->RightNode != 0) { DelNode = DelNode->RightNode; } ANode = DelNode->ParentNode; Node->NodeData = DelNode->NodeData; if (DelNode != Node->LeftNode) { ANode->RightNode = DelNode->LeftNode; } else { ANode->LeftNode = DelNode->LeftNode; } if (DelNode->LeftNode != NULL) { DelNode->LeftNode->ParentNode = ANode; } if (DelNode == ANode->LeftNode) { ANode->Magic -= 1; } else { ANode->Magic += 1; } } else { ANode = Node; /* 处理最多只有一个子节点的情况 */ if (Node->LeftNode != NULL) { /* 只有左节点的情况 */ DelNode = Node->LeftNode; Node->NodeData = DelNode->NodeData; Node->LeftNode = NULL; ANode->Magic -= 1; } else if (Node->RightNode != NULL) { /* 只有右节点的情况 */ DelNode = Node->RightNode; Node->NodeData = DelNode->NodeData; Node->RightNode = NULL; ANode->Magic += 1; } else { /* 处理删除节点的左右子节点都不存在的情况 */ ANode = Node->ParentNode; DelNode = Node; if (ANode == NULL) { *Root = ANode; } else if (ANode->LeftNode == Node) { ANode->LeftNode = NULL; ANode->Magic -= 1; } else { ANode->RightNode = NULL; ANode->Magic += 1; } } } /* 删除对应节点 */ free(DelNode); /* 调整平衡 */ if (ANode != NULL) { AVLTree_AdjustBalanceForDelete(Root, ANode, Data); } return CAPI_SUCCESS; }
    爱程序 不爱bug 爱生活 不爱黑眼圈 我和你们一样 我和你们不一样 我不是凡客 我要做geek
  • 相关阅读:
    使用Linux输出重定向将debug信息和ERROR信息分离
    C#中的委托和事件
    C#中如何把函数当做参数传递到别的函数中
    c#中的引用类型和值类型
    浅谈内联函数与宏定义的区别详解
    JVM原理讲解和调优
    判断Python输入是否为数字
    python异常处理
    bmi健康指数
    python查询mangodb
  • 原文地址:https://www.cnblogs.com/yifi/p/6420253.html
Copyright © 2011-2022 走看看