avltree insert(int data, avltree T){ if(!T){ T=(avltree)malloc(sizeof(struct avltreeNode)); T->data=data; T->height=0; T->left=T->right=NULL; // printf("%d\n",T->data); } else if(data < T->data){ T->left=insert(data,T->left); if(GetHeight(T->left)-GetHeight(T->right)==2) if(data < T->left->data) T=SingleLeftRotation(T); else T=DoubleLeftRightRotation(T); // printf("%d\n",T->data); } else if(data > T->data){ T->right=insert(data,T->right); if(GetHeight(T->left)-GetHeight(T->right)==-2) if(data > T->right->data) T=SingleRightRotation(T); else T=DoubleRightLeftRotation(T); // printf("%d\n",T->data); } T->height=Max(GetHeight(T->left),GetHeight(T->right))+1; // printf("height:%d\n",T->height); return T; }
AVLTree AVL_Insertion(ElementType x, AVLTree T) { if(!T) { T = (AVLTree)malloc(sizeof(AVLTreeNode)); T->Data = x; T->Height = 0; T->Left = T->Right = NULL; } else if(x < T->Data) { T->Left = AVL_Insertion(x, T->Left); if(GetHeight(T->Left) - GetHeight(T->Right) == 2) { if(x < T->Left->Data) T = SingleLeftRotation(T); else T = DoubleLeftRightRotation(T); } } else if(x > T->Data) { T->Right = AVL_Insertion(x, T->Right); if(GetHeight(T->Right) - GetHeight(T->Left) == 2) { if(x > T->Right->Data) T = SingRightRotation(T); else T = DoubleRightLeftRotation(T); } } T->Height = Max(GetHeight(T->Left), GetHeight(T->Right)) + 1; return T; }
/******************************************************************************* Função que faz o reequilíbrio do nó pretendido da AVL. Function that balances the tree if necessary in each node that does not respect the equilibrium rule, after insertion and deletion operations. *******************************************************************************/ static void Balance (PtAVLNode *proot) { unsigned int LeftH, RightH; if (*proot == NULL) return; /* subárvore vazia - empty tree */ LeftH = AVLHeight ((*proot)->PtLeft); /* altura subárvore esquerda - left subtree height */ RightH = AVLHeight ((*proot)->PtRight); /* altura subárvore direita - right subtree height */ if (LeftH - RightH == 2) /* subárvore esquerda desequilibrada? - left subtree unbalanced? */ { LeftH = AVLHeight ((*proot)->PtLeft->PtLeft); RightH = AVLHeight ((*proot)->PtLeft->PtRight); if (LeftH >= RightH) SingleRightRotation (proot); else DoubleLeftRightRotation (proot); } else if (RightH - LeftH == 2) /* subárvore direita desequilibrada? - right subtree unbalanced? */ { RightH = AVLHeight ((*proot)->PtRight->PtRight); LeftH = AVLHeight ((*proot)->PtRight->PtLeft); if (RightH >= LeftH) SingleLeftRotation (proot); else DoubleRightLeftRotation (proot); } else (*proot)->Height = LeftH > RightH ? LeftH + 1 : RightH + 1; /* atualizar a altura do nó - updationg the node height */ }
AVLTree DoubleLeftRightRotation ( AVLTree A ) { /* 注意:A必须有一个左子结点B,且B必须有一个右子结点C */ /* 将A、B与C做两次单旋,返回新的根结点C */ /* 将B与C做右单旋,C被返回 */ A->Left = SingleRightRotation(A->Left); /* 将A与C做左单旋,C被返回 */ return SingleLeftRotation(A); }
AVLTree DoubleLeftRightRotation(AVLTree A) { A->Left = SingRightRotation(A->Left); return SingleLeftRotation(A); // AVLTree B = A->Left; // AVLTree C = B->Right; // A->Left = C->Right; // B->Right = C->Left; // C->Left = B; // C->Right = A; // A->Height = Max(GetHeight(A->Left), GetHeight(A->Right)) + 1; // B->Height = Max(GetHeight(B->Left), GetHeight(B->Right)) + 1; // C->Height = Max(GetHeight(C->Left), GetHeight(C->Right)) + 1; }
AVLTree Insert( AVLTree T, ElementType X ) { /* 将X插入AVL树T中,并且返回调整后的AVL树 */ if ( !T ) { /* 若插入空树,则新建包含一个结点的树 */ T = (AVLTree)malloc(sizeof(struct AVLNode)); T->Data = X; T->Height = 0; T->Left = T->Right = NULL; } /* if (插入空树) 结束 */ else if ( X < T->Data ) { /* 插入T的左子树 */ T->Left = Insert( T->Left, X); /* 如果需要左旋 */ if ( GetHeight(T->Left)-GetHeight(T->Right) == 2 ) if ( X < T->Left->Data ) T = SingleLeftRotation(T); /* 左单旋 */ else T = DoubleLeftRightRotation(T); /* 左-右双旋 */ } /* else if (插入左子树) 结束 */ else if ( X > T->Data ) { /* 插入T的右子树 */ T->Right = Insert( T->Right, X ); /* 如果需要右旋 */ if ( GetHeight(T->Left)-GetHeight(T->Right) == -2 ) if ( X > T->Right->Data ) T = SingleRightRotation(T); /* 右单旋 */ else T = DoubleRightLeftRotation(T); /* 右-左双旋 */ } /* else if (插入右子树) 结束 */ /* else X == T->Data,无须插入 */ /* 别忘了更新树高 */ T->Height = Max( GetHeight(T->Left), GetHeight(T->Right) ) + 1; return T; }
void CObAvlTree::DoubleRightRotation( CNode* pNode ) { SingleLeftRotation(pNode->pLChild); SingleRightRotation(pNode); }
void CObAvlTree::RemoveAt(POSITION position) { //avl tree removing. //For a node having children, the concept model is to find the inorder successor of the removing node, //copy the data of IOS to the removing node, then remove the IOS rather than the removing node. //the rotation balance begins from the parent of the IOS and traces back to its ancestors. //however, the implementation removes the true removing node so that the iterator won't point to a garbage node. ASSERT_VALID(this); CNode* pOldNode = (CNode*) position; ASSERT(AfxIsValidAddress(pOldNode, sizeof(CNode))); //block 1. regular binary tree remove, except makeing pRotateNode point to the start tracing node for rotation, //and the bubble node's height is replaced the height of the removed node //case 1. single child, just bubble the child the the parent place //case 2. double children, bubble the in order successor to the parent place. CNode* pBubbleNode = NULL; CNode* pRotateNode = NULL; if( pOldNode->pLChild==NULL ){ pBubbleNode = pOldNode->pRChild; pRotateNode = pOldNode->pParent; }else if( pOldNode->pRChild==NULL ){ pBubbleNode = pOldNode->pLChild; pRotateNode = pOldNode->pParent; }else{ //case 2 pBubbleNode = pOldNode->pRChild; while( pBubbleNode->pLChild )pBubbleNode = pBubbleNode->pLChild; //now pBubbleNode is the IOS, but if bubble node is the right child of the removing node, //do not change the right child of the bubble node if( pBubbleNode->pParent!=pOldNode ){ //the bubble node is more than one height below the removing node pBubbleNode->pParent->pLChild = pBubbleNode->pRChild; if( pBubbleNode->pRChild )pBubbleNode->pRChild->pParent=pBubbleNode->pParent; //save the rotation place. pRotateNode = pBubbleNode->pParent; //link the right child of the removing node to bubble node pBubbleNode->pRChild = pOldNode->pRChild; pOldNode->pRChild->pParent = pBubbleNode; }else{ pRotateNode = pBubbleNode; } //link the left child of the removing node to the bubble node pBubbleNode->pLChild = pOldNode->pLChild; pOldNode->pLChild->pParent = pBubbleNode; //replace the height of the bubble node by the removed node ASSERT(AfxIsValidAddress(pBubbleNode, sizeof(CNode))); pBubbleNode->nHeight = pOldNode->nHeight; } CNode** ppNode=NULL; if( pOldNode==m_pNodeRoot )ppNode = &m_pNodeRoot; else if( pOldNode->pParent->pLChild==pOldNode )ppNode=&pOldNode->pParent->pLChild; else ppNode=&pOldNode->pParent->pRChild; *ppNode = pBubbleNode; if( pBubbleNode )pBubbleNode->pParent = pOldNode->pParent; FreeNode(pOldNode); //block 2, avl tree balance rotation //the loop goes upward to find the rotation node until the root node is reached or the current subtree's height is not changed. //if a rotation is done, LOOP CONTINUE beause the height of the subtree at the rotation node may decrease, //so the ancestors may need rotation. //if the rotation is not done for the node, then adjust the height of the current node. while( pRotateNode ){ int nOldHeight = NODEHEIGHT(pRotateNode); if( NODEHEIGHT(pRotateNode->pLChild)-NODEHEIGHT(pRotateNode->pRChild)==2 ){ //left subtree is too high, rotate to right CNode* pChildNode = pRotateNode->pLChild; ASSERT( pChildNode!=NULL ); if( NODEHEIGHT(pChildNode->pLChild)>=NODEHEIGHT(pChildNode->pRChild) ){ SingleRightRotation( pRotateNode ); }else{ ASSERT( NODEHEIGHT(pChildNode->pLChild)<NODEHEIGHT(pChildNode->pRChild) ); DoubleRightRotation( pRotateNode ); } //after the rotation, the pRotateNode becomes a child of the node at the rotation point pRotateNode = pRotateNode->pParent; }else if( NODEHEIGHT(pRotateNode->pRChild)-NODEHEIGHT(pRotateNode->pLChild)==2 ){ //right subtree is too high, rotate to left CNode* pChildNode = pRotateNode->pRChild; ASSERT( pChildNode!=NULL ); if( NODEHEIGHT(pChildNode->pLChild)<=NODEHEIGHT(pChildNode->pRChild) ){ SingleLeftRotation( pRotateNode ); }else{ ASSERT( NODEHEIGHT(pChildNode->pLChild)>NODEHEIGHT(pChildNode->pRChild) ); DoubleLeftRotation( pRotateNode ); } //after the rotation, the pRotateNode becomes a child of the node at the rotation point pRotateNode = pRotateNode->pParent; }else{ //no rotation happend here, adjust the height CalcHeight( pRotateNode ); } if( nOldHeight==NODEHEIGHT(pRotateNode) ){ //since the subtree's height is not changed, STOP LOOP since the ancestors' height is maintained. break; } pRotateNode = pRotateNode->pParent; } }
POSITION CObAvlTree::Insert(CObject* newElement) { ASSERT_VALID(this); //block 1, regular binary insertion CNode* pParent = m_pNodeRoot; CNode** ppNode = &m_pNodeRoot; while( *ppNode ){ pParent = *ppNode; int nRet = CompareNode( (LPVOID)&newElement, (LPVOID)&pParent->data ); if( nRet<=0 ){ ppNode = &pParent->pLChild; }else if( nRet>0 ){ ppNode = &pParent->pRChild; } } CNode* pNewNode = NewNode(pParent, NULL, NULL); pNewNode->data = newElement; *ppNode = pNewNode; //block 2, avl tree balance rotation //the loop goes upward to find the rotation node, //whenever a rotation is done, STOP LOOP beause the ancestors' height are the same after rotation. //if the rotation is not yet found, then adjust the height of the current node. CNode* pRotateNode = pParent; while( pRotateNode ){ if( NODEHEIGHT(pRotateNode->pLChild)-NODEHEIGHT(pRotateNode->pRChild)==2 ){ //left subtree is too high, rotate to right CNode* pChildNode = pRotateNode->pLChild; ASSERT( pChildNode!=NULL ); if( NODEHEIGHT(pChildNode->pLChild)>NODEHEIGHT(pChildNode->pRChild) ){ SingleRightRotation( pRotateNode ); }else{ ASSERT( NODEHEIGHT(pChildNode->pLChild)<NODEHEIGHT(pChildNode->pRChild) ); DoubleRightRotation( pRotateNode ); } break; }else if( NODEHEIGHT(pRotateNode->pRChild)-NODEHEIGHT(pRotateNode->pLChild)==2 ){ //right subtree is too high, rotate to left CNode* pChildNode = pRotateNode->pRChild; ASSERT( pChildNode!=NULL ); if( NODEHEIGHT(pChildNode->pLChild)<NODEHEIGHT(pChildNode->pRChild) ){ SingleLeftRotation( pRotateNode ); }else{ ASSERT( NODEHEIGHT(pChildNode->pLChild)>NODEHEIGHT(pChildNode->pRChild) ); DoubleLeftRotation( pRotateNode ); } break; } //no rotation happend here, adjust the height CalcHeight( pRotateNode ); pRotateNode = pRotateNode->pParent; } /* CNode* pRotateNode = pParent; CNode* pChildNode = pNewNode; CNode* pGrandChdNode = pNewNode; while( pRotateNode ){ if( pRotateNode->pLChild==pChildNode ){ //inserted in the left subtree. if( NODEHEIGHT(pRotateNode->pLChild)-NODEHEIGHT(pRotateNode->pRChild)==2 ){ ASSERT( pChildNode!=pGrandChdNode ); if( pChildNode->pLChild==pGrandChdNode ){ SingleRightRotation( pRotateNode ); }else{ DoubleRightRotation( pRotateNode ); } break; } }else{ //inserted in the right subtree if( NODEHEIGHT(pRotateNode->pRChild)-NODEHEIGHT(pRotateNode->pLChild)==2 ){ ASSERT( pChildNode!=pGrandChdNode ); if( pChildNode->pRChild==pGrandChdNode ){ SingleRightRotation( pRotNode ); }else{ DoubleRightRotation( pRotNode ); } break; } } //no rotation happend here, adjust the height CalcuHeight( pRotateNode ); //change the family pGrandChdNode = pChildNode; pChildNode = pRotateNode; pRotateNode = pRotateNode->pParent; }*/ /* CNode* pRotateNode = pParent; CNode* pNode = pNewNode; while( pRotateNode ){ CalcuHeight( pRotateNode ); if( pRotateNode->pLChild==pNode ){ //inserted in the left subtree. if( NODEHEIGHT(pRotateNode->pLChild)-NODEHEIGHT(pRotateNode->pRChild)==2 ){ int nRet = CompareNode( (LPVOID)&newElement, (LPVOID)&pNode->data ); if( nRet<=0 ){ SingleRightRotation( pRotNode ); }else{ DoubleRightRotation( pRotNode ); } break; } }else{ //inserted in the right subtree if( NODEHEIGHT(pRotateNode->pRChild)-NODEHEIGHT(pRotateNode->pLChild)==2 ){ int nRet = CompareNode( (LPVOID)&newElement, (LPVOID)&pNode->data ); if( nRet<=0 ){ SingleRightRotation( pRotNode ); }else{ DoubleRightRotation( pRotNode ); } break; } } //no rotation happend here, adjust the height CalcuHeight( pRotateNode ); pNode = pRotateNode; pRotateNode = pRotateNode->pParent; }*/ return (POSITION) pNewNode; }
/******************************************************************************* Função que faz a rotação dupla à direita a partir do nó pretendido da AVL. Function that makes the left-right double rotation. *******************************************************************************/ static void DoubleLeftRightRotation (PtAVLNode *pnode) { SingleLeftRotation (&(*pnode)->PtLeft); SingleRightRotation (pnode); }
avltree DoubleRightLeftRotation(avltree A){ A->right=SingleLeftRotation(A->right); return SingleRightRotation(A); }
/* 对称的右单旋与右-左双旋请自己实现 */ AVLTree DoubleRightLeftRotation(AVLTree A){ A->Right = SingleLeftRotation(A->Right); return SingleRightRotation(A); }