數據結構與算法 | 來來來,讓咱們從新認識一下什麼是樹



Hi! 你們好,我是小小,咱們開始今天的內容,今天主要講解什麼是樹。node

樹的遞歸結構

從一張圖中解釋什麼是樹這張圖,主要講解關於cart這個單詞的全部的可能組合,按照常理,須要先考慮三個字母的排列,而後對三個字母進行拆分,直到最後一個節點,這個過程就相似於樹 到底什麼是樹web

什麼是樹

樹是節點集合(A tree is a collection of nodes),面試

集合:集合是容許一個元素都沒有的集合,稱之爲空集。數組

首先,集合是容許一個元素都沒有的集合,稱之爲空集,那麼書是否是也容許一個節點都沒有的呢,是的,一個節點都沒有的樹,稱之爲空樹,若是不是空的,則會存在根節點r和零個或更多非空子樹,T1,T2.。。Tk,他們的根由來自r的有向鏈接,什麼叫有向邊,大體能夠理解爲箭頭。用圖的關係說明樹的內部關係緩存

  1. 根節點(root)一棵樹只有一個跟節點,全部的節點都在該節點的下面,嘗試把圖倒過來看,能夠當作一個咱們平常見到的數的根部,在這裏顯然字母A就是這顆樹的根節點。微信

  2. 子節點,父節點,一個節點,它對應的下面有連這的節點,那麼被連着的節點就是這個節點的子節點,也叫作孩子,那麼這個節點叫作被鏈接的節點的父親,看圖,B被A連這,因此B是A的一個孩子,同理,CDE等等這一行都是A的孩子,同時F,它連這K L M 同時被A連這,那麼F是A的一個孩子,同時又是K L M 的父親。數據結構

  3. 樹葉:樹葉就是那些沒有孩子的節點,好比B,C,D等等,例以下圖的綠色部分。app

  4. 兄弟: 按照咱們的理解,同一個父母生的固然是兄妹,以下圖所示,顏色相同的都是兄妹maven

  5. 路徑 咱們一樣能夠定義從父親到他孩子的路徑,下面的路徑,咱們就取上圖的一部分,一個子樹,做爲例子好比,A->O的路徑爲A->E->J->O它的長度爲3,實際爲它的邊數,圖中紅色的部分。編輯器

  6. 節點的深度:節點的深度指的是節點到樹根的長度,看下圖,咱們能夠輕易的知道,j節點的深度爲2,能夠理解爲 A-> E -> J 邊長爲2.顯然,此時根節點的深度爲0.

  7. 節點的高度:高度是從節點到葉子的最長路徑,好比節點F的高度爲1,顯然全部葉子節點高度爲0.

  8. 樹的高度,樹的高度是跟的高度,顯然在這圖中,樹的高度爲3,A->O

樹的特色

  1. 按照正常的邏輯,一我的不能同時有兩個父親,因此樹也同樣,下圖的兩個就解釋了這個問題
  2. 一顆正常的樹,它的樹枝是不會長成一個圓的,因此,樹中,是不可能出現環形的。圖中,紅色箭頭構成了一個環,因此都不是一顆樹。

樹的存儲結構

樹的存儲結構有三種,分別爲,雙親表示法,孩子表示法,孩子兄弟表示法。

雙親表示法

假設一組連續空間保存着樹的特色,同時在每一個節點中,附帶一個指示器表示雙親節點中鏈表的爲位置,也就是說,每一個節點除了知道本身是誰之外,還知道他的雙親在哪裏。其中data是數據域,存儲結點的數據信息。而parent是指針域,存儲該結點的雙親在數組中的下標。

//樹的雙親表示法結點結構定義
#define MAX_TRUE_SIZE 100
typedef int TElemType //樹結點的數據類型

//結點結構
typedef struct PTNode
{
TElemType data; //結點數據
int parent; //雙親位置
}PTNode

//樹結構
typedef struct
{
PTNode nodes[MAX_TRUE_SIZE]; //結點數組
int r,n //根的位置和結點數
}PTree

有了這樣的數據結構就能夠來實現雙親表示法。因爲根結點是沒有雙親的,因此咱們約定根結點的位置域設置爲-1,這也就意味着,咱們全部的結點都存有他雙親的位置。如圖1-2中的樹結構和表1-3中的樹雙親表示。這樣的存儲結構,咱們能夠根據結點的parent’指針很容易找到他的雙親結點,時間複雜度爲O(1),直到parent爲-1時,表示找到了樹結點的根

孩子表示法

換一種徹底不一樣的考慮方法,因爲樹中每一個結點可能有多棵子樹,能夠考慮用多重鏈表。每一個結點有多個指針域,其中每一個指針指向一顆子樹的根結點,咱們把這種方法叫作多重鏈表的表示方法。不過,樹的每一個結點的度,也就是他的孩子個數是不一樣的,因此設計兩種方法:

方案一

指針域的個數就等於樹的度,樹的度就是樹各個結點度的最大值。其結構如圖

其中data是數據域,child1到childd是指針域,用來指向該結點的孩子結點。對於圖1-1來講,樹的度是3,因此咱們指針域個數就是3,

方案二

每一個結點指針域的個數等於該結點的度,咱們專門取一個位置來存儲結點指針的個數。data爲指針域,degree爲度域,也就是存儲該結點的孩子結點的個數這就是咱們要說的孩子表示法,把每一個結點的孩子都排列起來,以單鏈表爲存儲結構,則n個結點有n個孩子鏈表,若是是葉子結點則此單鏈表爲空。而後n個頭指針又組成一個線性表,採用順序存儲結構,存放進一個一維數組,爲此,設計兩種存儲結構,一個是孩子鏈表的孩子結點,child是數據域,用來存儲某個結點在表頭數組中的下標。next是指針域,用來存儲指向結點的下一個孩子結點的指針。另外一個是表頭數組的表頭結點。data是數據域,存儲某結點的數據信息,firstchild是頭指針域,存儲該結點的孩子鏈表的頭指針。

//樹的孩子表示法結構定義
#define MAX_TRUE_SIZE 100
typedef struct CTNode //孩子結點
{
int child;
struct CTNode *next;
}*ChildPtr;
//表頭結構
typedef struct
{
TElemType data;
ChildPtr firstchild;
}CTBox;
//樹結構
typedef struct
{
CTBox nodes[MAX_TRUE_SIZE]; //結點數組
int r,n; //根的位置和結點數
}CTree

把把雙親表示法和孩子表示法綜合一下表示以下這種表示法叫作雙親孩子表示法,應該算是孩子表示法的改進。

孩子兄弟表示法

任一棵樹,它的結點的第一個孩子若是存在就是惟一的,它的右兄弟若是存在也是惟一的。所以。咱們設置兩個指針,分別指向該結點的第一個孩子和此結點的右兄弟。data是數據域,fitstchild爲指針域,存儲該結點的第一個孩子結點的存儲地址,rightsib是指針域,存儲該結點的右兄弟結點的存儲位置。

//孩子兄弟表示法結構定義
typedef struct CSDNode
{
TElemType data;
struct CSNode *firstchild,*rightsib;
}CSNode,*CSTree;

這種方法的示意圖以下所示這種表示法,給查找某個結點的某個孩子帶來了方便,只須要經過firstchild找到此結點的長子,而後在經過長子結點的rightsib找到它的二弟,接着一直找下去,直到找到具體的孩子。

推薦閱讀

● 面試官 | Java轉List三種方式,你說說吧。我。。懵逼。啥時候有三種了

● 面試官 | 這位連單點登陸都不知道,讓他回家等通知去吧

● 問題解決 | maven包衝突了怎麼辦,這款插件你不容錯過

● 必知必會 | 關於Redis緩存這三大問題,必知必會

● 必備收藏 |詳解 | 求你別用效率低下的I/O了,要不試試這種I/O

給我個好看再走好嗎?


本文分享自微信公衆號 - 小明菜市場(fileGeek)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索