日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构 非线性结构 树 介绍及存储方法

發布時間:2025/3/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构 非线性结构 树 介绍及存储方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?????????? 所謂樹, 其實跟鏈表有類似的地方,? 就是都是由節點和指針構成的數據結構.

?????????? 在鏈表中,? 每1個節點(尾節點除外)只有1個指針指向下1個節點. 所以鏈表各個節點可以由一條線鏈接起來, 就是一種線性結構.

?????????? 而在樹中, 每1個節點可以有1個或多個指針指向下1個節點,? 如下圖:



????????????? 所以樹是一種非線性結構, 對于這種結構, 有很多算法都要依賴遞歸來實現, 否則就相當復雜, 所以很多教程都把遞歸作為1個專題放在樹這章之前講解, 就是這個原因.

????????????? 其實樹也可以利用連續存儲來實現, 也就是說節點不需具有指向別的節點的指針, 但是這種樹必須是完全二叉樹。 下面會詳細提到。

1. 樹的定義

???????? 樹的定義有兩種, 一種是專業的定義, 跟遞歸有關.

???????? 專業定義:

???????????????? 1. 只有1個稱為根的節點.

???????????????? 2. 有若干個互不相交的子樹, 這些子樹本身也是樹.


???????????????? 解析下,子樹本身也是樹, 就如上上圖的樹A, 根就是是A了, 它具有2個子樹, 分別是B1 和 B2, 而B1和B2也是1棵樹啊, 所以, 這個定義跟遞歸有關.


?????????? 通俗定義:

???????????????? 1. 樹是有節點和邊組成.(為什么不用指針這個字眼,用邊?因為樹是可以利用連續存儲來實現的,下面會提到)

???????????????? 2. 每1個節點只有1個父節點, 但是可以有多個子節點.

???????????????? 3. 但是有1個節點例外, 該節點沒有父節點, 此節點就是根節點.



2. 樹的一些專業術語.

??????????? 節點:

? ? ? ? ? ? ? ? ? ? 構成樹的元素, 通常節點里會包含指向其他節點的指針.? 在C語言中, 節點通常是由結構體來表示的.


???????????? 父節點:

??????????????????? 節點的上1級節點,? 通常1個節點有且只有1個父節點, 根節點例外, 根節點沒有父節點.


???????????? 子節點:

??????????????????? 節點的下一級節點, 1個節點可以有1個或多個子節點, 也可以沒有子節點.


????????????? 子孫:

??????????????????? 1個節點的子節點或者子節點的子節點....,等所有下級節點都可以成為這個節點的子孫,? 1棵樹的所有節點都是根節點的子孫.?? 上圖C2 是B1的子孫, 但不是B2的子孫.


????????????? 兄弟:

??????????????????? 擁有同1個父節點的若干個節點成為兄弟, 上圖B1 就是 B2的兄弟


????????????? 堂兄弟:

???????????????????? 不屬于同1個父節點, 但是它們的父節點屬與同1個父節點的若干個節點就是堂兄弟. 上圖C1 就是 C3的堂兄弟.


????????????? 深度:

???????????????????? 1棵樹從根節點到最底層節點的層數稱之為深度.?? 根節點是第1層.


?????????????? 葉子節點:

????????????????????? 沒有子節點的節點, 因為葉子不同于樹干, 不能再分叉了.? 當1個棵樹只有1個節點, 那么這個節點是根節點. 也是葉子節點.


?????????????? 非終端節點:

?????????????????????? 實際就是非葉子節點,? 就是具有子節點的節點.


??????????????? :

??????????????????????? 1個節點的子節點個數成為這個節點的度

??????????????????????? 1個樹中擁有最大度的節點的度就是這個樹的度.


???????????????

? ? ? ? ? ? ?? 森林:

? ? ? ? ? ? ? ? ? ? ? ? ? n個互不相交的樹的集合, 成為森林. ????????


3. 樹的分類

??????????????? 一般的樹:

????????????????????????? 任意1個節點的子節點的個數都不受限制的樹.


??????????????? 二叉樹: (binary tree)

?????????????????????????? 任意1個節點的個數最多有連個, 且子節點的位置不能被更改, 這種樹就是二叉樹.

?

??????????????????????????? 第一句容易理解, 關鍵是第二句, 子節點的位置不能更改??? 其實意思就是二叉樹是有序的, 它的節點最多只有2個子節點, 分別是左子節點和右子節點,? 它們的順序不能被更改. 也不能更改節點的父子點(移動子樹),我們稱為這種樹是有序的樹

??????????????????????????? 一般的樹沒有這種要求, 可以是有序的樹, 也可以是無序的樹(子節點位置可更改),??? 但是2叉樹必須是有序的樹.

??????????????

???????????????????????????? 二叉樹還有分類

???????????????

???????????????????????????滿二叉樹: (full binary tree)

????????????????????????????????????? 在不增加層數的情況下,? 無法再多添加1個節點的二叉樹, 就是滿二叉樹. 例如上圖那個樹就是非滿2叉樹, 因為還可以添加1個C4節點在B2節點下.

????????????????????????

??????????????????????????????????????? 添加了C4節點后, 就是1個滿二叉樹, 如下圖:




???????????????????????????????????????? 假如1個滿二叉樹的層數是k, 那么它的節點個數必定是 (2^k-1).

???????????????????????????????????????? 這里順便貼個等比數列求和的推導公式:

(1)Sn=a1+a2+a3+...+an(公比為q) (2)q*Sn=a1*q+a2*q+a3*q+...+an*q =a2+a3+a4+...+a(n+1) (3)Sn-q*Sn=a1-a(n+1) (4)(1-q)Sn=a1-a1*q^n (5)Sn=(a1-a1*q^n)/(1-q) (6)Sn=(a1-an*q)/(1-q) (7)Sn=a1(1-q^n)/(1-q)
????????????????????? 完全二叉樹: (Complete binary tree)

???????????????????????????????? 完全二叉樹就厲害了,之前提到滿二叉樹的目的就是為了引出完全二叉樹. 滿二叉樹是完全二叉樹的一種。

???????????????????????????????? 若設二叉樹的深度為h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第 h 層所有的結點都連續集中在最左邊,這就是完全二叉樹。

???????????????????????????????? 又有1個通俗定義: 當1棵層數為k滿二叉樹, 從它的最底層的最右邊的節點開始,連續向左刪除n個節點(2k >= n >= 0), 得到的樹就是1棵完全二叉樹.

???????????????????????????????? 如下圖, 左邊兩個是完全二叉樹, 而右邊那個不是,因為最下層的節點不是向右連續的啊!



??????????????????????????? 這里補充一點:完全二叉樹是效率很高的數據結構,堆是一種完全二叉樹,所以效率極高,像十分常用的排序算法、Dijkstra算法、Prim算法等都要用堆才能優化,幾乎每次都要考到的二叉排序樹的效率也要借助平衡性來提高,而平衡性基于完全二叉樹。

??????????????????????????? 這里為什么要特別提到完全二叉樹呢?? 因為完全二叉樹是一種重要的數據結構, 跟棧,對列一樣, 二叉樹也可以用鏈式和數組內核來實現, 但是因為數組必須是連續存儲的, 所以數組實現的二叉樹必須是完全二叉樹。

??????????????????????????? 完全二叉樹的性質:

?????????????????????????????????? 1. 如果知道完全二叉樹的節點個數, 就必然可以退出完全二叉樹的形狀(包括層數, 最后一層的節點排布)。? 也就是說兩個節點樹相同的完全二叉樹的形狀是一樣的。

?????????????????????????????????? 2. 根據第1個性質, 只需要知道1個確定節點個數的完全二叉樹的節點編號, 就可以推出這個節點的父節點和字節點! 這個是1個非常重要的優點!

???????????????????????????

3. 樹的存儲(內存)

????? ??? 3.1 二叉樹的存儲:

??????????????? 3.1.1. 連續存儲

?????????????????????? 上面提過了, 要利用連續存儲(數組)來實現的二叉樹必須是完全二叉樹, 因為它們的節點必須是連續的啊! 如果要利用連續存儲來存儲普通的二叉樹, 就必須把這個二叉樹轉化為完全二叉樹。

?????????????????????? 關鍵是如何轉化? 很簡單, 就是添加必要的空節點把1個非完全二叉樹補成1個完全二叉樹, 如下圖:


????????????????????? 藍色的樹就是1個普通的2叉樹,? 白色的節點就是必要的不存放實際數據的節點, 添加上去組成1個完全二叉樹, 就可以利用連續存儲了。

????????????????????? 至于要轉成完全二叉樹的原因:

????????????????????? 假如只按一定的順序只存儲有效的節點,? 內存物理上是1個線性結構, 如果把非線性的樹存放在線性的內存中,存放后就變成線性結構了,例如上圖中的藍色樹在內存里存放: A,B1,C1,C2,D3,D4? 的確是能存放, 但是不能將存放的數據還原成原來的樹啊! 所以就必須添加一些無效的節點令它轉化成1個完全二叉樹!


????????????????????? 缺點:

??????????????????????? 其實也可以看出, 如過利用連續存儲來存放普通的二叉樹, 首先需要一定量的連續內存空間,而且必然會造成1些空間浪費。 而且普通二叉樹的層數越大, 耗費的內存越大!

??????????????????? ? 優點:

??????????????????????? 就是上面完全二叉樹的第2個性質,? 只需要知道1個節點在數組的位置, 就可以推出它的父節點和子節點, 時間復雜度是0啊!


????????????? 3.1.2. 鏈式存儲

???????????????????? 這個跟鏈表有點類似。

???????????????????? 我們會把每1個節點分成4個域, 分別是數據域, 父節點指針域, 左子節點指針域, 右字節域指針域。(或者不包含父節點指針域,則只有3個域)

???????????????????? 如下圖:



???????????????????? 可以見到,這種存儲方式浪費的空間很少, 無非就是一些子節點的空指針, 但是這些空指針個數仍是線性增長的, 但是我們認為浪費的空間已經很少啦, 比起連續存儲來講, 因為鏈式存儲不需存儲多余的節點啊。

????????????????????

??????????????????

????????

????? 3.2 一般樹的存儲:

????????????? 一般樹的特點是節點的度(子節點個數)無限制, 用上面連續存儲根本沒可能, 如果用鏈式存儲也很困難, 因為無法決定子節點的子節點指針域的個數啊!

??????????? 3.2.1 雙親表示法(數組)

??????????????????? 雙親表示法實際上也是利用連續存儲的, 只不過數組內的元素必須分為兩個域, 1個是數據域, 另1個是父節點的下標(注意不是指針啊). 根節點的父節點下標是·-1.

??????????????????? 雙親表示法對于元素(節點)在數組內的順序無要求。

? ? ? ? ? ? ? ? ? ? 如下圖:


???????????????? 如上圖右邊的數組, 基本上可以把1棵樹的結構表示出來了, 但是有個問題, 就是無法通過數組得到同1個父子點兄弟之間的順序, 例如無法知道C1,C2,C3這個3兄弟在樹中的順序, 所以雙親表示法只適合表示無序的樹。

? ? ? ? ? ? ? ?? 優點:

? ? ? ? ? ? ? ? ? ?? 幾乎不浪費內存空間, 查找父節點很容易。

? ? ? ? ? ? ? ?? 缺點:

? ? ? ? ? ? ? ? ? ?? 不能表示有序的樹, 查找子節點相對困難, 查找任何1個節點的子節點都必須遍歷整個數組。 不能表示有序的樹。


? ? ? ? ??

?????????? 3.2.2 孩子表示法(數組)

???????????????? 孩子表示法也是利用連續存儲來實現的, 它的節點同樣具有兩個域, 1個是數據域, 另1個是1個子節點下標鏈表的頭節點地址。

???????????????? 關鍵就是這個鏈表了, 鏈表的節點有兩個域, 1個是int類型,用于表示節點下標, 另1個是指針。

???????????????? 如下圖:



??????????? 可以見到, 因為可以利用子節點下標鏈表的順序來表示子節點兄弟的順序, 所以這種表示法是能表示有序樹的。

??????????? 優點:

????????????????? 查找子節點算法很方便, 可以表示有序樹

??????????? 缺點:

???????????????? 查找父節點算法很困難, 必須遍歷每1個節點的子節點下標鏈表, 如上圖, 甚至判斷哪個是根節點都需要遍歷啊(O(n^2))!?


??????????????

??????????

??????? 3.2.3 雙親孩子表示法(數組)

???????? 由上面的例子可以看出, 其實雙親表示法和孩子表示法的優缺點是互補的, 所以把它們合拼在一起就是雙親孩子表示法了。

???????? 所謂雙親孩子法就是指表示樹的數組內的節點有3個域, 數組域, 父節點下標域,及子節點下標鏈表域。

???????? 如下圖:

????????

???????? 優點:

????????????? 具有雙親表示法和孩子表示法的所有優點, 關鍵是方便地查找父節點和子節點。

???????? 缺點:

????????????? 占用相對更多的內存空間。


???????

?????? 3.2.4 二叉樹表示法


??????? 這個的原理就是把一般樹轉化為二叉樹, 然后再利用二叉樹的存儲方法來存儲。

??????? 關鍵是如何把1個一般樹轉化為二叉樹?? 一句話:? 每個子節點的左子節點指向它原來的第1個子節點,?右子節點指向它原來的下1個兄弟

??????? 所以這個方法又叫孩子兄弟鏈表表示法

??????? 如下圖:


??????? 可以看到, 轉換后層數增加了, 而且某個子樹的度越大, 轉化后所需的層數越多, 畢竟是利用層數來表示兄弟的個數啊。

??????? 而且有個特點, 就是轉化后的二叉樹, 對于根節點來講, 是沒有右字數的, 因為根節點沒有兄弟嘛。

??????? 優點:

???????????? 能使用一些二叉樹的算法。

??????? 缺點:

???????????? 查找真正的父節點和子節點的算法有點復雜,? 例如上圖轉化后的二叉樹, 如果求C3的父節點, 則必須反方向先求出C2和C1..



???????

???????? 3.3 森林的存儲:


? ? ? ? ??? 所謂森林上面也提到過了, 就是互不相交(沒有公共節點)的n棵樹的集合。

? ? ? ? ? ? 例如下圖中的三棵樹就可以組成1個森林。

? ? ????????



?????????? 一般來講,

?????????? 首先: 我們會先把森林的所有樹轉化為二叉樹(孩子兄弟鏈表表示法)

?????????? 然后: 把轉化后的二叉樹合成1個新的二叉樹, 怎么合成? 就是把各個二叉樹視為兄弟, 然后新增1個根節點作為它們的父子點。

?????????? 其實不難理解的啦, 轉化后如圖:


??????? 然后就按照二叉樹的方法存儲就ok了。


總結

以上是生活随笔為你收集整理的数据结构 非线性结构 树 介绍及存储方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。