樹和森林
文章目錄
前言
在學了二叉樹,這種特殊的樹後,我們再回到一般的樹,討論他的儲存和遍歷
一、樹的儲存
實際在寫程式碼的時候,人們用到很多種辦法來儲存樹,以下我來介紹最常見的三種方法
1.雙親表示法
因為我們知道樹中的每一個節點都有唯一的雙親,我們正是利用這個特點來通過一個順序表儲存樹中的節點,每個節點中多加一個元素來儲存其雙親的節點,節點的結構如下:
data | parent |
---|
儲存結構定義為下:
typedef struct TNode{
DataType data;
int parent;
}TNode;
typedef struct
{
TNode tree[MAX];
int root;
int num;
}PTree;
順序表的結構為:
Data | Parent | |
---|---|---|
0 | A | -1 |
1 | B | 0 |
2 | C | 0 |
3 | D | 0 |
4 | E | 1 |
5 | F | 1 |
6 | G | 3 |
7 | H | 3 |
8 | I | 3 |
9 | J | 6 |
因為每一個節點都包含著他的雙親的資訊,所以用這個結構在反覆求節點的雙親的時候很方便,但是求一個節點的孩子節點的時候,就比較麻煩,必須遍歷整個表來找到節點的雙親值是當前的節點。
2.孩子表示法
孩子表示法,就是把每個節點的孩子存到一個單連結串列中去,這個連結串列稱為“孩子連結串列”,每一個節點都對應一個孩子連結串列,沒有孩子的節點,對應的孩子連結串列為空,節點的資料和孩子的頭指標,我們還是用一個順序表來儲存。
儲存結構定義為下:
typedef struct ChildNode{
//孩子連結串列節點結構的定義
int Child;
struct ChildNode *next;
}ChildNode;
typedef struct {
DataType data;
ChildNode * FirstChild;//用來儲存孩子連結串列的頭結點
}DataNode;
typedef struct{
//樹的定義
DataNode nodes[MAX] ;
int root;//樹中根結點在順序表中的位置
int num;//樹中結點個數
}CTree;
順序表的結構為:
孩子表示法和上述的雙親表示法,我們聽名字就可以知道,這種儲存結構在找節點的孩子的時候十分方便,但是在找他的雙親的時候又有些麻煩,於是我們可以在這個順序表的每個結點加上一個雙親域形成帶雙親的孩子表示法。
順序表的結構為:
3.孩子兄弟表示法
通過我們學習二叉樹,我們可以知道,一個結點可以包含指向的孩子的指標,這裡,我們就利用二叉樹的這個特點,把一個孩子的指標改為,指向該節點的右兄弟結點。
如圖所示:
儲存結構定義為下:
typedef struct CSNode {
DataType data;
struct CSNode *FirstChild;//第一個孩子指標
struct CSNode *NextSibling;//右兄弟指標
} CSNode,*CSTree;
孩子兄弟結點是所講的三種儲存方式中最好操作的,他的本質就是二叉樹,只不過,他的右指標的所代表的含義從右孩子變成了他的兄弟,其他的與二叉樹相同,如果想找到某個結點的第n個孩子,可以先通過他的指標找到第一個孩子,然後通過第一個孩子的兄弟結點遍歷n-1次,此時得到的結點就是他的第n個孩子。
接下來所講的樹,森林與二叉樹之間的轉化,就是基於這種結構。
話不多說,直接進入轉化。
二、樹,森林與二叉樹之間的轉化
前面對樹的儲存進行了概述,接下來我們來看樹,森林與二叉樹之間的轉化
首先要告訴大家的是,此時的二叉樹與樹是一 一對應的關係,給定一棵樹有其對應的唯一的二叉樹,同理,給定一個二叉樹,也有唯一對應的樹(或森林)與之對應。
對應的關係圖如下:
二叉樹與樹轉化的實質就是,拿右指標為其兄弟,左指標為其孩子的二叉樹解釋成為一棵樹,本質是與二叉樹差不多的,只是他的右指標不再是他的右孩子,而是他的兄弟了,所以我們在解釋的時候一定要注意他的指向含義。
根據我們對二叉樹的定義,我們知道,任何一棵樹對應的二叉連結串列的根節點的是沒有兄弟的,那麼如果我們遇到了,根節點有兄弟的我們應該如何理解呢?其實,這個時候,我們可以將森林中的各個樹的根節點,視為兄弟,這樣子,這個樹我們就可以解釋了,其實他是一個森林對應的二叉樹。他的根節點和他的第一個孩子視為是這個森林中的第一個樹,右節點則是森林中的其他的樹,這樣子我們對根節點有兄弟的二叉樹也可以做解釋。
1.樹轉化成二叉樹
轉化過程如下:
2.森林轉換為二叉樹
轉化過程如下:
3.二叉樹轉化成森林
轉化過程如下:
相當於2的逆過程,對於每一個右節點已經不再是右孩子,而是該結點對應的兄弟,除此之外其餘正常
三、樹和森林的遍歷
1.樹的遍歷
本質與二叉樹的遍歷相似,對根分為先後的遍歷,但是對於樹來說沒有中根遍歷。
(1)樹的遍歷
①先根遍歷:
首先訪問根節點;
然後從左到右依次根結點的每一棵子樹
②後根遍歷:
首先從左到右依次根結點的每一棵子樹
然後訪問根節點;
(2)樹的遍歷演算法
樹的先根遍歷演算法①:
void RootFirst(CSTree root)
{
if(root != NULL)
{
Visit(root->data)//訪問根結點
p = root->FirstChild;
while(p != NULL) //依次遍歷每一棵子樹
{
RootFirst(p);//遞迴的呼叫進行遍歷
p = p->NextSibling;//指向下一個他的兄弟
}
}
}
樹的先根遍歷演算法②:
void RootFirst(CSTree root){
if(root != NULL)
{
Visit(root->data)//訪問根結點
RootFirst(root->FirstChild;);//先根遍歷第一個子樹
RootFirst(root->NextSibling);//先根遍歷他的兄弟樹
}
}
第二個遞迴的演算法與二叉樹的先序演算法更加的像,他的後根演算法只需在先根的演算法基礎上進行改動一下就可得到。
2.森林的遍歷
(1)先序遍歷:
①訪問森林中的第一棵樹的根結點
②先序訪問第一個樹的子樹森林
③先序訪問剩下第一棵樹的兄弟構成的森林
(1)中序遍歷:
①中序訪問第一個樹的子樹森林
②訪問森林中的第一棵樹的根結點
③中序訪問剩下第一棵樹的兄弟構成的森林
總結
通過學習樹和森林,我們會發現其實樹和森林都是可以用二叉樹來表示的,並且遍歷的演算法也很相似,所以二叉樹是我們能夠理解樹和森林的關鍵。
相關文章
- 資料結構——樹和森林資料結構
- 決策樹和隨機森林隨機森林
- 二叉樹和森林轉換二叉樹
- 資料結構中樹和森林的區別資料結構
- 【機器學習】--決策樹和隨機森林機器學習隨機森林
- [資料結構] 樹、二叉樹、森林的轉換資料結構二叉樹
- 二叉樹的遍歷演算法【和森林的遍歷】【PHP 原始碼測試】二叉樹演算法PHP原始碼
- 隨機森林和機器學習隨機森林機器學習
- 商業智慧(BI)視覺化大屏:既見樹木,又見森林視覺化
- bzoj3123: [Sdoi2013]森林(主席樹+Lca+啟發式合併)
- 極限森林
- 力軟商業智慧(BI)視覺化大屏:既見樹木,又見森林視覺化
- 挪威的森林
- 演算法金 | 決策樹、隨機森林、bagging、boosting、Adaboost、GBDT、XGBoost 演算法大全演算法隨機森林
- 螞蟻森林:四成中國人用手機種樹 參與者達到5.5億
- 系統分析與綜合思維相結合:又見森林又見樹木 - hjorteland
- 基環樹和笛卡爾樹
- 樹和二叉樹簡介二叉樹
- Appium和Python實現螞蟻森林自動化收取能量APPPython
- 決策樹VS隨機森林——應該使用哪種演算法?(附程式碼&連結)隨機森林演算法
- 機器學習(五):通俗易懂決策樹與隨機森林及程式碼實踐機器學習隨機森林
- 從一片森林(JavaScript)到另一片森林(C++)JavaScriptC++
- 森林-環境保護
- 通俗易懂--決策樹演算法、隨機森林演算法講解(演算法+案例)演算法隨機森林
- 一文讀懂隨機森林的解釋和實現隨機森林
- 平衡樹和二叉樹的區別二叉樹
- R:microtable包隨機森林隨機森林
- 隨機森林演算法隨機森林演算法
- 隨機森林的祕密隨機森林
- 隨機森林、EM、HMM、LDA隨機森林HMMLDA
- 二叉查詢樹和笛卡爾樹
- 淺談樹形結構的特性和應用(上):多叉樹,紅黑樹,堆,Trie樹,B樹,B+樹...
- WPF中的視覺樹(VisualTree)和邏輯樹(LogicalTree)視覺
- STP生成樹協議和MSTP多生成樹協議協議
- 《三體2:黑暗森林》總結
- 隨機森林演算法梳理隨機森林演算法
- B 樹和 B+樹的區別, 為什麼 MySQL 要使用 B+樹MySql
- 重學資料結構(六、樹和二叉樹)資料結構二叉樹