二叉树的遍历实现-1(三级)
生活随笔
收集整理的這篇文章主要介紹了
二叉树的遍历实现-1(三级)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
package com.learn.btree;/*** 二叉鏈表的節(jié)點* @author Leon.Sun**/
public class Node {/*** 節(jié)點的值*/// private Object value;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;/*** 二叉樹接口* 可以有不同的實現(xiàn)類,每個類可以使用不同的存儲結構,比如順序結構、鏈式結構* 鏈式結構可以是二叉的,也可以是三叉的* @author Leon.Sun**/
public interface BinaryTree {/*** 是否空樹* 你的樹是空的嗎,空是什么意思* 有沒有根節(jié)點,有根就不是空的了* @return*/public boolean isEmpty();/*** 樹結點數(shù)量* 樹里面有幾個節(jié)點* @return*/public int size();/*** 獲取二叉樹的高度* 得到樹的高度* @return*/public int getHeight();/*** 查詢指定值的結點* 在樹里面去找一個值* 我去找20,要告訴我這里沒有20才可以* @param value* @return*/public Node findKey(int value); // 查找/*** 前序遞歸遍歷* 這三個遍歷要采用遞歸來實現(xiàn)*/public void preOrderTraverse(); /*** 中序遍歷遞歸操作*/public void inOrderTraverse(); /*** 后序遍歷遞歸操作*/public void postOrderTraverse();/*** 后序遍歷遞歸操作* 這個是重載,一個有參,一個無參* @param node 樹根結點*/public void postOrderTraverse(Node node); /*** 中序遍歷非遞歸操作* 1)對于任意節(jié)點current,若該節(jié)點不為空則將該節(jié)點壓棧,并將左子樹節(jié)點置為current,重復此操作,直到current為空。 * 2)若左子樹為空,棧頂節(jié)點出棧,訪問節(jié)點后將該節(jié)點的右子樹置為current* 3) 重復1、2步操作,直到current為空且棧內(nèi)節(jié)點為空。 */public void inOrderByStack();/*** 前序遍歷非遞歸操作* 1)對于任意節(jié)點current,若該節(jié)點不為空則訪問該節(jié)點后再將節(jié)點壓棧,并將左子樹節(jié)點置為current,重復此操作,直到current為空。 * 2)若左子樹為空,棧頂節(jié)點出棧,將該節(jié)點的右子樹置為current * 3) 重復1、2步操作,直到current為空且棧內(nèi)節(jié)點為空。*/public void preOrderByStack(); /*** 后序遍歷非遞歸操作* 1)對于任意節(jié)點current,若該節(jié)點不為空則訪問該節(jié)點后再將節(jié)點壓棧,并將左子樹節(jié)點置為current,重復此操作,直到current為空。 * 2)若左子樹為空,取棧頂節(jié)點的右子樹,如果右子樹為空或右子樹剛訪問過,則訪問該節(jié)點,并將preNode置為該節(jié)點 * 3) 重復1、2步操作,直到current為空且棧內(nèi)節(jié)點為空。 */public void postOrderByStack(); /*** 按照層次遍歷二叉樹* 這個需要借助隊列來實現(xiàn),這里還是包含很多技能點的*/public void levelOrderByStack();
}
package com.learn.btree;/*** 他要實現(xiàn)一下2我們的BinaryTree,要實現(xiàn)這個接口* 你把這些方法掌握了,那二叉樹的基本操作呢就基本上知道了* 但不是所有的操作,基本操作都知道了* 這是一個鏈式二叉樹的實現(xiàn)類* * 這個類里面我們做一個操作,* @author Leon.Sun**/
public class LinkedBinaryTree implements BinaryTree {/*** 根節(jié)點*/private Node root;/*** 我每次增加一個節(jié)點的時候他就加1* 但是為什么我們目前沒有寫size,* 因為目前沒有增加的方法,* 我們創(chuàng)建這棵樹,是直接做的,* 當然還有簡單的方法,創(chuàng)建這棵樹時候,你把7傳進來* 但是這么做也沒有什么技術含量,這個size我們每次=求就可以了*/// private int size;/*** 然后我們再給他提供一個構造方法*/ public LinkedBinaryTree(Node root) {super();this.root = root;}public LinkedBinaryTree() {super();}/*** 這里永遠返回false,* 怎么樣這棵樹才是空的呢,樹是空的,一個節(jié)點也沒有*/@Overridepublic boolean isEmpty() {/*** 就是root等于null* 如果root等于的話他就是一個空的樹*/return root==null;}/*** 我們的這個size該怎么辦,*/@Overridepublic int size() {System.out.println("二叉樹節(jié)點的個數(shù): ");/*** 你想一下他的數(shù)量應該是多少* 你怎么知道他的結構是7呢,* 因為左邊是2,右邊是4,* 整個就是2+4+根1等于7* 你怎么知道這個是4呢,* 左邊是1,右邊是2,再加上根1,等于4* 你怎么知道這個是2呢,* 左邊是0,右邊是1,再加上這個根1,等于2* 你怎么知道7是1呢,* 左邊是0,右邊是0,再加上1等于1* 好像和我們剛才求高度是一樣的* 只不過高度里面是求兩個里面最大的樹* 我們現(xiàn)在是兩個數(shù)相加* */return this.size(root);}/*** 這里還是寫成private不對外公布了* 這里面要寫一個Node,* 寫Node root吧,root可讀性強*/private int size(Node root) {/*** 如果root等于null還是返回0*/if(root==null) { return 0;}else {/*** 獲取左子樹的size*/int nl = this.size(root.leftChild);/*** 獲取右子樹的size*/int nr = this.size(root.rightChild);/*** 返回的是誰,* 返回的是nl+nr+1* 返回左子樹右子樹size只和再加1*/return nl+nr+1; }}/*** 二叉樹的高度*/@Overridepublic int getHeight() {/*** 我們在這里輸出一句話來*/System.out.println("二叉樹的高度是: ");/*** return這個值,* 這個值怎么辦,和剛才一樣提供一個輔助的方法*/return this.getHeight(root);}/*** 提供一個輔助的方法* 這邊傳入一個Node root* @param root* @return*/private int getHeight(Node root) {/*** 首先是有前提條件的,root不能等于null* 如果root不等于null我們就做這個事了*/if(root==null) { /*** 如果root等于null了* 那就return o唄* 遞歸要有一個結束條件*/return 0;}else {/*** 獲取左子樹的高度* * 得到一個值,* 這里是l不是1,*/int nl = this.getHeight(root.leftChild);/*** 獲取右子樹的高度*/int nr = this.getHeight(root.rightChild);/*** 返回誰,返回左子樹,右子樹較大高度并加1* * 最后返回誰* 如果nl大于nr就返回nl加1* 如果nl小于nr就返回nr加1* 你看又是遞歸,也不怎么復雜*/return nl>nr ? nl+1 : nr+1; }}@Overridepublic Node findKey(int value) {return null;}/*** 先序 遍歷分幾步,分三步*/@Overridepublic void preOrderTraverse() {/*** 輸出根節(jié)點的值* 我們只要value的值1,* 這樣1就出來了* 這是有條件的,如果root要是等于空呢,* 空節(jié)點你就別輸出了,這也算遞歸的一個結構條件* * 我們只要簡單的變一下就可以了,把這里的ln去了*/if(root!=null) { System.out.print(root.value + " ");/*** 對左子樹進行先序遍歷* 左邊玩不了就不會走右邊* * 對做子樹進行遍歷怎么辦* 這跟左也沒有關系啊,* * 如果root不等于null,創(chuàng)建做子樹* */if(root.leftChild!=null) {/*** 創(chuàng)建左子樹,左子樹本來就是存在的* 對做子樹進行先序遍歷* 構建一個二叉樹,根是左子樹的根* 拿著root.leftChild做根*/BinaryTree leftTree = new LinkedBinaryTree(root.leftChild);/*** 拿著左子樹,4做根,* 這是一顆二叉樹了,對它進行遍歷* 對root.leftChild進行遍歷* 對左子樹進行先序遍歷*/leftTree.preOrderTraverse();}/*** 對右子樹進行先序遍歷* 只要這三步就可以* * preOrderTraverse這跟右子樹也沒有關系,* 什么左子樹什么右子樹,this是當前這棵樹* 他找的是當前這棵樹,當前這棵樹是誰啊,* 就是btree,你這么來做的話可能會死循環(huán)了,* * 但是你這么寫的話代碼有點繁瑣,條件都是一樣的,*/if(root.rightChild!=null) {BinaryTree rightTree = new LinkedBinaryTree(root.rightChild);rightTree.preOrderTraverse();}}}/*** 這里面怎么辦,*/@Overridepublic void inOrderTraverse() {/*** 再調(diào)用一個方法,不管別的我先輸出一個中序遍歷*/System.out.println("中序遍歷");/*** 第一次調(diào)用的時候是不是需要把整個二叉樹的根傳進去* 是不是有參數(shù)的,它是對整個樹進行二叉遍歷的*/this.inOrderTraverse(root);/*** 輸出換行*/System.out.println();}/*** 我們拿過來復制一下,這個方法是輔助的* 可以不對外開發(fā),直接寫成private* 傳一個Node root* 這個是不是有根啊* * 我再提供一個輔助的方法,還要傳參* 開發(fā)者考慮這些就可以了,然后再遞歸調(diào)用* 說來說去還要看結果的運行,* 別到時運行結果是錯的那就不好了*/private void inOrderTraverse(Node root) {/*** 再調(diào)用一個方法* 如果root不等于null做三件事* * 三條語句加一個判斷,就可以了* 是不是都用到了遞歸,我們體會到遞歸的強大之處*/if(root!=null) { /*** 遍歷左子樹* 怎么遍歷左子樹,這里面本來就有參數(shù)* * 你知道你調(diào)用inOrderTraverse(root.leftChild)* 這句話意味著什么嗎,剛開始root傳的是誰,傳的是1,* 下一份傳的是誰啊,相當于拿著4作為根了去遍歷一下* 遞歸要用了,調(diào)了好多次了,到了葉子的時候還要調(diào),當我你們拿到7做根的時候* 拿到node7做根了,如果我拿到node7做根,傳了node7葉子節(jié)點* node7不等于空,所以對他的左子樹進行遍歷,左子樹這個時候已經(jīng)是null了* */if(root.leftChild!=null) { this.inOrderTraverse(root.leftChild);}/*** 輸出根的值* 輸出他的值,他的值是7*/System.out.print(root.value + " ");/*** 遍歷右子樹,右子樹也是null了,*/if(root.rightChild!=null) {this.inOrderTraverse(root.rightChild);}}}@Overridepublic void postOrderTraverse() {/*** 輸出一下后序遍歷*/System.out.println("后序遍歷");/*** 第一次調(diào)用是root的根*/this.postOrderTraverse(root);/*** 輸出玩之后再來一個換行*/System.out.println();}/*** 我們再提供一個輔助的方法,這個輔助方法可以不對外面的調(diào)用者開發(fā)* 這里面要傳一個參數(shù),但是這個root是誰不確定,這個方法本來就有了* 有了我就直接用它了*/@Overridepublic void postOrderTraverse(Node node) {/*** 如果node等于null,* * 這里不是root了,而是node了,*/if(node!=null) {/*** 后序遍歷該怎么辦* 遍歷左子樹*/if(node.leftChild!=null) {/*** 左孩子當做一個棵樹來遍歷*/this.postOrderTraverse(node.leftChild);}/*** 遍歷右子樹*/if(node.rightChild!=null) {this.postOrderTraverse(node.rightChild);}/*** 輸出根的值* 先寫這一個* 不加ln,加個空格*/System.out.print(node.value + " "); }}@Overridepublic void inOrderByStack() {}@Overridepublic void preOrderByStack() {}@Overridepublic void postOrderByStack() {}@Overridepublic void levelOrderByStack() {}}
package com.learn.btree;/*** 在這個測試類里面我們要干什么,* 這是一個測試類,我們按照這些功能依次來實現(xiàn)* @author Leon.Sun**/
public class Test {public static void main(String[] args) {/*** 你想進行遍歷,我想遍歷一下這個數(shù)* 我想看看這個數(shù)一共有幾層,前提是創(chuàng)建一個二叉樹* 怎么來創(chuàng)建一個二叉樹呢,就把這個二叉樹創(chuàng)建起來,* 那該怎么辦呢,一個節(jié)點一個節(jié)點的創(chuàng)建出來,然后指明他們的關系不就可以了嗎* 從葉子開始吧,從5開始,Node5是不是有構造方法,告訴我他的值是多少* 值是5,左右都沒有,這是5了,*/Node node5 = new Node(5,null,null);/*** 再來創(chuàng)建一個4唄* 值是多少,值是4,左孩子沒有,右孩子是node5* 是不是指向他啊,這么久成了*/Node node4 = new Node(4,null,node5);/*** node3也是葉子節(jié)點*/Node node3 = new Node(3,null,null);/*** 下面從7開始吧* 7是葉子節(jié)點,那左右都是null* 值是7*/
// Node node7 = new Node(7,null,null);/*** node6,值是6,左孩子沒有,右孩子是node7*/
// Node node6 = new Node(6,null,node7);/*** node6就變成葉子了*/Node node6 = new Node(6,null,null);/*** 2還沒有呢,怎么辦,* node2值是2,左是node3,右是node6*/Node node2 = new Node(2,node3,node6);/*** 最后還差一個node1,值是1* 左邊指向的是node4,右邊指向的是node2* 我們相當于把一棵樹給搭建好了* 但是搭建好了之后和LinkedBinargyTree沒有一點關系* 好像只是把這些節(jié)點按照一定的規(guī)則排到一起了,你下邊還要做一件事* 這棵樹你得知道根是誰,只要我們能夠找到根,基本上就可以找到別的節(jié)點*/Node node1 = new Node(1,node4,node2);/*** 怎么把我們搭建的一大堆變成一棵樹呢,跟我們的類發(fā)生關聯(lián)* BinaryTree接口,把node1傳進去* 這么一棵樹就搭建好了,這個也太沒有技術含量了吧* 如果有100個節(jié)點的話,我們要加100棵樹嗎,* 因為我們這棵樹是沒有特點的,他沒有說左邊的小右邊的大* 值是不是沒有規(guī)律的,比如我們學過集合了,是不是學過TreeSet,* 人家里面的樹都是有序的,左邊的永遠小于根,根永遠小于右邊的,* 人家都是遞歸定義的,這種情況下你隨便給個值,不需要我們拼接這個數(shù)* 這個大家知道,*/BinaryTree btree = new LinkedBinaryTree(node1);/*** 比如我們把這個語句復制一份,我這里沒有傳這個根過去* 是不是空的二叉樹一個節(jié)點也沒有,他就是一顆空數(shù)組* 二叉樹我們已經(jīng)實現(xiàn)兩個操作了,創(chuàng)建二叉樹沒有多大含量* * 我們試一個特殊的情況,這什么意思啊* 創(chuàng)建了一個二叉樹,他是一個空的* 那他的節(jié)點數(shù)量是0,所以我們有時候?qū)懘a的時候要健壯* 某些邊界值一定要考慮到,看我們的代碼是不是完善* 這是0的,*/
// BinaryTree btree = new LinkedBinaryTree();/*** 判斷二叉樹是否為空,這個簡單* 判斷二叉樹是否為空這個怎么辦,輸出一下唄*/System.out.println(btree.isEmpty());System.out.println("先序遍歷:");/*** 先序遍歷遞歸* 什么叫先序遍歷,preOrderTraverse這個就是先序遍歷* 先序遍歷的結果是多少,1452367* * 但是還是不滿意,main方法是調(diào)用者來寫的,* 能不能我就調(diào)用一個方法,你把所有的事情都給我做了* 這是增加測試者的負擔,還要創(chuàng)建一個左子樹和右子樹,* 分別進行遍歷,我們針對這個做一些改進,*/btree.preOrderTraverse();System.out.println();System.out.println("中序遍歷:");/*** 中序遍歷遞歸* 中序遍歷的結果是這個:4513267* 結果必須對,中序遍歷你只需要做一件事* 這一句話就夠了,有人說你這一句話不太對* 因為你這里也沒有傳任何值* * 外層不需要傳任何的參數(shù),調(diào)這個方法就可以了,* 所有的細節(jié)在這里都可以搞定,*/btree.inOrderTraverse();/*** 后序遍歷遞歸* 后序遍歷:5437621* * 到這里我們就把先序中序后序遍歷都給寫出來了* 剛開始怎么辦,剛開始我們寫了一個比較復雜的,* */btree.postOrderTraverse();/*** 中序遍歷非遞歸* 中序遍歷如果采用非遞歸的遍歷* 需要借助棧* * 我們再實現(xiàn)一個功能,這個非遞歸的我們先等一等吧* 我們先看一下別的*//*** 按照層次遍歷,借助隊列* 先把這些層次記住*//*** 在二叉樹中查找某個值*//*** 二叉樹的高度,他總共有幾層* * 二叉樹的高度是幾啊你覺得,* 我要得到這棵樹的高度,這個該怎么寫* 這棵樹的高度是4,4層,我怎么知道這棵樹的高度是4* 要用遞歸,這和遞歸有關系嗎,遞歸,樹的高度就這么來* 整棵樹的高度是4,我怎么知道是4,先看他左子樹的高度是幾* 目前是2,左子樹是兩層,是2,右子樹的高度是幾,是3,* 左子樹的高度是2,右子樹的高度是3,從里面選一個大的,是3* 別忘了,還有一個根呢,根是幾,根是1,3+1=4* 有人說你怎么知道右子樹是3,左子樹這個是1,這個高度是2* 左子樹是1,右子樹是2,兩個里面找一個大的是幾,是2* 再加上這個根加1,是不是等于3,這好像還是遞歸,* 你怎么知道67這棵樹的高度是2呢,因為左子樹是0,右子樹是1* 一個0一個1,1再加上這個根,2就是這么得到的,* 你怎么知道7的高度是1,因為他的左子樹是0,右子樹是0* 兩個最大的是0,再加上個根,等于1,遞歸* 首先大家要有這個思想,因為樹的定義本來就是遞歸的,* 所以解決問題往遞歸來想,如果這個能夠想清楚,代碼估計就差不多了* * 二叉樹的高度是4,是4吧,怎么不是4,把7去了就變成3* 我們把7去一下,那就變成3了,如果出來個3就差不多了* */System.out.println(btree.getHeight());/*** 二叉樹的節(jié)點數(shù)量* 把我們要實現(xiàn)二叉樹的框架,都給大家搭建出來了* * 返回二叉樹的節(jié)點數(shù)量,他用了多少個節(jié)點* 節(jié)點數(shù)量輸出一下,這里面我們有一個方法,* 我完全可以這么來寫* * 二叉樹的節(jié)點數(shù)是7個*/System.out.println(btree.size());}}
?
總結
以上是生活随笔為你收集整理的二叉树的遍历实现-1(三级)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二叉树的遍历算法(三级)
- 下一篇: 二叉树的遍历实现-2(三级)