java實(shí)現(xiàn)二叉樹(shù)的創(chuàng)建及5種遍歷方法(總結(jié))
用java實(shí)現(xiàn)的數(shù)組創(chuàng)建二叉樹(shù)以及遞歸先序遍歷,遞歸中序遍歷,遞歸后序遍歷,非遞歸前序遍歷,非遞歸中序遍歷,非遞歸后序遍歷,深度優(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)二叉樹(shù)各節(jié)點(diǎn)值的數(shù)組 * @param nodelist 二叉樹(shù)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開(kāi)始編號(hào),所以還要+1 //這里父節(jié)點(diǎn)有1(2,3),2(4,5),3(6,7),4(8,9) 但是最后一個(gè)父節(jié)點(diǎn)有可能沒(méi)有右子節(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)樗锌赡軟](méi)有右子節(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()+" "); } /** * 先序遍歷二叉樹(shù) * @param root 二叉樹(shù)根節(jié)點(diǎn) */ public void preOrderTraversal(Node node){ if (node == null) //很重要,必須加上 當(dāng)遇到葉子節(jié)點(diǎn)用來(lái)停止向下遍歷 return; checkCurrentNode(node); preOrderTraversal(node.getLeft()); preOrderTraversal(node.getRight()); } /** * 中序遍歷二叉樹(shù) * @param root 根節(jié)點(diǎn) */ public void inOrderTraversal(Node node){ if (node == null) //很重要,必須加上 return; inOrderTraversal(node.getLeft()); checkCurrentNode(node); inOrderTraversal(node.getRight()); } /** * 后序遍歷二叉樹(shù) * @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)先遍歷(從上到下遍歷二叉樹(shù)) * @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存入,而是通過(guò)新建一個(gè)list來(lái)實(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)二叉樹(shù)的創(chuàng)建及5種遍歷方法(總結(jié))就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Java遞歸遍歷樹(shù)形結(jié)構(gòu)的實(shí)現(xiàn)代碼
- Java遍歷輸出指定目錄、樹(shù)形結(jié)構(gòu)所有文件包括子目錄下的文件
- 圖解二叉樹(shù)的三種遍歷方式及java實(shí)現(xiàn)代碼
- 圖解紅黑樹(shù)及Java進(jìn)行紅黑二叉樹(shù)遍歷的方法
- Java實(shí)現(xiàn)二叉樹(shù)的深度優(yōu)先遍歷和廣度優(yōu)先遍歷算法示例
- java實(shí)現(xiàn)遍歷樹(shù)形菜單兩種實(shí)現(xiàn)代碼分享
- Java二叉樹(shù)的四種遍歷方式詳解
- 簡(jiǎn)單談?wù)凧ava遍歷樹(shù)深度優(yōu)先和廣度優(yōu)先的操作方式
相關(guān)文章
SpringBoot Security安裝配置及Thymeleaf整合
這篇文章主要介紹了SpringBoot Security安裝配置及Thymeleaf整合,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12SpringCloud?Gateway?DispatcherHandler調(diào)用方法詳細(xì)介紹
我們第一個(gè)關(guān)注的類就是DispatcherHandler,這個(gè)類提供的handle()方法,封裝了我們之后所有的handlerMappings,這個(gè)DispatcherHandler有點(diǎn)想SpringMVC的DispatchServlet,里面也是封裝了請(qǐng)求和對(duì)應(yīng)的處理方法的關(guān)系2022-10-10Java應(yīng)用啟動(dòng)停止重啟Shell腳本模板server.sh
這篇文章主要為大家介紹了Java應(yīng)用啟動(dòng)、停止、重啟Shell腳本模板server.sh,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08Java判斷List中相同值元素的個(gè)數(shù)實(shí)例
今天小編就為大家分享一篇Java判斷List中相同值元素的個(gè)數(shù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07IDEA創(chuàng)建Maven項(xiàng)目一直顯示正在加載的問(wèn)題及解決
這篇文章主要介紹了IDEA創(chuàng)建Maven項(xiàng)目一直顯示正在加載的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12mybatis中使用InsertProvider注解報(bào)錯(cuò)解決全過(guò)程
這篇文章主要介紹了mybatis中使用InsertProvider注解報(bào)錯(cuò)解決全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07springBoot?啟動(dòng)指定配置文件環(huán)境多種方案(最新推薦)
springBoot?啟動(dòng)指定配置文件環(huán)境理論上是有多種方案的,一般都是結(jié)合我們的實(shí)際業(yè)務(wù)選擇不同的方案,比如,有pom.xml文件指定、maven命令行指定、配置文件指定、啟動(dòng)jar包時(shí)指定等方案,今天我們一一分享一下,需要的朋友可以參考下2023-09-09