1. 程式人生 > >按之字形順序打印二叉樹

按之字形順序打印二叉樹

public 控制 num return res class imp comment 記得

http://blog.csdn.net/qq_27703417/article/details/70977347

請實現一個函數按照之字形打印二叉樹,即第一行按照從左到右的順序打印,第二層按照從右至左的順序打印,第三行按照從左到右的順序打印,其他行以此類推

第一行的時候,控制的是第二行的打印順序,第二行的時候,控制的是第三行的打印順序

奇數行從左到右壓入棧,所以下一行按逆序打印

偶數行從右到左壓入棧,所以下一行按正序打印

創建2個棧stack1和stack2,先將root結點壓入到stack1中,然後開始循環過程:從stack1中彈出root,每次彈出一個結點時要判斷它的左右子節點是否是null,如果不為null就壓入到另一個棧stack2中,即這裏彈出結點的棧和壓入子節點的棧應該是分開的2個棧,從stack1中彈出的結點它的子節點要壓入到另一個棧stack2中,當stack1中的結點彈光後,先判斷stack2裏面的元素是否為空,如果stack2中的結點數目也為0,那麽說明在stack1彈出結點的時候沒有再壓入子節點到stack2中,說明此時已經沒有下一層了,於是遍歷結束,即遍歷循環結束的判斷條件是:stack1.isEmpty()並且stack2.isEmpty()。Stack1彈完後這一層就遍歷結束了,它的下一層的結點都在stack2中了,為了便於循環中的操作,將stack2賦值給stack1,將stack2重新創建,這樣就始終只要對stack1進行彈出,對stack2進行壓入操作了,在循環代碼中的實現較為簡單。即基本操作過程就是從stack1中彈出結點,並將結點的子節點放入到另一個棧stack2中,當stack1遍歷結束後就將stack2賦值給stack1,並將stack2重建,直到stack1和stack2都變空為止。需要註意的是:對於每一層,要求打印的順序是不同的,對於奇數層,要求從左到右遍歷結點,對於偶數層要求從右到左遍歷結點,如何實現?對於偶數層,例如②③,在彈出時是先彈出③再彈出②,此時為了使得它的下一層能夠從左到右輸出,應該使得對於彈出的結點,先將其右孩子放入棧stack2,在將左孩子放入stack2,於是stack2中先後壓入⑦⑥⑤④,彈出時的順序就是④⑤⑥⑦;同理對於奇數層的結點,例如第三層,在遍歷時的順序是④⑤⑥⑦,它的下一層要求遍歷順序是15,14,13,12,11,⑩⑨⑧,於是在對④⑤⑥⑦的子節點壓入棧是應該先壓入左孩子再壓入右孩子,於是先後向stack2中壓入⑧⑨⑩11,12,13,14,15.總結來說,

對於奇數層的結點在彈出時,它的孩子壓入stack2的順序應該是從左到右,即先壓入左孩子再壓入右孩子;對於偶數層的結點在彈出時,它的孩子壓入stack2的順序應該是從右到左,即先壓入右孩子再壓入左孩子。這種交替需要在循環體中寫2中遍歷子孩子的代碼,並且記錄一個層數計數器levelCount,通對其的奇偶性判斷來決定使用哪一段代碼即可。

  1. import java.util.*;
  2. //之字形遍歷:使用2個棧,遍歷先壓入左結點再壓入右結點和先右結點再左結點交替進行;自動換行,不用last和nlast
  3. public class Solution {
  4. //創建結果集,成員變量
  5. ArrayList<ArrayList<Integer>> results;
  6. public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
  7. results=new ArrayList<ArrayList<Integer>>();
  8. //特殊輸入
  9. if(pRoot==null) return results;
  10. //調用方法解決問題
  11. this.process(pRoot);
  12. //返回結果集
  13. return results;
  14. }
  15. //該方法用來之字形遍歷二叉樹,並將每層結果放入到results中
  16. private void process(TreeNode root){
  17. //①創建輔助棧
  18. Stack<TreeNode> stack1=new Stack<>();
  19. Stack<TreeNode> stack2=new Stack<>();
  20. //每一層的結果集
  21. ArrayList<Integer> list=new ArrayList<>();
  22. //第一變量記錄層數
  23. int levelCount=1;
  24. //②先將root壓入棧
  25. stack1.push(root);
  26. //③循環:彈棧遍歷--左右孩子入棧--交換stack1和stack2
  27. //只要stack1和stack2不全為空就可以繼續
  28. while(!(stack1.isEmpty()&&stack2.isEmpty())){
  29. //彈出並遍歷
  30. TreeNode temp=stack1.pop();
  31. list.add(temp.val);
  32. //左右孩子壓入stack2中
  33. if(levelCount%2!=0){
  34. //奇數層,先左再右
  35. if(temp.left!=null){
  36. stack2.push(temp.left);
  37. }
  38. if(temp.right!=null){
  39. stack2.push(temp.right);
  40. }
  41. }else{
  42. //偶數層,先右再左
  43. if(temp.right!=null){
  44. stack2.push(temp.right);
  45. }
  46. if(temp.left!=null){
  47. stack2.push(temp.left);
  48. }
  49. }
  50. //判斷此時stack1是否為空,即本層是否遍歷完成
  51. if(stack1.isEmpty()){
  52. //本層遍歷完成:換list,換stack1和stack2;層數加1
  53. results.add(list);
  54. list=new ArrayList<Integer>();
  55. stack1=stack2;
  56. stack2=new Stack<TreeNode>();
  57. //千萬記得層數+1
  58. levelCount++;
  59. }
  60. }
  61. }
  62. }

按之字形順序打印二叉樹