首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

平衡二叉樹(AVL)C 語言完整實現:插入、刪除、旋轉與高度維護

     編輯:關於C語言

平衡二叉樹(AVL)C 語言完整實現:插入、刪除、旋轉與高度維護

AVL 樹通過旋轉操作維持左右子樹高度差 ≤ 1,保證查找 O(log n)。本文從旋轉原理、節點結構、輔助函數、插入刪除邏輯逐步構建完整可運行代碼,附頭文件與源文件。

四種旋轉操作

節點結構含 data、height、左右孩子指針。空節點高度定義為 -1,葉子高度 0。

LL 單右旋(左左)

BTNode* singleRotateLL(BTree* BT, BTNode* phead) {
    BTNode* temp = phead->lchild;
    if(temp->rchild) {
        phead->lchild = temp->rchild;
        phead->lchild->height = node_height(BT, phead->lchild);
    } else phead->lchild = NULL;
    temp->rchild = phead;
    if(temp->rchild->data == BT->phead->data) BT->phead = temp;
    phead = temp;
    // 更新高度:先子後父
    phead->rchild->height = node_height(BT, phead->rchild);
    phead->height = node_height(BT, phead);
    return phead;
}

RR 單左旋(右右)

鏡像對稱,處理 temp->lchild。

LR 雙旋(左右)

BTNode* doubleRotateLR(BTree* BT, BTNode* phead) {
    BTNode* temp = phead->lchild;
    phead->lchild = singleRotateRR(BT, temp); // 先對左孩子 RR
    temp = phead;
    phead = singleRotateLL(BT, temp);        // 再對當前節點 LL
    return phead;
}

RL 雙旋(右左)

鏡像:先對右孩子 LL,再對當前節點 RR。

輔助函數

int node_height(BTree* BT, BTNode* n) {
    if(!n) return -1;
    if(!n->lchild && !n->rchild) return 0;
    return max(node_height(BT, n->lchild), node_height(BT, n->rchild)) + 1;
}
void tree_height(BTree* BT, BTNode* n) { // 遍歷更新全樹高度
    if(!n) return;
    node_height(BT, n);
    if(n->lchild) tree_height(BT, n->lchild);
    if(n->rchild) tree_height(BT, n->rchild);
}
int max(int a, int b) { return a > b ? a : b; }

插入邏輯:遞歸插入 + 回溯平衡

BOOL tree_add(BTree* BT, BTNode* phead, TYPE value) {
    if(!phead || phead->data == value) return 0;
    if(value < phead->data) {
        if(!phead->lchild) { /* 創建節點 */ }
        else {
            tree_add(BT, phead->lchild, value);
            // 回溯檢查平衡
            BTNode* root = (phead == BT->phead) ? phead : phead->lchild;
            if(node_height(BT, root->lchild) - node_height(BT, root->rchild) == 2) {
                if(root->lchild->data > value) root = singleRotateLL(BT, root);
                else root = doubleRotateLR(BT, root);
            }
            phead = root; // 關鍵:更新父節點的孩子指針
        }
    } else { /* 右子樹對稱 */ }
    phead->height = node_height(BT, phead);
    return 1;
}

關鍵點:無父指針,需通過返回值或雙重指針更新父節點的孩子指針;根節點特殊處理。

刪除邏輯:三種情況 + 回溯平衡

  1. 被刪節點有左子樹:用左子樹**最大值**替代
  2. 有右子樹:用右子樹**最小值**替代
  3. 葉子節點:直接刪除

刪除後調用 tree_height 重新計算全樹高度(簡化做法),再按 flag(根/左/右)檢查平衡並旋轉。

完整代碼結構

binary.h:類型定義、結構體、函數指針接口聲明
binary.c:所有函數實現、main 測試用例
測試:插入 9,4,5,6,1,7,8,11,10 → 先序/中序/後序遍歷 → 刪除 4,1,6 → 修改 9→2 → 再次遍歷驗證。

總結與避坑指南

  • 高度定義統一:空=-1,葉=0
  • 旋轉後**必須**按「子→父」順序更新高度
  • 插入/刪除回溯時,正確識別不平衡節點(root 變量)
  • 根節點旋轉後更新 BT->phead
  • 刪除後全樹重算高度雖簡單但 O(n),優化可沿路徑向上更新
  • 雙旋分解為兩次單旋,順序不可反

AVL 實現雖繁瑣,但徹底理解旋轉本質與高度維護,是掌握平衡樹的必經之路。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved