c語(yǔ)言二叉樹(shù)非遞歸實(shí)現(xiàn)

有了遞歸實(shí)現(xiàn)為啥還要用非遞歸呢?你會(huì)不會(huì)有疑惑缭乘?如果有沐序,請(qǐng)接著看琉用。

函數(shù)的調(diào)用需要用到棧堕绩,一個(gè)應(yīng)用分配到的棧空間一般為1M大小邑时,在數(shù)據(jù)很大的情況會(huì)造成棧溢出奴紧,所以要少用遞歸。

不用遞歸實(shí)現(xiàn)的原理是模擬棧的運(yùn)行機(jī)制------先進(jìn)后出晶丘,如果這個(gè)不會(huì)的話黍氮,可以看我寫(xiě)的數(shù)組模擬棧(現(xiàn)在還沒(méi)寫(xiě))。

頭文件

#ifdef __cplusplus
extern "C" {
#endif

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//bool
#include <stdbool.h>
//字節(jié)封裝的模擬棧
#include "SeqStack.h"
/* 
*自定義結(jié)構(gòu)體必須包含BiNode結(jié)構(gòu)體,且位于結(jié)構(gòu)體最上方
*struct Person
*{

* struct BiNode data;

* int age;
  };
  *增加必須提供返回值int型的比較函數(shù),參數(shù)為(void* ,void*),函數(shù)內(nèi)強(qiáng)轉(zhuǎn)自己定義的結(jié)構(gòu)體
  *int init(void* d1, void* d2)
  *{

* struct Person* p1 = (struct Person*)d1;

* struct Person* p2 = (struct Person*)d2;

* int tmp = (p1->age) - (p2->age);

* return tmp;
  *}
  *遍歷需要提供遍歷函數(shù)浅浮,參數(shù)為void*沫浆,函數(shù)內(nèi)強(qiáng)轉(zhuǎn)自己定義的結(jié)構(gòu)體
  *void myprint(void* node)
  *{

* if (NULL == node)

* {

* return;

* }

* struct Person* p = (struct Person*)node;

* 

* myprint(p->data.lchild);
  *
  *printf("%c\n", p->age);
  *

* myprint(p->data.rchild);
  *}
  *
  */
  //定義結(jié)構(gòu)體
  struct BiNode {
  //父節(jié)點(diǎn)用于刪除
    struct BiNode* parent;
    struct BiNode* rchild;
    struct BiNode* lchild;
    //用于遍歷
    bool flag;
  };

  //初始化樹(shù),外部調(diào)用
  void* Init_BBTree();
  //插入根數(shù)據(jù)滚秩,外部調(diào)用
  void Insert_BBTree(void* tree,void *data,int(*compare)(void *,void *));
  //返回樹(shù)高度专执,內(nèi)部使用
  int getHight(struct BiNode* node);
  //左旋,內(nèi)部使用
  struct BiNode* LeftHand(struct BiNode* data);
  //右旋,內(nèi)部使用
  struct BiNode* RightHand(struct BiNode* data);
  //平衡樹(shù)節(jié)點(diǎn),內(nèi)部使用
  struct BiNode* AdjTree(struct BiNode* data);
  //遍歷二叉樹(shù)
  void foreachTree(void* tree, void(*myprint)(void*));
  //刪除節(jié)點(diǎn),外部使用
  void RemoveTree(void* tree, void* data,int(*compare)(void* ,void*));
  //銷毀郁油,外部使用
  void DestroyTree(void* tree);

  

#ifdef __cplusplus
}
#endif

初始化

void* Init_BBTree()
{//開(kāi)辟一個(gè)新空間
    struct ABLTree* tree = malloc(sizeof(struct ABLTree));
    //開(kāi)辟失敗返回NULL
    if (NULL == tree)
    {
        return NULL;
    }//初始化根節(jié)點(diǎn)為NULL
    tree->root = NULL;
    //返回空間指針
    return tree;
}

插入數(shù)據(jù)

void Insert_BBTree(void* tree, void* data, int(*compare)(void*, void*))
{//判斷參數(shù)是否為空
    if (NULL == tree)
    {
        return;
    }
    if (NULL == data)
    {
        return;
}
    if (NULL == compare)
    {
        return;
    }
    //強(qiáng)轉(zhuǎn)
    struct ABLTree* newtree = (struct ABLTree*)tree;
    //判斷根節(jié)點(diǎn)是否為空本股,若為空攀痊,把數(shù)據(jù)賦值給根節(jié)點(diǎn),并返回
    if (NULL == newtree->root)
    {
        newtree->root = data;
        return;
    }
    //不為空拄显,初始化一個(gè)棧
    void* stack = Init_SeqStack();
    //把根節(jié)點(diǎn)壓入棧中
    Push_SeqStack(stack, newtree->root);
    //判斷棧中是否還有數(shù)據(jù)
    while (Size_SeqStack(stack) > 0)
    {//獲取棧頂元素
        struct BiNode* info = (struct BiNode*)Top_SeqStack(stack);
        //彈出棧頂元素
        Pop_SeqStack(stack);
        //判斷棧頂元素與數(shù)據(jù)的大小
        if(compare(info,data)>0)
        {//如果棧頂元素大苟径,判斷棧頂元素的左子節(jié)點(diǎn)是否為空
            if (NULL == info->lchild)
            {//為空,賦值并返回
                info->lchild = data;
                info->lchild->parent = info;
                break;
            }
            //不為空躬审,把左子節(jié)點(diǎn)壓入棧中,并中斷當(dāng)前循環(huán)棘街,進(jìn)入下次循環(huán)
            Push_SeqStack(stack, info->lchild);
            continue;
        }
        else
        {//如果棧頂元素小,判斷棧頂元素的右子節(jié)點(diǎn)是否為空
            if (NULL == info->rchild)
            {//為空盒件,賦值并返回
                info->rchild = data;
                info->rchild->parent = info;
                break;
            }
                    //不為空蹬碧,把右子節(jié)點(diǎn)壓入棧中,并中斷當(dāng)前循環(huán),進(jìn)入下次循環(huán)
            Push_SeqStack(stack, info->rchild);
            continue;
        }

    }
    //銷毀棧
    Destroy_SeqStack(stack);
    //平衡樹(shù)節(jié)點(diǎn)
    newtree->root = AdjTree(newtree->root);
}

調(diào)節(jié)平衡

//獲取樹(shù)高度
int getHight(struct BiNode* node)
{
    if (NULL == node)
    {
        return 0;
    }
    int n = getHight(node->lchild);
    int m = getHight(node->rchild);
    return n > m ? ++n : ++m;
}

//左旋轉(zhuǎn)
struct BiNode* LeftHand(struct BiNode* data)
{
    struct BiNode* temp = data;
     
    data = data->rchild;
    data->parent = temp->parent;
    struct BiNode* pCurror = data->lchild;
    temp->rchild = data->lchild;
    if (pCurror)
    {
        pCurror->parent = temp;
    }

    data->lchild = temp;
    temp->parent=data;
    return data;
}
//右旋轉(zhuǎn)
struct BiNode* RightHand(struct BiNode* data)
{
    struct BiNode* temp = data;
    data = data->lchild;
    data->parent= temp->parent;
    struct BiNode* pCurror = data->rchild;
    temp->lchild = data->rchild;
    if (data->rchild)
    {
        pCurror->parent = temp;
    }
    data->rchild = temp;

    temp->parent = data;
    
    return data;
}
//平衡節(jié)點(diǎn)
struct BiNode* AdjTree(struct BiNode* data)
{//判斷節(jié)點(diǎn)是否為空炒刁,為空返回該節(jié)點(diǎn)
    if (NULL == data)
    {
        return data;
    }
    //判斷子節(jié)點(diǎn)是否有一個(gè)不為空恩沽,都為空不需要調(diào)整
    if (NULL != data->lchild || NULL != data->rchild)
    {
    //初始化棧
        void* stack = Init_SeqStack();
        //把節(jié)點(diǎn)壓入棧
        Push_SeqStack(stack, data);
        //棧中節(jié)點(diǎn)不為0就循環(huán)
        while (Size_SeqStack(stack) > 0)
        {//獲取棧頂元素
            struct BiNode* info = (struct BiNode*)Top_SeqStack(stack);
            //判斷右子節(jié)點(diǎn)是否為空
            if (NULL != info->rchild)
            {//不為空,壓入棧中
                Push_SeqStack(stack, info->rchild);
            }
//判斷左子節(jié)點(diǎn)是否為空
            if (NULL != info->lchild)
            {
            //不為空翔始,壓入棧中
                Push_SeqStack(stack, info->lchild);
            }
            //彈出棧頂元素
            Pop_SeqStack(stack);
            
                //判斷節(jié)點(diǎn)左右子節(jié)點(diǎn)高度差
                    int l = getHight(info->lchild);
                    int r = getHight(info->rchild);
                    //如果左高度-右高度大于1罗心,要進(jìn)行右旋
                    if ((l - r) > 1)
                    {
                        struct BiNode* d1 = info->lchild;
                        int ll = getHight(d1->lchild);
                        int rl = getHight(d1->rchild);
                        //如果子節(jié)點(diǎn)的右節(jié)點(diǎn)高度大于左節(jié)點(diǎn)高度,要先進(jìn)行左旋
                        if (rl > ll)
                        {//左旋
                            info->lchild = LeftHand(d1);
                        }
                        //右旋
                        info = RightHand(info);
                    }
                    //右高度比左高度大1城瞎,要進(jìn)行左旋
                    else if ((r - l) > 1)
                    {
                        struct BiNode* d1 = info->rchild;

                        int ll = getHight(d1->lchild);
                        int rl = getHight(d1->rchild);
                        //如果左子節(jié)點(diǎn)高度大于右子節(jié)點(diǎn)高度
                        if (ll > rl)
                        {//右旋
                            info->rchild = RightHand(d1);
                        }
                        //左旋
                        info = LeftHand(info);
                    }
                                        
        
                    返回交換后的節(jié)點(diǎn)        
                return info;
            }
            //銷毀棧
        Destroy_SeqStack(stack);
    
        }
    //不滿足條件渤闷,返回傳入的節(jié)點(diǎn)
    return data;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市脖镀,隨后出現(xiàn)的幾起案子飒箭,更是在濱河造成了極大的恐慌,老刑警劉巖蜒灰,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弦蹂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡强窖,警方通過(guò)查閱死者的電腦和手機(jī)凸椿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)翅溺,“玉大人脑漫,你說(shuō)我怎么就攤上這事×椋” “怎么了优幸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)褪猛。 經(jīng)常有香客問(wèn)我网杆,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任严里,我火速辦了婚禮,結(jié)果婚禮上追城,老公的妹妹穿的比我還像新娘刹碾。我一直安慰自己,他們只是感情好座柱,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布迷帜。 她就那樣靜靜地躺著,像睡著了一般色洞。 火紅的嫁衣襯著肌膚如雪戏锹。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,584評(píng)論 1 312
  • 那天火诸,我揣著相機(jī)與錄音锦针,去河邊找鬼。 笑死置蜀,一個(gè)胖子當(dāng)著我的面吹牛奈搜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盯荤,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼馋吗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了秋秤?” 一聲冷哼從身側(cè)響起宏粤,我...
    開(kāi)封第一講書(shū)人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎灼卢,沒(méi)想到半個(gè)月后绍哎,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芥玉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年蛇摸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了备图。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灿巧。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖揽涮,靈堂內(nèi)的尸體忽然破棺而出抠藕,到底是詐尸還是另有隱情,我是刑警寧澤蒋困,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布盾似,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏零院。R本人自食惡果不足惜溉跃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望告抄。 院中可真熱鬧撰茎,春花似錦、人聲如沸打洼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)募疮。三九已至炫惩,卻和暖如春阿浓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爸舒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工稿蹲, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涂炎。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓设哗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親震缭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容