java實(shí)現(xiàn)二叉樹的創(chuàng)建及5種遍歷方法(總結(jié))
用java實(shí)現(xiàn)的數(shù)組創(chuàng)建二叉樹以及遞歸先序遍歷,遞歸中序遍歷,遞歸后序遍歷,非遞歸前序遍歷,非遞歸中序遍歷,非遞歸后序遍歷,深度優(yōu)先遍歷,廣度優(yōu)先遍歷8種遍歷方式:
package myTest;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
public class myClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
myClass tree = new myClass();
int[] datas = new int[]{1,2,3,4,5,6,7,8,9};
List<Node> nodelist = new LinkedList<>();
tree.creatBinaryTree(datas, nodelist);
Node root = nodelist.get(0);
System.out.println("遞歸先序遍歷:");
tree.preOrderTraversal(root);
System.out.println();
System.out.println("非遞歸先序遍歷:");
tree.preOrderTraversalbyLoop(root);
System.out.println();
System.out.println("遞歸中序遍歷:");
tree.inOrderTraversal(root);
System.out.println();
System.out.println("非遞歸中序遍歷:");
tree.inOrderTraversalbyLoop(root);
System.out.println();
System.out.println("遞歸后序遍歷:");
tree.postOrderTraversal(root);
System.out.println();
System.out.println("非遞歸后序遍歷:");
tree.postOrderTraversalbyLoop(root);
System.out.println();
System.out.println("廣度優(yōu)先遍歷:");
tree.bfs(root);
System.out.println();
System.out.println("深度優(yōu)先遍歷:");
List<List<Integer>> rst = new ArrayList<>();
List<Integer> list = new ArrayList<>();
tree.dfs(root,rst,list);
System.out.println(rst);
}
/**
*
* @param datas 實(shí)現(xiàn)二叉樹各節(jié)點(diǎn)值的數(shù)組
* @param nodelist 二叉樹list
*/
private void creatBinaryTree(int[] datas,List<Node> nodelist){
//將數(shù)組變成node節(jié)點(diǎn)
for(int nodeindex=0;nodeindex<datas.length;nodeindex++){
Node node = new Node(datas[nodeindex]);
nodelist.add(node);
}
//給所有父節(jié)點(diǎn)設(shè)定子節(jié)點(diǎn)
for(int index=0;index<nodelist.size()/2-1;index++){
//編號(hào)為n的節(jié)點(diǎn)他的左子節(jié)點(diǎn)編號(hào)為2*n 右子節(jié)點(diǎn)編號(hào)為2*n+1 但是因?yàn)閘ist從0開始編號(hào),所以還要+1
//這里父節(jié)點(diǎn)有1(2,3),2(4,5),3(6,7),4(8,9) 但是最后一個(gè)父節(jié)點(diǎn)有可能沒有右子節(jié)點(diǎn) 需要單獨(dú)處理
nodelist.get(index).setLeft(nodelist.get(index*2+1));
nodelist.get(index).setRight(nodelist.get(index*2+2));
}
//單獨(dú)處理最后一個(gè)父節(jié)點(diǎn) 因?yàn)樗锌赡軟]有右子節(jié)點(diǎn)
int index = nodelist.size()/2-1;
nodelist.get(index).setLeft(nodelist.get(index*2+1)); //先設(shè)置左子節(jié)點(diǎn)
if(nodelist.size() % 2 == 1){ //如果有奇數(shù)個(gè)節(jié)點(diǎn),最后一個(gè)父節(jié)點(diǎn)才有右子節(jié)點(diǎn)
nodelist.get(index).setRight(nodelist.get(index*2+2));
}
}
/**
* 遍歷當(dāng)前節(jié)點(diǎn)的值
* @param nodelist
* @param node
*/
public void checkCurrentNode(Node node){
System.out.print(node.getVar()+" ");
}
/**
* 先序遍歷二叉樹
* @param root 二叉樹根節(jié)點(diǎn)
*/
public void preOrderTraversal(Node node){
if (node == null) //很重要,必須加上 當(dāng)遇到葉子節(jié)點(diǎn)用來停止向下遍歷
return;
checkCurrentNode(node);
preOrderTraversal(node.getLeft());
preOrderTraversal(node.getRight());
}
/**
* 中序遍歷二叉樹
* @param root 根節(jié)點(diǎn)
*/
public void inOrderTraversal(Node node){
if (node == null) //很重要,必須加上
return;
inOrderTraversal(node.getLeft());
checkCurrentNode(node);
inOrderTraversal(node.getRight());
}
/**
* 后序遍歷二叉樹
* @param root 根節(jié)點(diǎn)
*/
public void postOrderTraversal(Node node){
if (node == null) //很重要,必須加上
return;
postOrderTraversal(node.getLeft());
postOrderTraversal(node.getRight());
checkCurrentNode(node);
}
/**
* 非遞歸前序遍歷
* @param node
*/
public void preOrderTraversalbyLoop(Node node){
Stack<Node> stack = new Stack();
Node p = node;
while(p!=null || !stack.isEmpty()){
while(p!=null){ //當(dāng)p不為空時(shí),就讀取p的值,并不斷更新p為其左子節(jié)點(diǎn),即不斷讀取左子節(jié)點(diǎn)
checkCurrentNode(p);
stack.push(p); //將p入棧
p = p.getLeft();
}
if(!stack.isEmpty()){
p = stack.pop();
p = p.getRight();
}
}
}
/**
* 非遞歸中序遍歷
* @param node
*/
public void inOrderTraversalbyLoop(Node node){
Stack<Node> stack = new Stack();
Node p = node;
while(p!=null || !stack.isEmpty()){
while(p!=null){
stack.push(p);
p = p.getLeft();
}
if(!stack.isEmpty()){
p = stack.pop();
checkCurrentNode(p);
p = p.getRight();
}
}
}
/**
* 非遞歸后序遍歷
* @param node
*/
public void postOrderTraversalbyLoop(Node node){
Stack<Node> stack = new Stack<>();
Node p = node,prev = node;
while(p!=null || !stack.isEmpty()){
while(p!=null){
stack.push(p);
p = p.getLeft();
}
if(!stack.isEmpty()){
Node temp = stack.peek().getRight();
if(temp == null||temp == prev){
p = stack.pop();
checkCurrentNode(p);
prev = p;
p = null;
}else{
p = temp;
}
}
}
}
/**
* 廣度優(yōu)先遍歷(從上到下遍歷二叉樹)
* @param root
*/
public void bfs(Node root){
if(root == null) return;
LinkedList<Node> queue = new LinkedList<Node>();
queue.offer(root); //首先將根節(jié)點(diǎn)存入隊(duì)列
//當(dāng)隊(duì)列里有值時(shí),每次取出隊(duì)首的node打印,打印之后判斷node是否有子節(jié)點(diǎn),若有,則將子節(jié)點(diǎn)加入隊(duì)列
while(queue.size() > 0){
Node node = queue.peek();
queue.poll(); //取出隊(duì)首元素并打印
System.out.print(node.var+" ");
if(node.left != null){ //如果有左子節(jié)點(diǎn),則將其存入隊(duì)列
queue.offer(node.left);
}
if(node.right != null){ //如果有右子節(jié)點(diǎn),則將其存入隊(duì)列
queue.offer(node.right);
}
}
}
/**
* 深度優(yōu)先遍歷
* @param node
* @param rst
* @param list
*/
public void dfs(Node node,List<List<Integer>> rst,List<Integer> list){
if(node == null) return;
if(node.left == null && node.right == null){
list.add(node.var);
/* 這里將list存入rst中時(shí),不能直接將list存入,而是通過新建一個(gè)list來實(shí)現(xiàn),
* 因?yàn)槿绻苯佑胠ist的話,后面remove的時(shí)候也會(huì)將其最后一個(gè)存的節(jié)點(diǎn)刪掉*/
rst.add(new ArrayList<>(list));
list.remove(list.size()-1);
}
list.add(node.var);
dfs(node.left,rst,list);
dfs(node.right,rst,list);
list.remove(list.size()-1);
}
/**
* 節(jié)點(diǎn)類
* var 節(jié)點(diǎn)值
* left 節(jié)點(diǎn)左子節(jié)點(diǎn)
* right 右子節(jié)點(diǎn)
*/
class Node{
int var;
Node left;
Node right;
public Node(int var){
this.var = var;
this.left = null;
this.right = null;
}
public void setLeft(Node left) {
this.left = left;
}
public void setRight(Node right) {
this.right = right;
}
public int getVar() {
return var;
}
public void setVar(int var) {
this.var = var;
}
public Node getLeft() {
return left;
}
public Node getRight() {
return right;
}
}
}
運(yùn)行結(jié)果:
遞歸先序遍歷:
1 2 4 8 9 5 3 6 7
非遞歸先序遍歷:
1 2 4 8 9 5 3 6 7
遞歸中序遍歷:
8 4 9 2 5 1 6 3 7
非遞歸中序遍歷:
8 4 9 2 5 1 6 3 7
遞歸后序遍歷:
8 9 4 5 2 6 7 3 1
非遞歸后序遍歷:
8 9 4 5 2 6 7 3 1
廣度優(yōu)先遍歷:
1 2 3 4 5 6 7 8 9
深度優(yōu)先遍歷:
[[1, 2, 4, 8], [1, 2, 4, 9], [1, 2, 5], [1, 3, 6], [1, 3, 7]]
以上這篇java實(shí)現(xiàn)二叉樹的創(chuàng)建及5種遍歷方法(總結(jié))就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot Security安裝配置及Thymeleaf整合
這篇文章主要介紹了SpringBoot Security安裝配置及Thymeleaf整合,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12
SpringCloud?Gateway?DispatcherHandler調(diào)用方法詳細(xì)介紹
我們第一個(gè)關(guān)注的類就是DispatcherHandler,這個(gè)類提供的handle()方法,封裝了我們之后所有的handlerMappings,這個(gè)DispatcherHandler有點(diǎn)想SpringMVC的DispatchServlet,里面也是封裝了請求和對(duì)應(yīng)的處理方法的關(guān)系2022-10-10
Java應(yīng)用啟動(dòng)停止重啟Shell腳本模板server.sh
這篇文章主要為大家介紹了Java應(yīng)用啟動(dòng)、停止、重啟Shell腳本模板server.sh,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
Java判斷List中相同值元素的個(gè)數(shù)實(shí)例
今天小編就為大家分享一篇Java判斷List中相同值元素的個(gè)數(shù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-07-07
IDEA創(chuàng)建Maven項(xiàng)目一直顯示正在加載的問題及解決
這篇文章主要介紹了IDEA創(chuàng)建Maven項(xiàng)目一直顯示正在加載的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
mybatis中使用InsertProvider注解報(bào)錯(cuò)解決全過程
這篇文章主要介紹了mybatis中使用InsertProvider注解報(bào)錯(cuò)解決全過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
springBoot?啟動(dòng)指定配置文件環(huán)境多種方案(最新推薦)
springBoot?啟動(dòng)指定配置文件環(huán)境理論上是有多種方案的,一般都是結(jié)合我們的實(shí)際業(yè)務(wù)選擇不同的方案,比如,有pom.xml文件指定、maven命令行指定、配置文件指定、啟動(dòng)jar包時(shí)指定等方案,今天我們一一分享一下,需要的朋友可以參考下2023-09-09

