0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

使用C語言代碼實(shí)現(xiàn)平衡二叉樹

我快閉嘴 ? 來源:博客園 ? 作者:博客園 ? 2022-09-21 11:00 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1. 什么是平衡二叉樹

平衡二叉樹,我們也稱【二叉平衡搜索樹/AVL】,樹中任何節(jié)點(diǎn)的兩個(gè)子樹的高度最大差別為1,巴拉巴拉。。。(https://baike.baidu.com/item/AVL樹/10986648?fr=aladdin)

但是有個(gè)注意的點(diǎn): 平衡二叉樹的前提是 二叉排序樹(https://baike.baidu.com/item/二叉搜索樹/7077855?fr=aladdin)

這篇博客主要總結(jié)平衡二叉樹,所以,二叉排序樹知識(shí)不會(huì)提及,但是會(huì)用到。

如果想要看 排序二叉樹調(diào)整為 平衡二叉樹 旋轉(zhuǎn)相關(guān)內(nèi)容的,調(diào)整至 第5節(jié)。

平衡二叉樹

ba84432a-3958-11ed-9e49-dac502259ad0.png

非平衡二叉樹

最小不平衡子樹節(jié)點(diǎn)為 130

左子樹深度為 1,右子樹深度為3 ,其差值大于1,所以不平衡

ba94cf10-3958-11ed-9e49-dac502259ad0.png

2. 如何判斷二叉樹最小不平衡子樹

最小不平衡子樹為 130 這顆子樹(黃色標(biāo)注)

baa4faa2-3958-11ed-9e49-dac502259ad0.png

判定最小不平衡子樹的關(guān)鍵就在于,判斷這棵樹的左子樹 和 右字?jǐn)?shù) 深度之差是否大于1,若大于1 ,則證明該樹不平衡

檢查二叉樹是否平衡函數(shù)代碼實(shí)現(xiàn)

typedef struct {
        int data; // 數(shù)據(jù)節(jié)點(diǎn)
        struct TreeNode *left; // 指向左子樹
        struct TreeNode *right; // 指向右子樹
} TreeNode , *PTreeNode;

// 記錄平衡二叉樹
bool BalanceTrue = false;
// 最小不平衡子樹地址
TreeNode *rjt = NULL;

// 檢查二叉樹是否平衡,若不平衡 BalanceTrue 為 true
int checkTreeBalance(TreeNode *root) {
        if (NULL == root) { return 0; }
        int x = checkTreeBalance(root->left);
        int y = checkTreeBalance(root->right);

        // 若檢測(cè)到最小不平衡二叉樹后,不進(jìn)行后面的檢查
        if (BalanceTrue) return 0;
    
        int xx = abs(x-y);

        if (xx > 1) {
                // 左子樹 和 右子樹 相差大于1 , 二叉樹不平衡
                BalanceTrue = true;
                rjt = root;
        }
         
        return (x>y?x+1:y+1);
}

程序執(zhí)行結(jié)果

# gcc -w -g -std=c11 BalanceTree.c 
# 
# ./a.out 
當(dāng)前二叉樹遍歷
前序遍歷: 580    130     80      160     150     158     210     1590    900     2100    1900
中序遍歷: 80     130     150     158     160     210     580     900     1590    1900    2100
二叉樹不平衡,不平衡子樹根節(jié)點(diǎn)為: 130
# 

3. 二叉樹不平衡情況

在一顆平衡二叉樹的前提下,插入和刪除一個(gè)節(jié)點(diǎn),都有可能會(huì)引起二叉樹不平衡,不平衡的情況主要有以下四種

左左更高

baef3f54-3958-11ed-9e49-dac502259ad0.png

左右更高

bb353f22-3958-11ed-9e49-dac502259ad0.png

右左更高

bb677960-3958-11ed-9e49-dac502259ad0.png

右右更高

bbb2f520-3958-11ed-9e49-dac502259ad0.png

4. 判斷不平衡二叉樹哪邊高

bbe90b6a-3958-11ed-9e49-dac502259ad0.png

bc229c54-3958-11ed-9e49-dac502259ad0.png

如上圖紅色所示,可以先根據(jù)最小不平衡二叉樹左子樹或者右子樹高,上圖所示,為右子樹高,則將最小不平衡二叉樹的右子樹作為樹根節(jié)點(diǎn),繼續(xù)判斷子樹的左子樹或者右子樹高。
比如上圖的結(jié)果是右左較高,若進(jìn)行調(diào)整的話,為先讓不平衡子樹右節(jié)點(diǎn)的樹先向右旋轉(zhuǎn),然后再向左旋轉(zhuǎn)。

判斷不平衡二叉樹哪邊高代碼實(shí)現(xiàn)

typedef struct {
        int data; // 數(shù)據(jù)節(jié)點(diǎn)
        struct TreeNode *left; // 指向左子樹
        struct TreeNode *right; // 指向右子樹
} TreeNode , *PTreeNode;

// 記錄平衡二叉樹
bool BalanceTrue = false;
// 最小不平衡子樹地址
TreeNode *rjt = NULL;

// 返回二叉樹樹高
int treeHeight(TreeNode *root) {
        if (NULL == root) return 0;
        int ll = treeHeight(root->left);
        int rr = treeHeight(root->right);
        return (ll>rr?ll+1:rr+1);
}

int main() {
    /*  構(gòu)建二叉樹
    判斷平衡,獲取最小不平衡子樹, 將數(shù)據(jù)存入 rjt 中
    輸出二叉樹 前序/中序
    */
    if (BalanceTrue) {
        printf("二叉樹不平衡,不平衡子樹根節(jié)點(diǎn)為: %d
",rjt->data);
    } else {
        return 0;
    };


    int ll = treeHeight(rjt->left);
    int rr = treeHeight(rjt->right);
    if (1 < ll - rr) {
        printf("左子樹高
");
        TreeNode *rjt_ll = rjt->left;

        int child_ll = treeHeight(rjt_ll->left);
        int child_rr = treeHeight(rjt_ll->right);
        if (child_ll > child_rr) {
            printf("左子樹更高
");
        } else if (child_rr > child_ll) {
            printf("右字?jǐn)?shù)更高");
        }

    } else if (1 <  rr - ll) {
        printf("右子數(shù)高
");
        TreeNode *rjt_rr = rjt->right;

        int child_ll = treeHeight(rjt_rr->left);
        int child_rr = treeHeight(rjt_rr->right);
        if (child_ll > child_rr) {
            printf("左子樹更高
");
        } else if (child_rr > child_ll) {
            printf("右字?jǐn)?shù)更高");
        }

    }

    return 0;
}

輸出

# gcc BalanceTree.c -w -g -std=c11
# 
# ./a.out 
當(dāng)前二叉樹遍歷
前序遍歷:130    80      160     150     158     210
中序遍歷:80     130     150     158     160     210
二叉樹不平衡,不平衡子樹根節(jié)點(diǎn)為: 130
右子數(shù)高
左子樹更高
# 

5. 如何調(diào)整平衡二叉樹

所謂的旋轉(zhuǎn),其實(shí)是修改指針指向的值,僅此而已。

二叉樹不平衡有四種情況

左左更高

原始二叉樹,若要調(diào)整為平衡二叉樹,需要整棵樹向右旋轉(zhuǎn)

bc3dbdcc-3958-11ed-9e49-dac502259ad0.png

調(diào)整1:整棵樹向右旋轉(zhuǎn)

bc671424-3958-11ed-9e49-dac502259ad0.png

左右更高

原始二叉樹,若要調(diào)整為平衡二叉樹,需要先讓不平衡子樹左節(jié)點(diǎn)先向左旋轉(zhuǎn),然后再向右旋轉(zhuǎn)

bc77a866-3958-11ed-9e49-dac502259ad0.png

調(diào)整1: 先讓不平衡子樹左節(jié)點(diǎn)的樹先向左旋轉(zhuǎn)

bcb42688-3958-11ed-9e49-dac502259ad0.png

調(diào)整2:整棵樹向右

bd051188-3958-11ed-9e49-dac502259ad0.png

右左更高

原始二叉樹,若要調(diào)整為平衡二叉樹,需要先讓不平衡子樹右節(jié)點(diǎn)的樹先向右旋轉(zhuǎn),然后再向左旋轉(zhuǎn)

bd4f87b8-3958-11ed-9e49-dac502259ad0.png

調(diào)整1: 先讓不平衡子樹右節(jié)點(diǎn)的樹先向右旋轉(zhuǎn)

bd6bbd2a-3958-11ed-9e49-dac502259ad0.png

調(diào)整2:整棵樹向左

bd992e54-3958-11ed-9e49-dac502259ad0.png

右右更高

原始二叉樹,若要調(diào)整為平衡二叉樹,需要整棵樹向左旋轉(zhuǎn)

bdd9f4d4-3958-11ed-9e49-dac502259ad0.png

調(diào)整1:整棵樹向左旋轉(zhuǎn)

be214bb8-3958-11ed-9e49-dac502259ad0.png

全部代碼

# include 
# include 
# include 
# include 

typedef struct {
int data; // 數(shù)據(jù)節(jié)點(diǎn)
struct TreeNode *left; // 指向左子樹
struct TreeNode *right; // 指向右子樹
} TreeNode , *PTreeNode;

// 記錄平衡二叉樹
bool BalanceTrue = false;
// 最小不平衡子樹地址
TreeNode *rjt = NULL;

// 檢查二叉樹是否平衡,若不平衡 BalanceTrue 為 true
int checkTreeBalance(TreeNode *root) {
if (NULL == root) { return 0; }
int x = checkTreeBalance(root->left);
int y = checkTreeBalance(root->right);

// 若檢測(cè)到最小二叉樹后,不進(jìn)行后面的檢查
if (BalanceTrue) return 0;
int xx = abs(x-y);

if (xx > 1) {
// 左子樹 和 右子樹 相差大于1 , 二叉樹不平衡
BalanceTrue = true;
rjt = root;
}
 
return (x>y?x+1:y+1);
}

// 返回二叉樹樹高
int treeHeight(TreeNode *root) {
if (NULL == root) return 0;
int ll = treeHeight(root->left);
int rr = treeHeight(root->right);
return (ll>rr?ll+1:rr+1);
}

// 父節(jié)點(diǎn)查詢
TreeNode* queryTopData(TreeNode *root,int data) {
// 空地址異常拋出
if (NULL == root) return NULL;

// top: 父節(jié)點(diǎn) ,如果為Null, 該節(jié)點(diǎn)為父節(jié)點(diǎn)
// tmp: 遍歷查詢節(jié)點(diǎn) 
TreeNode *top = NULL;
TreeNode *tmp = root;

while (tmp != NULL) {
if (data == tmp->data) {
// 節(jié)點(diǎn)為 返回Null
if (NULL == top) return NULL;
return top;
}

top = tmp;
if (data > tmp->data) {
tmp = tmp->right;
} else if (data < tmp->data) {
tmp = tmp->left;
}
}
return NULL;
}

// 左左旋轉(zhuǎn)
//
// 不平衡二叉樹
//       70
//      /   
//    50    80
//   /      
//  40  60
//  /
// 30
//
// 旋轉(zhuǎn)后平衡二叉樹(向右旋轉(zhuǎn))
//
//    50
//  /   
// 40    70
// /     /  
//30   60    80
//
bool turnLL(TreeNode **root , TreeNode *notBalanceRoot) {

if ((*root) != notBalanceRoot) {
printf("左左旋轉(zhuǎn),非根節(jié)點(diǎn)
");
// 非根節(jié)點(diǎn)
TreeNode *lleft = notBalanceRoot->left;
TreeNode *lright = lleft->right;

// 查找父節(jié)點(diǎn)
TreeNode *fdata = queryTopData((*root),notBalanceRoot->data);
if (NULL == fdata) return false;

lleft->right = notBalanceRoot;
notBalanceRoot->left = lright;

if (notBalanceRoot == fdata->left) {
fdata->left = lleft;
} else if (notBalanceRoot == fdata->right) {
fdata->right = lleft;
}
return true;

} else {
// 根節(jié)點(diǎn)
printf("左左旋轉(zhuǎn),是根節(jié)點(diǎn)
");
TreeNode *lleft = notBalanceRoot->left;
TreeNode *absroot = lleft;
TreeNode *lright = lleft->right;


lleft->right = notBalanceRoot;
notBalanceRoot->left = lright;

(*root) = absroot;
return true;
}

}

// 左右旋轉(zhuǎn)
//不平衡二叉樹
//      70
//     /   
//    50    80
//    /     
//   40 60
//  /   
// 55
//
//左子樹向左
//      70
//     /   
//    60    80
//    /
//   50
//  /      
// 40  55
//                                                           
//                                                                   
// 整棵樹向右
// 
//     60
//    /   
//   50    70
//  /       
// 40  55    80
//
bool turnLR(TreeNode **root , TreeNode *notBalanceRoot) {
if ((*root) != notBalanceRoot) {
printf("左右旋轉(zhuǎn),非根節(jié)點(diǎn)");

TreeNode *lleft = notBalanceRoot->left;
TreeNode *leftRight = lleft->right;
TreeNode *leftRightLeft = leftRight->left;

// 第一次調(diào)整
leftRight->left = lleft;
lleft->right = leftRightLeft;
notBalanceRoot->left = leftRight;


// 查找父節(jié)點(diǎn)
TreeNode *fdata = queryTopData((*root),notBalanceRoot->data);
//if (NULL != fdata) printf("fdata: %d
",fdata->data);

// 第二次調(diào)整
lleft = notBalanceRoot->left;
leftRight = lleft->right;

lleft->right = notBalanceRoot;
notBalanceRoot->left = leftRight;


if (notBalanceRoot == fdata->left) {
fdata->left = lleft;
} else if (notBalanceRoot == fdata->right) {
fdata->right = lleft;
}
} else {
printf("左右旋轉(zhuǎn),是根節(jié)點(diǎn)
");

TreeNode *lleft = notBalanceRoot->left;
TreeNode *leftRight = lleft->right;
TreeNode *leftRightLeft = leftRight->left;

// 第一次調(diào)整
leftRight->left = lleft;
lleft->right = leftRightLeft;
notBalanceRoot->left = leftRight;

// 第二次調(diào)整
lleft = notBalanceRoot->left;
leftRight = lleft->right;

lleft->right = notBalanceRoot;
notBalanceRoot->left = leftRight;

(*root) = lleft;
}
}

// 右左旋轉(zhuǎn)
//不平衡二叉樹
//   70
//  /  
// 50   80
//     /  
//    75  88
//     
//     77
//
//左子樹向右
//   70
//  /  
// 50   75
//     /  
//    77  80
//         
//         88
//                                                                                                           
//                                                                                                                  
//                                                                                                                      
//整棵樹向左
//     75
//    /  
//   70  80
//  /      
// 50  77  88 
//
bool turnRL(TreeNode **root , TreeNode *notBalanceRoot) {
TreeNode *rright = notBalanceRoot->right;
TreeNode *rightLeft = rright->left;
TreeNode *rightLeftRight = rightLeft->right;

// 第一次調(diào)整
rightLeft->right = rright;
rright->left = rightLeftRight;
notBalanceRoot->right = rightLeft;

// 查找父節(jié)點(diǎn)
TreeNode *fdata = queryTopData((*root),notBalanceRoot->data);
//if (NULL != fdata) printf("fdata: %d
",fdata->data);

// 第二次調(diào)整
rright = notBalanceRoot->right;
rightLeft = rright->left;

rright->left = notBalanceRoot;
notBalanceRoot->right = rightLeft;

if ((*root) != notBalanceRoot) {
printf("右左旋轉(zhuǎn),非根節(jié)點(diǎn)
");
if (notBalanceRoot == fdata->left) {
fdata->left = rright;
} else if (notBalanceRoot == fdata->right) {
fdata->right = rright;
}

} else {
printf("右左旋轉(zhuǎn),是根節(jié)點(diǎn)
");
(*root) = rright;
}
}

// 右右旋轉(zhuǎn)
// 
// 不平衡二叉樹
//  70
// /  
//50   80
//    /  
//   75  88
//      /
//     85
//
//
//
//向左旋轉(zhuǎn)
//    80
//   /  
//  70   88
// /     /  
//50  75 85  
bool turnRR(TreeNode **root , TreeNode *notBalanceRoot) {
if ((*root) != notBalanceRoot) {
printf("右右旋轉(zhuǎn),非根節(jié)點(diǎn)");
TreeNode *rright = notBalanceRoot->right;
TreeNode *rleft = rright->left;

// 查找父節(jié)點(diǎn)
TreeNode *fdata = queryTopData((*root),notBalanceRoot->data);
if (NULL != fdata) printf("fdata: %d
",fdata->data);

                rright->left = notBalanceRoot;
                notBalanceRoot->right = rleft;

                if (notBalanceRoot == fdata->left) {
                        fdata->left = rright;
                } else if (notBalanceRoot == fdata->right) {
                        fdata->right = rright;
                }

} else {
// 右右旋轉(zhuǎn),是根節(jié)點(diǎn)
printf("右右旋轉(zhuǎn),是根節(jié)點(diǎn)
");
TreeNode *rright = notBalanceRoot->right;
TreeNode *absroot = rright;
TreeNode *rleft = rright->left;

rright->left = notBalanceRoot;
notBalanceRoot->right = rleft;

(*root) = absroot;

}
}

// 二叉樹前序遍歷
void Print1(TreeNode *root) {
if (NULL == root) return;
printf("%d	",root->data);
Print1(root->left);
Print1(root->right);
}

// 二叉樹中序遍歷
void Print2(TreeNode *root) {
if (NULL == root) return;
Print2(root->left);
printf("%d	",root->data);
Print2(root->right);
}

// 二叉樹后續(xù)遍歷
void Print3(TreeNode *root) {
if (NULL == root) return;
Print3(root->left);
Print3(root->right);
printf("%d	",root->data);
}

// 插入二叉樹節(jié)點(diǎn)
TreeNode* addNode(TreeNode *root,int data) {
if (NULL == root) {
// 頭節(jié)點(diǎn)插入
TreeNode *Node = (TreeNode *)malloc(sizeof(TreeNode));
if (NULL == Node) {
printf("新節(jié)點(diǎn)申請(qǐng)內(nèi)存失敗
");
return NULL;
}
Node->data = data;

return Node;
}

TreeNode *tmp = root;
TreeNode *top = NULL;

// 找到合適的最尾巴節(jié)點(diǎn)
while (NULL != tmp) {
top = tmp;
if (tmp->data == data) {
printf("已經(jīng)存在該節(jié)點(diǎn),節(jié)點(diǎn)地址: %p
",tmp);
return root;
}
if (tmp->data < data) {
tmp = tmp->right;
} else if (tmp->data > data) {
tmp = tmp->left;
}
}

TreeNode *Node = (TreeNode *)malloc(sizeof(TreeNode));
Node->data = data;
if (NULL == Node) {
printf("申請(qǐng)新節(jié)點(diǎn)內(nèi)存失敗
");
return root;
}

// 鏈接節(jié)點(diǎn)
if (data > top->data) {
top->right = Node;
} else if (data < top->data) {
top->left = Node;
}

return root;
}


// 刪除二叉排序樹節(jié)點(diǎn)
bool DeleteTreeNode(TreeNode **TreeRoot,int data) {
if (NULL == (*TreeRoot)) return false;

printf("刪除節(jié)點(diǎn): %d
",data);

TreeNode *tmp = (*TreeRoot);
TreeNode *top = NULL;

while (tmp != NULL) {
if (tmp->data == data) {
// 葉子節(jié)點(diǎn)
if ((NULL == tmp->left) && (NULL == tmp->right)) {
// 葉子節(jié)點(diǎn)
if (NULL == top) {
// 僅有根節(jié)點(diǎn)的葉子節(jié)點(diǎn)
free(tmp);
return true;
} else {
// 其他的葉子節(jié)點(diǎn)
TreeNode *lastNode = top;
if (tmp == lastNode->left) {
lastNode->left = NULL;
} else if (tmp == lastNode->right) {
lastNode->right = NULL;
}
free(tmp);
return true;
}
} else {
// 非葉子節(jié)點(diǎn)
// 算法為: 
// 默認(rèn)算法為: 1.  當(dāng)刪除該節(jié)點(diǎn)時(shí),獲取該樹右子樹最左子節(jié)點(diǎn)
//             2.  當(dāng)右子樹為空時(shí),此時(shí)應(yīng)該獲取左子樹最右端子節(jié)點(diǎn)

if (NULL != tmp->right) {
// 方案 1
TreeNode *tmp2 = tmp->right;
TreeNode *top2 = NULL;

// 找到最后一個(gè)節(jié)點(diǎn)
while (tmp2->left != NULL) {
top2 = tmp2;
tmp2 = tmp2->left;
}

// 刪除老的節(jié)點(diǎn)
tmp->data = tmp2->data;
// 只有右子樹節(jié)點(diǎn) 沒有左子樹節(jié)點(diǎn)
if (NULL == top2) {
tmp->right = NULL;

} else {
top2->left = NULL;
}
free(tmp2);
} else {
// 方案 2
TreeNode *tmp2 = tmp->left;
TreeNode *top2 = NULL;

// 找到最后一個(gè)節(jié)點(diǎn)
while (tmp2->right != NULL) {
tmp2 = tmp2->right;
}

// 刪除老的節(jié)點(diǎn)
tmp->data = tmp2->data;
if (NULL == top2) {
tmp->left = NULL;
} else {
top2->right = NULL;
}
free(tmp2);
}

}
} else {
top = tmp;
if (data > tmp->data) {
tmp = tmp->right;
} else {
tmp = tmp->left;
}
}
}
return false;
}

// 二叉樹平衡調(diào)整
bool treeBalance(TreeNode **root) {
checkTreeBalance((*root));
while (BalanceTrue) {
printf("二叉樹不平衡,最小不平衡子樹數(shù)據(jù)結(jié)點(diǎn): %d
",rjt->data);
TreeNode *tmp;

if (1 < treeHeight(rjt->left) - treeHeight(rjt->right)) {
// 對(duì)于不平衡二叉樹而言,左子樹比右子樹高
//
//printf("左
");
if (rjt->left != NULL) {
tmp = rjt->left;
int ll = treeHeight(tmp->left);
int rr = treeHeight(tmp->right);

if (ll > rr) {
// 對(duì)于不平衡子樹 左子樹 而言, 左子樹比右子樹高
// 左左旋轉(zhuǎn)

turnLL(root,rjt);

} else {
// 對(duì)于不平衡子樹 左子樹 而言, 右子樹比左子樹高
// 左右旋轉(zhuǎn)
//
turnLR(root ,rjt);
}
} 
} else if (1 < treeHeight(rjt->right) - treeHeight(rjt->left)) {
// 對(duì)于不平衡二叉樹而言,右子樹比左子樹高
//
//printf("右
");
if (rjt->right != NULL) {
tmp = rjt->right;
int ll = treeHeight(tmp->left);
int rr = treeHeight(tmp->right);

if (ll > rr) {
//右左旋轉(zhuǎn)
turnRL(root,rjt);
} else {
//右右旋轉(zhuǎn)
turnRR(root,rjt);
}
}
}

BalanceTrue = false;
checkTreeBalance((*root));
printf("二叉樹調(diào)整平衡后數(shù)據(jù)結(jié)點(diǎn):
");
printf("前序遍歷:");
Print1(*root);
printf("
");
printf("中序遍歷:");
Print2(*root);
printf("
");
printf("
");
}

}

int main() {
TreeNode *root = NULL;

printf("平衡二叉樹插入測(cè)試
");
int nums[] = {65,60,70,55,40,63,69,66,68,77};
int i;
for (i=0;i<sizeof(nums)/sizeof(int);i++) {
printf("插入數(shù)據(jù): %d
",nums[i]);

root = addNode(root,nums[i]);
if (NULL == root) {
printf("首節(jié)點(diǎn)申請(qǐng)失敗"); 
return -1;
}

treeBalance(&root);
sleep(1);

}
printf("
當(dāng)前二叉樹遍歷
");
printf("前序遍歷:");
Print1(root);
printf("
");
printf("中序遍歷:");
Print2(root);
printf("
");
//return 0;

printf("

平衡二叉樹刪除測(cè)試
");

for (i=2;i<5;i++) {
DeleteTreeNode(&root,nums[i]);

treeBalance(&root);
sleep(1);
}

printf("
當(dāng)前二叉樹遍歷
");
printf("前序遍歷:");
Print1(root);
printf("
");
printf("中序遍歷:");
Print2(root);
printf("
");

return 0;
}

程序執(zhí)行結(jié)果

# gcc BalanceTree.c -w -g -std=c11
# 
# ./a.out 
平衡二叉樹插入測(cè)試
插入數(shù)據(jù): 65
插入數(shù)據(jù): 60
插入數(shù)據(jù): 70
插入數(shù)據(jù): 55
插入數(shù)據(jù): 40
二叉樹不平衡,最小不平衡子樹數(shù)據(jù)結(jié)點(diǎn): 60
左左旋轉(zhuǎn),非根節(jié)點(diǎn)
二叉樹調(diào)整平衡后數(shù)據(jù)結(jié)點(diǎn):
前序遍歷:65     55      40      60      70
中序遍歷:40     55      60      65      70

插入數(shù)據(jù): 63
二叉樹不平衡,最小不平衡子樹數(shù)據(jù)結(jié)點(diǎn): 65
左右旋轉(zhuǎn),是根節(jié)點(diǎn)
二叉樹調(diào)整平衡后數(shù)據(jù)結(jié)點(diǎn):
前序遍歷:60     55      40      65      63      70
中序遍歷:40     55      60      63      65      70

插入數(shù)據(jù): 69
插入數(shù)據(jù): 66
二叉樹不平衡,最小不平衡子樹數(shù)據(jù)結(jié)點(diǎn): 70
左左旋轉(zhuǎn),非根節(jié)點(diǎn)
二叉樹調(diào)整平衡后數(shù)據(jù)結(jié)點(diǎn):
前序遍歷:60     55      40      65      63      69      66      70
中序遍歷:40     55      60      63      65      66      69      70

插入數(shù)據(jù): 68
二叉樹不平衡,最小不平衡子樹數(shù)據(jù)結(jié)點(diǎn): 65
右左旋轉(zhuǎn),非根節(jié)點(diǎn)
二叉樹調(diào)整平衡后數(shù)據(jù)結(jié)點(diǎn):
前序遍歷:60     55      40      66      65      63      69      68      70
中序遍歷:40     55      60      63      65      66      68      69      70

插入數(shù)據(jù): 77
二叉樹不平衡,最小不平衡子樹數(shù)據(jù)結(jié)點(diǎn): 60
右右旋轉(zhuǎn),是根節(jié)點(diǎn)
二叉樹調(diào)整平衡后數(shù)據(jù)結(jié)點(diǎn):
前序遍歷:66     60      55      40      65      63      69      68      70      77
中序遍歷:40     55      60      63      65      66      68      69      70      77


當(dāng)前二叉樹遍歷
前序遍歷:66     60      55      40      65      63      69      68      70      77
中序遍歷:40     55      60      63      65      66      68      69      70      77


平衡二叉樹刪除測(cè)試
刪除節(jié)點(diǎn): 70
刪除節(jié)點(diǎn): 55
刪除節(jié)點(diǎn): 40
二叉樹不平衡,最小不平衡子樹數(shù)據(jù)結(jié)點(diǎn): 60
右左旋轉(zhuǎn),非根節(jié)點(diǎn)
二叉樹調(diào)整平衡后數(shù)據(jù)結(jié)點(diǎn):
前序遍歷:66     63      60      65      69      68      77
中序遍歷:60     63      65      66      68      69      77


當(dāng)前二叉樹遍歷
前序遍歷:66     63      60      65      69      68      77
中序遍歷:60     63      65      66      68      69      77
# 

審核編輯:湯梓紅


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7631

    瀏覽量

    141145
  • 二叉樹
    +關(guān)注

    關(guān)注

    0

    文章

    74

    瀏覽量

    12604

原文標(biāo)題:平衡二叉樹 C語言代碼實(shí)現(xiàn)

文章出處:【微信號(hào):技術(shù)讓夢(mèng)想更偉大,微信公眾號(hào):技術(shù)讓夢(mèng)想更偉大】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 0人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    計(jì)算機(jī)級(jí)二叉樹的問題

    各位大神,本人馬上要考計(jì)算機(jī)級(jí)了,那個(gè)二叉樹老是弄不明白,比如一個(gè)題目,一棵二叉樹共有25個(gè)節(jié)點(diǎn),其中五個(gè)葉子節(jié)點(diǎn),則度為1的節(jié)點(diǎn)數(shù)為?
    發(fā)表于 09-04 09:45

    基于二叉樹的時(shí)序電路測(cè)試序列設(shè)計(jì)

    為了實(shí)現(xiàn)時(shí)序電路狀態(tài)驗(yàn)證和故障檢測(cè),需要事先設(shè)計(jì)一個(gè)輸入測(cè)試序列?;?b class='flag-5'>二叉樹節(jié)點(diǎn)和樹枝的特性,建立時(shí)序電路狀態(tài)二叉樹,按照電路二叉樹節(jié)點(diǎn)(狀態(tài))與樹枝(輸入)的層次邏輯
    發(fā)表于 07-12 13:57 ?0次下載
    基于<b class='flag-5'>二叉樹</b>的時(shí)序電路測(cè)試序列設(shè)計(jì)

    二叉樹層次遍歷算法的驗(yàn)證

    實(shí)現(xiàn)二叉樹的層次遍歷算法,并對(duì)用”A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))”創(chuàng)建的二叉樹進(jìn)行測(cè)試。
    發(fā)表于 11-28 01:05 ?2211次閱讀
    <b class='flag-5'>二叉樹</b>層次遍歷算法的驗(yàn)證

    二叉樹,一種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)類型

    然后我們?cè)俣x一棵深度也為 3 的二叉樹,該二叉樹的 n 個(gè)結(jié)點(diǎn)(n≤7),當(dāng)從 1 到 n 的每個(gè)結(jié)點(diǎn)都與上圖中的編號(hào)結(jié)點(diǎn)一一對(duì)應(yīng)時(shí),這二叉樹就稱為完全二叉樹。
    的頭像 發(fā)表于 04-13 10:48 ?4622次閱讀
    <b class='flag-5'>二叉樹</b>,一種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)類型

    詳解電源二叉樹到底是什么

    作為數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ),分很多種,像 AVL 、紅黑、二叉搜索....今天我想分享的是關(guān)于二叉樹
    的頭像 發(fā)表于 06-06 15:05 ?1.1w次閱讀
    詳解電源<b class='flag-5'>二叉樹</b>到底是什么

    C語言二叉樹代碼免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是C語言二叉樹代碼免費(fèi)下載。
    發(fā)表于 08-27 08:00 ?1次下載

    紅黑(Red Black Tree)是一種自平衡二叉搜索

    平衡(Balance):就是當(dāng)結(jié)點(diǎn)數(shù)量固定時(shí),左右子樹的高度越接近,這棵二叉樹平衡(高度越低)。而最理想的平衡就是完全二叉樹/滿
    的頭像 發(fā)表于 07-01 15:05 ?6177次閱讀
    紅黑<b class='flag-5'>樹</b>(Red Black Tree)是一種自<b class='flag-5'>平衡</b>的<b class='flag-5'>二叉</b>搜索<b class='flag-5'>樹</b>

    二叉樹操作的相關(guān)知識(shí)和代碼詳解

    是數(shù)據(jù)結(jié)構(gòu)中的重中之重,尤其以各類二叉樹為學(xué)習(xí)的難點(diǎn)。在面試環(huán)節(jié)中,二叉樹也是必考的模塊。本文主要講二叉樹操作的相關(guān)知識(shí),梳理面試常考的內(nèi)容。請(qǐng)大家跟隨小編一起來復(fù)習(xí)吧。 本篇針對(duì)面
    的頭像 發(fā)表于 12-12 11:04 ?2242次閱讀
    <b class='flag-5'>二叉樹</b>操作的相關(guān)知識(shí)和<b class='flag-5'>代碼</b>詳解

    二叉樹的前序遍歷非遞歸實(shí)現(xiàn)

    我們之前說了二叉樹基礎(chǔ)及二叉的幾種遍歷方式及練習(xí)題,今天我們來看一下二叉樹的前序遍歷非遞歸實(shí)現(xiàn)。 前序遍歷的順序是, 對(duì)于中的某節(jié)點(diǎn),先遍
    的頭像 發(fā)表于 05-28 13:59 ?2157次閱讀

    二叉排序樹AVL如何實(shí)現(xiàn)動(dòng)態(tài)平衡

    熟悉的二叉樹種類有二叉搜索(排序、查找)、二叉平衡、伸展
    的頭像 發(fā)表于 10-28 17:02 ?2076次閱讀
    <b class='flag-5'>二叉排序樹</b>AVL如何<b class='flag-5'>實(shí)現(xiàn)</b>動(dòng)態(tài)<b class='flag-5'>平衡</b>

    C語言數(shù)據(jù)結(jié)構(gòu):什么是二叉樹?

    完全二叉樹:完全二叉樹是效率很高的數(shù)據(jù)結(jié)構(gòu)。對(duì)于深度為K,有n個(gè)節(jié)點(diǎn)的二叉樹,當(dāng)且僅當(dāng)每一個(gè)節(jié)點(diǎn)都與深度為K的滿二叉樹中編號(hào)從1至n的節(jié)點(diǎn)一一對(duì)應(yīng)時(shí),稱為完全
    的頭像 發(fā)表于 04-21 16:20 ?3556次閱讀

    怎么就能構(gòu)造成二叉樹呢?

    一直跟著公眾號(hào)學(xué)算法的錄友 應(yīng)該知道,我在二叉樹:構(gòu)造二叉樹登場(chǎng)!,已經(jīng)講過,只有 中序與后序 和 中序和前序 可以確定一顆唯一的二叉樹。前序和后序是不能確定唯一的二叉樹的。
    的頭像 發(fā)表于 07-14 11:20 ?1845次閱讀

    二叉樹代碼實(shí)現(xiàn)

    二叉樹的主要操作有遍歷,例如有先序遍歷、中序遍歷、后序遍歷。在遍歷之前,就是創(chuàng)建一棵二叉樹,當(dāng)然,還需要有刪除二叉樹的算法。
    的頭像 發(fā)表于 01-18 10:41 ?1468次閱讀
    <b class='flag-5'>二叉樹</b>的<b class='flag-5'>代碼</b><b class='flag-5'>實(shí)現(xiàn)</b>

    C++構(gòu)建并復(fù)制二叉樹

    使用C++構(gòu)建一個(gè)二叉樹并復(fù)制、輸出。
    的頭像 發(fā)表于 01-10 15:17 ?1269次閱讀
    <b class='flag-5'>C</b>++構(gòu)建并復(fù)制<b class='flag-5'>二叉樹</b>

    C++自定義二叉樹并輸出二叉樹圖形

    使用C++構(gòu)建一個(gè)二叉樹并輸出。
    的頭像 發(fā)表于 01-10 16:29 ?2026次閱讀
    <b class='flag-5'>C</b>++自定義<b class='flag-5'>二叉樹</b>并輸出<b class='flag-5'>二叉樹</b>圖形

    電子發(fā)燒友

    中國(guó)電子工程師最喜歡的網(wǎng)站

    • 2931785位工程師會(huì)員交流學(xué)習(xí)
    • 獲取您個(gè)性化的科技前沿技術(shù)信息
    • 參加活動(dòng)獲取豐厚的禮品