瞭解過二叉樹就應該知道,二叉樹存在三種遍歷方法:前序遍歷(根→左→右)、中序遍歷(左→根→右)、後續遍歷(左→右→根)。node
自定義二叉樹:this
/// <summary> /// 二叉樹的節點定義 /// </summary> /// <typeparam name="T">數據具體類型</typeparam> public class Node<T> { public T data { get; set; } public Node<T> lchild { get; set; } public Node<T> rchild { get; set; } public Node() { } public Node(T data) { this.data = data; } public Node(T data, Node<T> lchild, Node<T> rchild) { this.data = data; this.lchild = lchild; this.rchild = rchild; } }
看一下三種遍歷的代碼實現:這裏涉及到雙遞歸的方法。spa
//該方法爲遞歸遍歷,僅闡述一下方法,目的在於搞清楚他們之間的邏輯關係。 // 前序遍歷 public void PreOrder(Node<T> node) { //根節點開始,不爲空的話,執行下面代碼。 if (node != null) { // 前序方向根->左->右 //輸出跟節點,往下走。 Console.Write(node.data + " "); //當左節點不爲空,返回遞歸。左節點爲空,往下走 PreOrder(node.lchild); //當左節點爲空,輸入右節點遞歸。 PreOrder(node.rchild); } } // 中序遍歷 public void MidOrder(Node<T> node) { if (node != null) { // 中序遍歷方向,左->根->右 // 輸入跟節點,左節點不爲空,一直往下走,當左節點爲空,輸出最下面的左節點 MidOrder(node.lchild); //輸出 Console.Write(node.data + " "); // 當每次輸出一個左節點,若是他有右節點,遞歸右節點 MidOrder(node.rchild); } } // 後序遍歷 public void PostOrder(Node<T> node) { if (node != null) { //後序遍歷,左->右->根 //一直遞歸左節點不輸出,直到最下面的左右節點都市空的,才輸出 PostOrder(node.lchild); PostOrder(node.rchild); //輸出 Console.Write(node.data + " "); } }
解釋一下雙遞歸:(遇到雙遞歸問題時,當第一個遞歸執行的時候,第二個遞歸併非不執行,而是先進棧,根據順序來,簡單明瞭的解釋就是,第一個遞歸你該怎麼走就怎麼走,徹底沒什麼能夠阻擋你,第二個遞歸就不一樣了,他是在第一個遞歸的基礎上執行的,但不是馬上執行,而是執行遞歸進棧,當第一個遞歸徹底執行技術的時候,第二個遞歸出棧,開始慢慢執行!)code
具體解釋:blog
如上圖所示,二叉樹的基本遍歷方法中並不存在題目要求的方法,所以,必須自定義一種方法實現要求。遞歸
通過思考,得出以下步驟:get
(1)定義兩個鏈表,一個做爲寄存鏈表,一個用做與最後輸出的鏈表。it
(2)若根節點不爲空,把根節點存在寄存鏈表裏。io
(3)接下來,把他放到最後輸出的鏈表裏,以後呢,若是這個節點還有左右子節點的話,把左右子節點依次存在寄存鏈表裏面。class
(4)執行(3)循環,當循環執行次數大於或者等於寄存鏈表的長度時,中止執行(由於每執行一次循環,就至關於把寄存鏈表裏的數字存到輸出鏈表裏,當全搞定,天然中止。)
using System.Collections.Generic; /* public class TreeNode { public int val; public TreeNode left; public TreeNode right; public TreeNode (int x) { val = x; } }*/ class Solution { public List<int> PrintFromTopToBottom(TreeNode root) { // write code here //定義輸出鏈表List1和寄存鏈表List2 List<int> List1 = new List<int>(); List<TreeNode> List2 = new List<TreeNode>(); int i = 0; //根節點的添加方法 if (root != null) { List2.Add(root); } //(3)循環 while (i < List2.Count) { //定義一個節點Node1等於寄存鏈表中的第i個數 TreeNode Node1 = List2[i]; //給輸出鏈表添加數據 List1.Add(Node1.val); //左右子節點排隊進入鏈表List2 if (Node1.left != null) { List2.Add(Node1.left); } if (Node1.right != null) { List2.Add(Node1.right); } //i的執行次數應等於二叉樹節點數 i++; } return List1; } }