數(shù)據(jù)結(jié)構(gòu)之樹(含代碼)

樹的定義

1.樹是由根結(jié)點(diǎn)和若干顆子樹構(gòu)成的赶么。樹是由一個集合以及在該集合上定義的一種關(guān)系構(gòu)成的肩豁。集合中的元素稱為樹的結(jié)點(diǎn),所定義的關(guān)系稱為父子關(guān)系辫呻。父子關(guān)系在樹的結(jié)點(diǎn)之間建立了一個層次結(jié)構(gòu)清钥。在這種層次結(jié)構(gòu)中有一個結(jié)點(diǎn)具有特殊的地位,這個結(jié)點(diǎn)稱為該樹的根結(jié)點(diǎn)放闺,或稱為樹根祟昭。
(1)有且只有一個稱為根的節(jié)點(diǎn)。
(2)有若干個互不相交的樹怖侦,這些子樹本也是一顆樹 篡悟。樹由節(jié)點(diǎn)和邊構(gòu)成(指針域) ,每個節(jié)點(diǎn)只有一個父節(jié)點(diǎn)但可以有多個子節(jié)點(diǎn)匾寝,但有一個節(jié)點(diǎn)例外搬葬,該節(jié)點(diǎn)沒有根節(jié)點(diǎn),此節(jié)點(diǎn)稱為根節(jié)點(diǎn)

二叉樹

專業(yè)術(shù)語

節(jié)點(diǎn) 父節(jié)點(diǎn) 子節(jié)點(diǎn) 子孫 堂兄弟
深度:從根節(jié)點(diǎn)到最底層節(jié)點(diǎn)的層數(shù)稱之為深度,上圖有4層艳悔。
葉子節(jié)點(diǎn):沒有子節(jié)點(diǎn)的節(jié)點(diǎn)急凰,如上圖中的#節(jié)點(diǎn)。
非終端節(jié)點(diǎn):非葉子節(jié)點(diǎn)猜年。
度:子節(jié)點(diǎn)的個數(shù)(樹內(nèi)所有節(jié)點(diǎn)度的最大值)抡锈。

樹的分類

一般樹 二叉樹 森林
一般樹:任意一個節(jié)點(diǎn)的子節(jié)點(diǎn)的個數(shù)都不受限制
二叉樹:任意一個節(jié)點(diǎn)的子節(jié)點(diǎn)的個數(shù)最多兩個,且子節(jié)點(diǎn)的位置不可更改(有序乔外,從上到下床三,從左到右)。(上圖為二叉樹)
森林 :n個互補(bǔ)相交的樹的集合

二叉樹的分類

一般二叉樹:袁稽。勿璃。。推汽。补疑。
滿二叉樹:在不增加樹的層數(shù)的前提下,無法再多添加一個節(jié)點(diǎn)的二叉樹就是滿二叉樹歹撒。
完全二叉樹:如果只是刪除了滿二叉樹最底層最右邊的連續(xù)若干個節(jié)點(diǎn)莲组,這樣形成的二叉樹就是完全二叉樹。
完全二叉樹包含滿二叉樹

樹的存儲(重點(diǎn))

二叉樹的存儲:連續(xù)存儲【完全二叉樹】和鏈?zhǔn)酱鎯?/h5>

(1)連續(xù)存儲【完全二叉樹(用貼的方法)】:為什么要轉(zhuǎn)換為完全而二叉樹的原因:樹為非線性二連續(xù)存儲為線性暖夭,且如果只存取有效節(jié)點(diǎn)則無法還原以前二叉樹的本來面目锹杈。無法確定關(guān)系.
優(yōu)點(diǎn):查找某個節(jié)點(diǎn)的父節(jié)點(diǎn)和子節(jié)點(diǎn)(也包括判斷有咩有)速度很快
缺點(diǎn):耗用內(nèi)存空間過大
(2)鏈?zhǔn)酱鎯Γㄖ羔槪?/p>

一般樹的存儲(非線性結(jié)構(gòu)用線性結(jié)構(gòu)來存儲)

(1)雙親表示法(求父節(jié)點(diǎn)方便)
(2)孩子表示法(求子節(jié)點(diǎn)方便)
(3)雙親孩子表示法(求父節(jié)點(diǎn)和子節(jié)點(diǎn))
(4)二叉樹表示法 把一個普通書轉(zhuǎn)化為二叉樹來存儲撵孤。
轉(zhuǎn)換方法為:設(shè)法保證任意一個節(jié)點(diǎn)的左指針域指向它的第一個孩子,右指針域指向它的下一個兄弟竭望。只要能滿足此條件邪码,就可以把一個普通樹轉(zhuǎn)化成二叉樹。一個普通樹轉(zhuǎn)化成的二叉樹一定沒有右子樹(是根節(jié)點(diǎn) 視頻p65 22:33)

森林的存儲

先把森林轉(zhuǎn)化為二叉樹咬清,再存儲二叉樹闭专,具體方式為:根節(jié)點(diǎn)之間可以當(dāng)成是兄弟來看待

構(gòu)造二叉樹代碼

typedef struct NODE//定義節(jié)點(diǎn) 
{
    int data;//數(shù)據(jù)域
    struct NODE * Left;//左指針 (左孩子) 
    struct NODE * Right; //右指針 (右孩子) 
}BTree,*PBTree;

void Creat_BTree(PBTree &T)//先輸入根,再輸入左子樹旧烧,再輸入右子樹(左邊優(yōu)先
{
    int val;
    cin>>val;
    if(val==-1) T=NULL;//節(jié)點(diǎn)指向空 ,輸入-1結(jié)束影钉。 
    else
    {
        T=(PBTree)malloc(sizeof(BTree));
        T->data=val;
        Creat_BTree(T->Left);//遞歸
        Creat_BTree(T->Right);
    }   
}

輸入值要有一些操作

若想得到圖中的二叉樹要這樣輸入:

1 2 4 -1 -1 5 -1 -1 3 -1 6 -1 -1
**例1**

先序遍歷

遞歸版
例1的結(jié)果為 1 2 4 5 3 6

過程

void preoder(PBTree &T)
{
    if(T!=NULL)
    {
        cout<<T->data<<" ";
        preoder(T->Left);
        preoder(T->Right);
    }
    return;
} 

非遞歸版
非遞歸的前序遍歷需要用到棧的性質(zhì),也就是先進(jìn)后出掘剪。在這里偷些懶平委,直接使用#include<stack>,直接使用棧的頭文件夺谁。

偷些懶廉赔,直接使用#include<stack>,直接使用棧的頭文件予权。
 void preoder(PBTree &T)//先序遍歷昂勉。
{
    PBTree temp=T;//臨時指針 
    stack<PBTree>s ;//創(chuàng)建一個新的棧來存儲節(jié)點(diǎn)。
    while(temp||!s.empty())//當(dāng)temp!=NULL或者棧s為空時 
    {
        while(temp)//控制左節(jié)點(diǎn)扫腺,只有當(dāng)左節(jié)點(diǎn)為空時,才會想起他的右孩子村象。當(dāng)節(jié)點(diǎn)不為空時笆环,一定要向左孩子看一下。 
        {
            cout<<temp->data<<" ";
            s.push(temp);//將節(jié)點(diǎn)壓入棧厚者,方便回溯
            temp=temp->Left;//左節(jié)點(diǎn) 
        }
        // 當(dāng)空節(jié)點(diǎn)時躁劣,跳出循環(huán)
        temp = s.top();
        s.pop();
        //  找到右孩子
        temp = temp->Right;
    }
     return ;
}

中序遍歷

遞歸版
例1的結(jié)果為4 2 5 1 3 6

過程

void inoder(PBTree &T)
{
        if(T!=NULL)
    {
        inoder(T->Left);
        cout<<T->data<<" ";
        inoder(T->Right);
    }
    return;
}

非遞歸版

void inorder(PBTree &T)
{
    //  用于儲存遍歷的元素
    stack<node*> s;
    while( T ||  !s.empty() )
    {
        if ( T!= NULL )
        {
            s.push(T);
            T= T->Left;
        }
        else
        {
           T= s.top();
           s.pop();
           cout << T->data << " ";
            T = T->Right;
        }
    }
}

后序遍歷

遞歸版
例1的結(jié)果為 4 5 2 6 3 1

過程

void postoder(PBTree &T)
{
        if(T!=NULL)
    {
        postoder(T->Left);
        postoder(T->Right);
        cout<<T->data<<" ";
    }
    return;
} 

層次遍歷

遞歸版
例1的結(jié)果為


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市库菲,隨后出現(xiàn)的幾起案子账忘,更是在濱河造成了極大的恐慌,老刑警劉巖熙宇,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鳖擒,死亡現(xiàn)場離奇詭異,居然都是意外死亡烫止,警方通過查閱死者的電腦和手機(jī)蒋荚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來馆蠕,“玉大人期升,你說我怎么就攤上這事惊奇。” “怎么了播赁?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵颂郎,是天一觀的道長。 經(jīng)常有香客問我容为,道長祖秒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任舟奠,我火速辦了婚禮竭缝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘沼瘫。我一直安慰自己抬纸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布耿戚。 她就那樣靜靜地躺著湿故,像睡著了一般。 火紅的嫁衣襯著肌膚如雪膜蛔。 梳的紋絲不亂的頭發(fā)上坛猪,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機(jī)與錄音皂股,去河邊找鬼墅茉。 笑死,一個胖子當(dāng)著我的面吹牛呜呐,可吹牛的內(nèi)容都是我干的就斤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蘑辑,長吁一口氣:“原來是場噩夢啊……” “哼洋机!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起洋魂,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤绷旗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后副砍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衔肢,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年址晕,在試婚紗的時候發(fā)現(xiàn)自己被綠了膀懈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡谨垃,死狀恐怖启搂,靈堂內(nèi)的尸體忽然破棺而出硼控,到底是詐尸還是另有隱情,我是刑警寧澤胳赌,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布牢撼,位于F島的核電站,受9級特大地震影響疑苫,放射性物質(zhì)發(fā)生泄漏熏版。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一捍掺、第九天 我趴在偏房一處隱蔽的房頂上張望撼短。 院中可真熱鬧,春花似錦挺勿、人聲如沸曲横。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽禾嫉。三九已至,卻和暖如春蚊丐,著一層夾襖步出監(jiān)牢的瞬間熙参,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工麦备, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留孽椰,地道東北人。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓泥兰,卻偏偏與公主長得像弄屡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鞋诗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355

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