程式設計之美 3 10 分層遍歷二叉樹

2021-06-21 15:33:25 字數 2694 閱讀 2876

看到這本書就有一種高大上的感覺,隨手翻翻,今天又搞一道!

首先,看到問題1我首先想到了圖的廣度優先搜尋遍歷演算法,後來一查書(資料結構高分筆記),才想起來樹本來就有一種遍歷方式叫「層次遍歷(p110)"。也就問題1中想要列印樹的方式。利用了資料結構「迴圈佇列」作為輔助的工具。

其實自己想的時候也想到了用佇列的這個辦法。不過想來這本資料結構之高分筆記是我很久之前看過的書,所以想到用佇列這個辦法肯定是受到了這本書的影響。但是書中描述的演算法還是不能完全滿足本題的要求,主要在於書中描述的演算法是將分層遍歷的元素依次放在乙個陣列。但是這樣就造成乙個問題,無法滿足書中要求的分行列印。

那麼我對書中分層遍歷的思路進行改進,那麼就可以滿足書中的要求了:

就拿程式設計之美的題幹中的圖來說:

遍歷到1時,將1放入佇列,然後在1的後面插入乙個標記,標記這是一行,再將1的孩子2和3插入到佇列。

然後取1出佇列,然後列印1

再從佇列中取,取的是標記,那麼把此標記再插入隊尾。

然後從佇列中取,此時是新的一行了吧。然後再將2的孩子插入到隊尾,接著列印2

那麼再從佇列中取,取到3,那麼將3的孩子插入到隊尾,再列印3.

再從佇列中取,會取到標記.....

就這樣一直迴圈下去。

這個做法是我自己新發現的,主要是從昨天看到的nginx裡面的結構體ngx_cycle_t的元素:

裡面領悟出來的。

在講這個演算法之前,提醒大家注意,在本題後面不是還有幾個擴充套件問題麼?我這個演算法也考慮到了後面的擴充套件問題,所以擴充套件問題也一起被解決了。

這個演算法實際上用乙個圖就能很請清楚的看懂,如下所示:

簡單來說就是利用雙向鍊錶,由於使用單項鍊表是無法滿足擴充套件問題中要求每一層的訪問資料變為由右到左的,但是雙向鍊錶可以很好的解決這個問題。

注意這個陣列中每乙個元素都是雙向鍊錶的表頭,為了標識表頭,我們使得其的data部分為null。那麼當,從head開始遍歷或者是從tail開始遍歷都能夠很好的解決判斷是否遍歷完整個鍊錶資料。

/**

* 程式設計之美3.10:分層遍歷二叉樹

* * 使用雙向完成該功能

* 更詳細的內容參見:

*/#include #include #include typedef struct nodenode;

typedef struct doublequeuedq;

/** * 這個是要遞迴呼叫的

* 第一次呼叫的時候的根節點

* depth是層次的高度,同時也是dqarray的下標

* node節點應該加到與depth對應的下標

ndoe節點的孩子加到depth+1 的下標

*/void builddoublequeue(node *node , int depth,dq **dqarray)

//currentdphead指向表頭

dq *currentdphead = dqarray[depth];

if(currentdphead->next == currentdphead)else

builddoublequeue(node->lchild,depth+1,dqarray);

builddoublequeue(node->rchild,depth+1,dqarray);

}int main()

//root是第0層,所以我們把root

builddoublequeue(root,0,dqarray);

printf("從左到右列印---------------\n");

//建好之後,我們按照書上的要求列印

for(i = 0; i < 4 ; i++)

printf("\n");

} printf("從右到左列印---------------\n");

for(i = 0; i < 4 ; i++)

printf("\n");

} printf("從下到上列印---------------\n");

//建好之後,我們按照書上的要求列印

for(i = 3; i >= 0 ; i--)

printf("\n");

}}

從左到右列印---------------

1 2 3

4 5 6

7 8

從右到左列印---------------

1 3 2

6 5 4

8 7

從下到上列印---------------

7 8

4 5 6

2 3

1

使用了遞迴來構建雙向鍊錶,實際上也可以用迴圈來完成。用迴圈完成時構建的時間複雜度就是o(n),因為遍歷了二叉樹中的每乙個元素。然而我在這裡採用了遞迴,時間複雜度為o(nlogn)。我寫的時候無意識的就寫成了遞迴,可見這到題用遞迴更容易完成。

其次,我們有額外的空間複雜度,但是好處就是我們在一次計算好之後,在得到需要的第幾層的元素、第幾層的第幾個元素的時間複雜度都為o(1);

程式設計之美 3 10 分層遍歷二叉樹

1 2 3 4 5 6 7 8 運用bfs只能輸出1,2,3,4,5,6,7,8這個序列,並不知道分層資訊,因此如何分層列印呢?我的方法就是對每乙個節點做以下判斷,如果該節點在佇列中的下乙個節點是是null說明該節點是樹在某一層的最後乙個節點,將該節點的子節點輸入佇列中之後,在輸入乙個null節點。...

程式設計之美讀書筆記 3 10 分層遍歷二叉樹

3.10 分層遍歷二叉樹 看到milo寫的這篇文章 又翻了下書,發現書的 p253 有個瑕疵,每個節點值後面都會顯示乙個空格,如果將間隔字元改為 輸出的每行最後都有乙個 不能達到要求。不過,只要將 cout vec cur data 這行改為 if cur last 1 cout vec cur d...

3 10分層遍歷二叉樹 擴充套件問題

給定一棵二叉樹,要求按分層遍歷該二叉樹,即從上到下按層次訪問該二叉樹 每一層將單獨輸出一行 每一層要求訪問的順序為從左到右,並將節點依次編號。要求遍歷輸出的結果分別為圖2,圖3和圖4,其中圖3和圖4是擴充套件問題。圖1 圖2 圖3 圖4 程式設計之美書上,採用的是容器構成的陣列來實現的,相比於遞迴演...