劍指Offer的學習筆記(C#篇)-- 從上往下打印二叉樹

題目描述

從上往下打印出二叉樹的每一個節點,同層節點從左至右打印。

一 . 題目解析

        瞭解過二叉樹就應該知道,二叉樹存在三種遍歷方法:前序遍歷(根→左→右)、中序遍歷(左→根→右)、後續遍歷(左→右→根)。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;
    }
}
相關文章
相關標籤/搜索