Java中關(guān)于二叉樹層序遍歷深入了解
前言
大家好,我是bigsai,在數(shù)據(jù)結(jié)構(gòu)與算法中,二叉樹無論是考研、筆試都是非常高頻的考點(diǎn)內(nèi)容,在二叉樹中,二叉樹的遍歷又是非常重要的知識點(diǎn),今天給大家講講二叉樹的層序遍歷。
這部分很多人可能會但是需要注重一下細(xì)節(jié)。
前面介紹了二叉排序樹的構(gòu)造和基本方法的實(shí)現(xiàn),遍歷也是比較重要的一環(huán),并且二叉樹的層序遍歷也是bfs的最簡單情況,這里我就將二叉樹的層序遍歷以及??紗栴}給大家分享一下。
在了解二叉樹的遍歷之前,需要具備數(shù)據(jù)結(jié)構(gòu)與算法有隊(duì)列、遞歸、棧、二叉樹,這些內(nèi)容咱們前面都有講過,有這方面知識欠缺的同學(xué)可以往前翻一翻看一看!
層序遍歷
層序遍歷,聽名字也知道是按層遍歷。一個節(jié)點(diǎn)有左右節(jié)點(diǎn),按層處理就是當(dāng)前層兄弟節(jié)點(diǎn)的優(yōu)先級要大于子節(jié)點(diǎn)處理的優(yōu)先級,所以就是要將子節(jié)點(diǎn)放到后面處理,這就適合隊(duì)列這個數(shù)據(jù)結(jié)構(gòu)用來存儲。
對于隊(duì)列,先進(jìn)先出。從root節(jié)點(diǎn)push到隊(duì)列,那么隊(duì)列中先出來的順序是第二層的左右(假設(shè)都有),第二層每個節(jié)點(diǎn)執(zhí)行的時候按照左右順序添加到隊(duì)列,第三層的節(jié)點(diǎn)就會有序的放到最后面……按照這樣的規(guī)則就能得到一個層序遍歷的順序。
實(shí)現(xiàn)的代碼也很容易理解:
public int[] levelOrder(TreeNode root) { int arr[]=new int[10000]; int index=0; Queue<TreeNode>queue=new ArrayDeque<>(); if(root!=null) queue.add(root); while (!queue.isEmpty()){ TreeNode node=queue.poll(); arr[index++]= node.val; if(node.left!=null) queue.add(node.left); if(node.right!=null) queue.add(node.right); } return Arrays.copyOf(arr,index); }
分層存儲
但是在具體筆試他可能要求你分層存儲,例如力扣的102二叉樹的層序遍歷,要求返回一個List<List<Integer>>
類型。
這種相比上面一個多了一層邏輯就是每一層數(shù)據(jù)放到一塊,這個也很容易,最好想到的就是兩個隊(duì)列(容器)一層一層遍歷存儲,然后交替,但是兩個隊(duì)列(容器)的寫法常常會被面試官嫌棄,很多面試官讓你想想怎么不用兩個容器實(shí)現(xiàn)?
不用雙隊(duì)列去枚舉結(jié)果也很容易,重要的就是先記錄隊(duì)列大小size(當(dāng)前層節(jié)點(diǎn)數(shù)量),然后執(zhí)行size次數(shù)的枚舉即可,具體代碼為:
public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>>list=new ArrayList<List<Integer>>(); if(root==null)return list; Queue<TreeNode>q1=new ArrayDeque<TreeNode>(); q1.add(root); while (!q1.isEmpty()) { int size=q1.size(); List<Integer>value=new ArrayList<Integer>(); for(int i=0;i<size;i++) { TreeNode pNode=q1.poll(); if(pNode.left!=null) q1.add(pNode.left); if(pNode.right!=null) q1.add(pNode.right); value.add(pNode.val); } list.add(value); } return list; }
之字形打印
除了這個直接層序遍歷,二叉樹還有很高頻的就是之字形遍歷,例如劍指offer32和力扣103 二叉樹的鋸齒形層序遍歷,它的題目要求為:
請實(shí)現(xiàn)一個函數(shù)按照之字形順序打印二叉樹,即第一行按照從左到右的順序打印,第二層按照從右到左的順序打印,第三行再按照從左到右的順序打印,其他行以此類推。
這道題雖然不是難題,但是有點(diǎn)繞,本來隊(duì)列這玩意我們就要大腦想一下什么順序,又出來一個之字形,屬實(shí)增加的思維邏輯,有不少小伙伴反映當(dāng)時面試官讓手撕這道題,自己以前明明寫過,但是太緊張自己給自己繞進(jìn)去了!
其實(shí)這個問題也很容易轉(zhuǎn)化,因?yàn)橹抵皇谴鎯?,我們按照老樣子去進(jìn)行層序遍歷,只不過在遍歷時候通過當(dāng)前層奇偶數(shù)來給它判斷是從左往右存儲到結(jié)果中還是從右往左放到結(jié)果中。當(dāng)然,判斷奇數(shù)偶數(shù)也很容易,可以用變量,也可以用結(jié)果List的size()都可。
個人實(shí)現(xiàn)的一個樸素代碼為:
public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> value=new ArrayList<>();//存儲到的最終結(jié)果 if(root==null) return value; int index=0;//判斷 Queue<TreeNode>queue=new ArrayDeque<>(); queue.add(root); while (!queue.isEmpty()){ List<Integer>va=new ArrayList<>();//臨時 用于存儲到value中 int len=queue.size();//當(dāng)前層的數(shù)量 for(int i=0;i<len;i++){ TreeNode node=queue.poll(); if(index%2==0) va.add(node.val); else va.add(0,node.val); if(node.left!=null) queue.add(node.left); if(node.right!=null) queue.add(node.right); } value.add(va); index++; } return value; }
上面實(shí)現(xiàn)代碼也僅使用一個隊(duì)列,不過這個問題可能有很多更巧妙的解法需要大家自己去挖掘。
結(jié)語
二叉樹的層序遍歷是二叉樹內(nèi)容中較為簡單的內(nèi)容,但是層序遍歷尤其是之字形遍歷(鋸齒形遍歷)出現(xiàn)的頻率真的太高了,并且最好是掌握比較好的方法不要顯得太臃腫。
不過在實(shí)際遇到問題時候,能AC是第一位,然后才是精簡的邏輯和騷氣的代碼。
二叉樹層序遍歷變種問題不多,掌握上面三個問題基本就夠了,而二叉樹的前序、中序、后序遍歷(遞歸非遞歸)考察非常多,后面會給大家加快梳理總結(jié),敬請期待!
到此這篇關(guān)于Java中關(guān)于二叉樹層序遍歷深入了解的文章就介紹到這了,更多相關(guān)Java 二叉樹層序遍歷內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring boot整合RabbitMQ實(shí)例詳解(Fanout模式)
這篇文章主要介紹了spring boot整合RabbitMQ的實(shí)例講解(Fanout模式),非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-04-04詳解在Spring Boot框架下使用WebSocket實(shí)現(xiàn)消息推送
這篇文章主要介紹了詳解在Spring Boot框架下使用WebSocket實(shí)現(xiàn)消息推送,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2016-12-12MyBatis-plus+達(dá)夢數(shù)據(jù)庫實(shí)現(xiàn)自動生成代碼的示例
這篇文章主要介紹了MyBatis-plus+達(dá)夢數(shù)據(jù)庫實(shí)現(xiàn)自動生成代碼的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08Java數(shù)據(jù)結(jié)構(gòu)之?dāng)?shù)組(動力節(jié)點(diǎn)之Java學(xué)院整理)
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)之?dāng)?shù)組(動力節(jié)點(diǎn)之Java學(xué)院整理)的相關(guān)資料,包括創(chuàng)建和內(nèi)存分配,數(shù)組封裝后的使用等,需要的朋友參考下吧2017-04-04spring cloud gateway集成hystrix實(shí)戰(zhàn)篇
這篇文章主要介紹了spring cloud gateway集成hystrix實(shí)戰(zhàn),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07詳解Java中ByteArray字節(jié)數(shù)組的輸入輸出流的用法
ByteArrayInputStream和ByteArrayOutputStream分別集成自InputStream和OutputStream這兩個輸入和輸出流,這里我們就來詳解Java中ByteArray字節(jié)數(shù)組的輸入輸出流的用法,需要的朋友可以參考下2016-06-06SpringMVC攔截器實(shí)現(xiàn)登錄認(rèn)證
這篇文章主要介紹了SpringMVC攔截器實(shí)現(xiàn)登錄認(rèn)證的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-11-11java使用POI實(shí)現(xiàn)html和word相互轉(zhuǎn)換
這篇文章主要為大家詳細(xì)介紹了java使用POI實(shí)現(xiàn)html和word的相互轉(zhuǎn)換,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12