二叉树的遍历算法(三级)
生活随笔
收集整理的這篇文章主要介紹了
二叉树的遍历算法(三级)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
知道二叉樹在計算機里面是怎么存儲的,有順序存儲結構,采用數組存儲,也有鏈式存儲結構,采用二叉鏈表,或者采用三叉鏈表,那采用鏈式存儲結構更多一點,下面我們會講二叉樹在計算機里的實現,就是鏈式存儲結構的二叉鏈表為例來進行講解的,講這個具體實現之前呢,我們要知道一下二叉樹的遍歷策略,什么叫遍歷?大家想一下,如果是一個線性表的話,他的遍歷是很簡單的,怎么簡單呢,比如說一個數組,來個for循環就遍歷完了,鏈表的遍歷怎么來遍歷,也是一個for循環,然后我們動指針就可以了,讓指針指向下一個節點,直到末尾,它是一條線順藤摸瓜,都可以把所有的數據遍歷出來,對于樹來說就比較復雜了,這里面可是有好幾條線啊,你怎么采用一種方式把里面的每個節點都走一遍,并且只走一遍,這就叫遍歷,遍歷的單詞叫Traverse:1. 就是按照順序訪問樹的所有節點,并且每個節點恰好訪問一次,遍歷其實是下面很多操作的一個基礎,遍歷相當于我們都能找到每個節點2. 下面就可以查詢,我按照我走的策略,看看比較這個值,看看是不是我找的,或者我要更新,我要把2這個值更新成5,遍歷是后面很多操作的一個基礎,因為遍歷我們會得到這樣的一個數列,就好比是一個線性結構了,就像我們的線性表一樣,這就是一個線性結構了,所以我們遍歷呢怎么辦呢,也可以看成是認為的把非線性結構線性化,樹是非線性結構的,就變成他了,關鍵點什么叫遍歷,強調一下,非線性結構的線性化,它是很多操作的基礎,我們怎么進行遍歷呢,我們把整個二叉樹看成三部分,根,左子樹和右子樹,那如果按照這個來遍歷的話,他就有幾種排列組合方式,到底是先做還是先右呢,如果三種任意排列的話,就有幾種啊,他有6種,如果我們再規定一下,必須先遍歷左子樹,再遍歷右子樹,一下子就減掉三個,這樣一來,在這個前提下,規定先遍歷左子樹,再遍歷右子樹,這么一來就是三種方式,怎么會有三種方式呢,1. 先遍歷左子樹,再遍歷右子樹,請問根要放在哪里,根你當然可以放到最前面了,這個叫先根遍歷,或者叫先序遍歷,先遍歷根,再遍歷左子樹,再遍歷右子樹2. 還有一個我把根放在中間,這個叫中序或者中根遍歷3. 還有一個我把根放在最后,這個叫后續遍歷
我們樹的遍歷主要有三種遍歷,怎么這么復雜啊,我先第一層,再第二層,再第三層,再第四層,都遍歷了一下,可以嗎,也可以這叫按照層次遍歷,但是這種遍歷在實際開發中呢,使用的并不多,更多的還是使用上面的一種遍歷,并且上面這三種,因為我們的樹是采用遞歸遍歷的,這是根,這是左子樹,這是右子樹,對于右子樹來說他又有根,又有左子樹又有右子樹,它是遞歸定律的,所以我們這種遍歷的話,先根再左子樹再右子樹,他也是遞歸的,所以這三種遍歷,我們都可以采用遞歸來實現,遞歸有什么好處啊,編碼簡單,一會我們就能見到了,可以采用遞歸辦法我們可以不用遞歸,不用遞歸代碼就比較復雜了,真的很復雜嗎,一會大家就知道了,按層次遍歷,只能按照非遞歸的方式,層次遍歷沒有遞歸,這個明確一下我們先看一下遍歷的算法,什么叫做先序,中序,后序,我們先寫一下,就是這棵樹,我能采用不同的算法,遍歷一下,首先要明白這個遍歷的思路是什么,然后再用代碼給大家實現,我們要進行遍歷了,首先我們要進行先序遍歷,然后我們這邊要進行中序遍歷,這個叫后序或者后根遍歷,都是可以的,1. 首先我們的先序遍歷是什么意思,先是根,然后是左子樹,然后是右子樹,是這么來的,根就是一個節點,左子樹,右子樹就是多個節點了,所以我們應該怎么辦,畫一個圖,先遍歷根的,第一步先遍歷根,然后該誰了,然后左子樹,然后右子樹,雖然我不知道下面的順序會是什么,但是我敢保證,肯定是先有4和5,先把4和5遍歷出來,才有可能遍歷這一塊,然后就遍歷左子樹,再遍歷右子樹了,對于左子樹和右子樹我們該怎么遍歷啊,重復剛才的內容,怎么重復呢,這個4是根,然后它有沒有左啊,沒有,它有沒有右啊,有,這我們就進行遍歷了,我們怎么來進行遍歷,左沒有,沒有就遍歷右,右是5,下面該右子樹了,右子樹我們該怎么辦,右子樹和剛才的一樣,先根,再左,然后再右,先是2,然后是3,再然后就稍微等一下,再然后又是一棵樹,那對下面這棵樹我們又該怎么辦,那就畫唄,先6,再左沒有,再右,所有這是6和7,按照我們剛才的這種思路,分析的思路,是怎么辦,采用遞歸的分析的思路,你會發現對于每個左子樹和右子樹,他采用的處理是采用遞歸在處理的,把左子樹看成是一棵完整的樹,右子樹看成是一棵完整的樹,再套用根,左右的規則就可以了,這是我們一個遍歷的規則2. 中序遍歷:中序遍歷該怎么辦,先左,再根,再右,我把這個寫完以后右邊的大家一起來寫,先是左子樹,然后是根,然后是右子樹,左子樹有好幾條線,然后根是1,右子樹有好多節點,先左,沒有,再根,再右,就可以了,我們這么來寫,這是4,5,我們再看這一部分,先左只有一個,然后再根,再右,先來個幾,3,再來個2,對于這一塊他還是顆樹,這棵樹我們應該怎么辦,左沒有,根6,然后呢7,怎么來的,我們寫一下先來個6,再來個7,這是一個內容,7怎么辦,7就一個節點了,你怎么知道他是一個節點了,老師我一眼就看出來了計算機是看不出來的,計算機怎么知道7是葉子節點了,左孩子和右孩子都是空3. 后根遍歷:大家想一下這個到底該是怎么回事呢,先左子樹,再右子樹,然后再是根,先是左,再是右,最后是根,根是1,左邊該怎么辦,先左左邊有嗎,右邊5,再是根4,這應該是5,4,右子樹呢,同樣是先左再右再根我們得到結論是什么,3,2,中間這一塊呢別著急,我們先畫一個橫線,遞歸的意思,然后怎么辦,先左再右,然后再根,7,6二叉樹的遍歷就講到這里了
已知一棵二叉樹的后序遍歷的序列為 5 4 3 7 6 2 1,中序遍歷的序列為 4 5 1 3 2 6 7,則其先序遍歷的序列是什么?我們是可以推出來的,怎么推呢,只要給出一個中序遍歷,后序先序只要給你一個,你都可以把另外一種給求出來,但是如果先給你一個先,再給你一個后,讓你求中序,那不好說,那求不出來的,怎么可能,不理解,我們拿過來,復制一下,中序后序,我又中序和后序,我怎么知道先序呢,那我當然知道了,后序最后一個肯定是根,然后1是根了,一下子就可以確定誰是根了,然后1的左邊就是左=子樹,1的右邊就是右子樹,我們的樹不用畫,直接就可以寫出來1. 先序遍歷:DLR,D是Deque,根左右,一下子我們就知道誰是根了,1是根,左邊是多少待定,右邊是多少待定,我們先看左邊,左邊只有兩個數,一個4,一個5,什么叫后續遍歷,最后一個肯定是根,先序遍歷的話先寫一個4,后邊就是左和右,左和右不管是誰直接寫5就行了,到底是左還是右,可以看出來的,怎么看出來,4是根,是左是右都有可能,5在后面的那就是右,所以剛才的圖我們就可以畫出來,先寫一個1,然后再來畫一下,這是4,5到底是左還是右是可以畫出來的,根的后面那肯定是右,這是5,下面就沒有難度了,對于我們右邊這4個節點同樣這么來,告訴我怎么辦,后繼遍歷里面最后一個肯定就是根,這個就是根,前面就是左,后邊就是右,這應該是2,左邊是3,這個不用說了,先是2,左邊只有一個3,看我們寫的對嗎,14523到目前為止沒有錯,該這個6和7了,在后序里面后面的一個,那我們就知道了一個是6,另外一個肯定是7,但是7是左還是右啊,畫一下,這是我們的6,7在右邊,這就是我們的7,這是關于我們二叉樹遍歷的一些相關的算法,作序中序后序大家要會,層次代理我們就不說了,層次代理是怎么回事?看著簡單,我們一看就能把層次遍歷寫出來,代碼不好寫,我們先序中序后序看著寫不好寫,寫代碼非常簡單,可以用遞歸來實現,關于遍歷的相關算法已經講了下面我們來看,我們寫實現,二叉樹每一個節點怎么表示,我們是不是已經寫過二叉鏈表了,每個節點包括三部分,所以我們就這么寫了寫二叉樹的節點
package com.learn.btree;/*** 二叉鏈表的節點* @author Leon.Sun**/
public class Node {/*** 節點的值*/private Object value;/*** 左孩子* 左子樹的引用* 同樣為了處理方便,我們把private去掉*/// private Node leftChild; Node leftChild;/*** 右子樹的引用*/// private Node rightChild;Node rightChild;public Node() {super();}public Node(Object value) {super();this.value = value;}public Node(Object value, Node leftChild, Node rightChild) {super();this.value = value;this.leftChild = leftChild;this.rightChild = rightChild;}/*** 這個toString該怎么寫呢* 輸出三個屬性的值就可以了*/@Overridepublic String toString() {return "Node [value=" + value + ", leftChild=" + leftChild + ", rightChild=" + rightChild + "]";}}
package com.learn.btree;/*** 二叉樹接口* 可以有不同的實現類,每個類可以使用不同的存儲結構,比如順序結構、鏈式結構* 鏈式結構可以是二叉的,也可以是三叉的* @author Leon.Sun**/
public interface BinaryTree {/*** 是否空樹* 你的樹是空的嗎,空是什么意思* 有沒有根節點,有根就不是空的了* @return*/public boolean isEmpty();/*** 樹結點數量* 樹里面有幾個節點* @return*/public int size();/*** 獲取二叉樹的高度* 得到樹的高度* @return*/public int getHeight();/*** 查詢指定值的結點* 在樹里面去找一個值* 我去找20,要告訴我這里沒有20才可以* @param value* @return*/public Node findKey(int value); // 查找/*** 前序遞歸遍歷* 這三個遍歷要采用遞歸來實現*/public void preOrderTraverse(); /*** 中序遍歷遞歸操作*/public void inOrderTraverse(); /*** 后序遍歷遞歸操作*/public void postOrderTraverse();/*** 后序遍歷遞歸操作* 這個是重載,一個有參,一個無參* @param node 樹根結點*/public void postOrderTraverse(Node node); /*** 中序遍歷非遞歸操作* 1)對于任意節點current,若該節點不為空則將該節點壓棧,并將左子樹節點置為current,重復此操作,直到current為空。 * 2)若左子樹為空,棧頂節點出棧,訪問節點后將該節點的右子樹置為current* 3) 重復1、2步操作,直到current為空且棧內節點為空。 */public void inOrderByStack();/*** 前序遍歷非遞歸操作* 1)對于任意節點current,若該節點不為空則訪問該節點后再將節點壓棧,并將左子樹節點置為current,重復此操作,直到current為空。 * 2)若左子樹為空,棧頂節點出棧,將該節點的右子樹置為current * 3) 重復1、2步操作,直到current為空且棧內節點為空。*/public void preOrderByStack(); /*** 后序遍歷非遞歸操作* 1)對于任意節點current,若該節點不為空則訪問該節點后再將節點壓棧,并將左子樹節點置為current,重復此操作,直到current為空。 * 2)若左子樹為空,取棧頂節點的右子樹,如果右子樹為空或右子樹剛訪問過,則訪問該節點,并將preNode置為該節點 * 3) 重復1、2步操作,直到current為空且棧內節點為空。 */public void postOrderByStack(); /*** 按照層次遍歷二叉樹* 這個需要借助隊列來實現,這里還是包含很多技能點的*/public void levelOrderByStack();
}
package com.learn.btree;/*** 他要實現一下2我們的BinaryTree,要實現這個接口* 你把這些方法掌握了,那二叉樹的基本操作呢就基本上知道了* 但不是所有的操作,基本操作都知道了* * @author Leon.Sun**/
public class LinkedBinargyTree implements BinaryTree {@Overridepublic boolean isEmpty() {return false;}@Overridepublic int size() {return 0;}@Overridepublic int getHeight() {return 0;}@Overridepublic Node findKey(int value) {return null;}@Overridepublic void preOrderTraverse() {}@Overridepublic void inOrderTraverse() {}@Overridepublic void postOrderTraverse() {}@Overridepublic void postOrderTraverse(Node node) {}@Overridepublic void inOrderByStack() {}@Overridepublic void preOrderByStack() {}@Overridepublic void postOrderByStack() {}@Overridepublic void levelOrderByStack() {}}
package com.learn.btree;/*** 在這個測試類里面我們要干什么,* @author Leon.Sun**/
public class Test {public static void main(String[] args) {/*** 你想進行遍歷,我想遍歷一下這個數* 我想看看這個數一共有幾層,前提是創建一個二叉樹* *//*** 判斷二叉樹是否為空,這個簡單*//*** 先序遍歷遞歸*//*** 中序遍歷遞歸*//*** 后續遍歷遞歸*//*** 中序遍歷非遞歸* 中序遍歷如果采用非遞歸的遍歷* 需要借助棧*//*** 按照層次遍歷,借助隊列* 先把這些層次記住*//*** 在二叉樹中查找某個值*//*** 二叉樹的高度,他總共有幾層*//*** 二叉樹的節點數量* 把我們要實現二叉樹的框架,都給大家搭建出來了*/}
}
?
總結
以上是生活随笔為你收集整理的二叉树的遍历算法(三级)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 树和二叉树的基本概念(二级)
- 下一篇: 二叉树的遍历实现-1(三级)