盜圖
前言
最近準備面試 ,復習了一下數據結構 中的二叉樹,整理了二叉樹的前序、中序、后序、深度和廣度遍歷以及遞歸和非遞歸實現方法,如有好的方案大家可以一起討論。
前序遍歷
先遍歷根節點,然后再遍歷左子樹,最后再遍歷右子樹
JAVA 示例:
/**
* 前序遍歷
*/
public void previousTraverse() {
if (Objects.nonNull(root)) {
doPreviousTraverse(root);
}
}
private void doPreviousTraverse(Node root) {
//先遍歷根節點
System.out.println(root.getData());
if (Objects.nonNull(root.getLeft())) {
doPreviousTraverse(root.getLeft());
}
if (Objects.nonNull(root.getRight())) {
doPreviousTraverse(root.getRight());
}
}
中序遍歷
思路:先遍歷左子樹,然后遍歷根節點,最后遍歷右子樹
java 示例
/**
* 中序遍歷
*/
public void middleTraverse() {
if (Objects.nonNull(root)) {
doMiddleTraverse(root);
}
}
private void doMiddleTraverse(Node root) {
//先遍歷左節點
if (Objects.nonNull(root.getLeft())) {
doMiddleTraverse(root.getLeft());
}
//遍歷根節點
System.out.println(root.getData());
//遍歷右節點
if (Objects.nonNull(root.getRight())) {
doMiddleTraverse(root.getRight());
}
}
后序遍歷
思路:先遍歷左子樹,然后遍歷右子樹,再遍歷根節點
java示例
/**
* 后序遍歷
*/
public void afterTraverse() {
if (Objects.nonNull(root)) {
doAfterTraverse(root);
}
}
private void doAfterTraverse(Node root) {
//先遍歷左節點
if (Objects.nonNull(root.getLeft())) {
doAfterTraverse(root.getLeft());
}
// 遍歷右節點
if (Objects.nonNull(root.getRight())) {
doAfterTraverse(root.getRight());
}
//遍歷根節點
System.out.println(root.getData());
}
廣度遍歷
思路:使用隊列來輔助實現,首先把根節點放到隊列里,然后彈出 根節點 打印根節 點的値,判斷左子節點是否為空,不為空放入隊列,判斷右節點是否為空,不為空 放入隊列,一次重復上述步驟,找到隊列里沒有數據結束,打印出來的序列則為該 樹的廣度遍歷。
java 示例:
/**
* 廣度遍歷
*/
public void broadCastTraverse() {
if (Objects.nonNull(root)) {
//定義一個存放節點的隊列
LinkedList<Node> nodes = new LinkedList<>();
nodes.addLast(root);
while (!nodes.isEmpty()) {
Node node = nodes.removeFirst();
System.out.println(node.getData());
if (Objects.nonNull(node.getLeft())) {
nodes.addLast(node.getLeft());
}
if (Objects.nonNull(node.getRight())) {
nodes.addLast(node.getRight());
}
}
}
}
深度遍歷 即先序遍歷 若不采用遞歸方式則序借助棧的后進先出
先將根節點事先放到棧中然后執行下面的步驟: 1.從棧頂彈出節點 2.打印節點的値 3.判斷該節點的右子節點是否為空,若不為空則將右子節點放入棧中 4.判斷該節點的左子節點是否為空,若不為空則將左子節點放入棧中 重復上述步驟,直到棧為空
java 示例
/**
* 深度遍歷 即先序遍歷 若不采用遞歸方式則序借助棧的后進先出
* 先將根節點事先放到棧中然后執行下面的步驟:
* 1.從棧頂彈出節點
* 2.打印節點的値
* 3.判斷該節點的右子節點是否為空,若不為空則將右子節點放入棧中
* 4.判斷該節點的左子節點是否為空,若不為空則將左子節點放入棧中
* 重復上述步驟,直到棧為空
*/
public void deepTraverse() {
if (Objects.nonNull(root)) {
Stack<Node> nodes = new Stack<>();
nodes.push(root);
while (!nodes.isEmpty()) {
Node node = nodes.pop();
System.out.println(node.getData());
if (Objects.nonNull(node.getRight())) {
nodes.push(node.getRight());
}
if (Objects.nonNull(node.getLeft())) {
nodes.push(node.getLeft());
}
}
}
}
中序遍歷 非遞歸遍歷 借用棧來實現
思路: 1.首先將根節點 入棧 2.依次將左節點入棧直到左節點為空 3.彈出棧頂打印判斷是否有右節點,若有則入棧
java 示例
/**
* Non-recursive traversal
*
* 中序遍歷 非遞歸遍歷 借用棧來實現
* 思路:
* 1.首先將根節點 入棧
* 2.依次將左節點入棧直到左節點為空
* 3.彈出棧頂打印判斷是否有右節點,若有則入棧
*/
public void nonRecursiveTraverse() {
if (Objects.nonNull(root)) {
Node node = root;
Stack<Node> nodes = new Stack<>();
while (Objects.nonNull(node) || !nodes.isEmpty()) {
if (Objects.nonNull(node)) {
//將根節點入棧
nodes.push(node);
node = node.getLeft();
} else {
Node someLeft = nodes.pop();
System.out.println(someLeft.getData());
if (Objects.nonNull(someLeft.getRight())) {
node = someLeft.getRight();
}
}
}
}
}
完整源碼位置
https://github.com/241600489/homeworks/tree/master/src/main/java/zym/sort/tree/binary
后記
看完之后如果覺得有用麻煩點個贊加個關注哦
參考
https://blog.csdn.net/qq_38875300/article/details/89299647






