C#樹的實現

MoMaek淺陌發表於2018-06-07

C#資料結構——樹的實現

樹的簡單說明:樹型結構是一類重要的非線性資料結構,其中以樹和二叉樹最為常用。直觀看來,樹是以分支關係定義的層次結構。樹結構在客觀世界中廣泛存在,如人類社會的族譜和各種社會組織機構都可以用樹來形象的表示。樹在計算機領域中也得到了廣泛的應用,如在編譯程式中,可以用樹來表示源程式的語法結構。又如在資料庫系統中,樹型結構也是資訊的重要組織形式之一。

關鍵技術

樹的抽象資料型別定義包含樹的結構定義和基本操作,下面分別進行介紹。
(1)結構定義
樹是n(n≥1)個節點的有限集,在任意一棵非空樹中,都應該符合以下條件:

  • 有且僅有一個特定的節點稱為根的節點;
  • 當n>1時,其餘節點可分為m個互不相交的有限集,其中每一個集合本身又是一棵樹,並且稱為根的子樹。

(2)基本操作
樹的基本操作主要包括:構造空樹、銷燬樹、清空樹、求樹的深度、訪問結點、插入子樹和刪除子樹等。

設計過程

(1)開啟Visual Studio 開發環境,新建一個類庫專案,命名為Arbor。
(2)將“Class1.cs”檔案重新命名為“Ctree.cs”。
(3)程式主要程式碼如下:

class TravelBinTree : ITravelBinTree, IInsertBinTree
{
    const int INIT_TREE_SIZE = 20;
    private IBinNode tree;
    private BinNodeLine head;    //線索化後的頭指標
    private IBinNode prenode;    //指向最近訪問過的前驅節點
    public TravelBinTree()
    {
        tree = new BinNodePtr();
    }
    public TravelBinTree(IBinNode INode)
    {
        tree = INode;
    }
    /// <summary>
    /// 先序遍歷樹,用非遞迴演算法實現
    /// </summary>
    /// <remarks>非遞迴實現</remarks>
    public void PreOrderTravel()
    {
        IBinNode temptree;
        Stack stk = new Stack(INIT_TREE_SIZE);
        if (tree == null)
            throw (new InvalidOperationException("訪問的樹為空"));
        temptree = tree;
        stk.Push(tree);
        while (stk.Count != 0)
        {
            while (temptree != null)
            {
                Print(temptree);
                stk.Push(temptree.Left);
                temptree = temptree.Left;
            }
            stk.Pop(); // 空指標退棧
            if (stk.Count != 0)
            {
                temptree = (IBinNode)stk.Pop();
                stk.Push(temptree.Right);
                temptree = temptree.Right;
            }
        }
    }
    public void InOrderTravel()
    {
        InOrderTravel(tree);
    }
    private void InOrderTravel(IBinNode t)
    {
        if (t == null) return;
        InOrderTravel(t.Left);
        Print(t);
        InOrderTravel(t.Right);
    }
    public void RevOrderTravel()
    {
        RevOrderTravel(tree);
    }
    private void RevOrderTravel(IBinNode t)
    {
        if (t == null) return;
        RevOrderTravel(t.Left);
        RevOrderTravel(t.Right);
        Print(t);
    }
    public void Print(IBinNode t)
    {
        Console.Write(t.Element + ",");
    }
    public void Insert(IBinNode node, Position pos)
    {
        if (node == null)
            throw (new InvalidOperationException("不能將空節點插入樹"));
        switch (pos)
        {
            case Position.LEFT: tree.Left = node; break;
            case Position.RIGHT: tree.Right = node; break;
        }
    }
    /// <summary>
    /// 按照先序遍歷順序遍歷樹
    /// </summary>
    public void TreeBuilder()
    {
        Stack stk = new Stack(INIT_TREE_SIZE);
        stk.Push(tree);
        Position pos;
        string para;
        pos = Position.LEFT;
        IBinNode baby, temp;
        while (true)
        {
            para = Console.ReadLine();
            if (para == "")
            {
                if (pos == Position.RIGHT)
                {
                    stk.Pop();
                    while (stk.Count != 0 && ((IBinNode)stk.Peek()).Right != null)
                        stk.Pop();
                    if (stk.Count == 0) break;
                }
                else
                    pos = Position.RIGHT;
            }
            else
            {
                // if (tree.GetType().Equals(baby) == true)
                baby = new BinNodePtr(para);
                temp = (IBinNode)stk.Peek();
                if (pos == Position.LEFT)
                    temp.Left = baby;
                else
                    temp.Right = baby;
                pos = Position.LEFT;
                stk.Push(baby);
            }
        }
    }
    /// <summary>
    /// 中序線索化
    /// </summary>
    public void InOrderThreading()
    {
        head = new BinNodeLine("");
        head.RTag = Tag.THREAD;
        head.Right = head;
        if (tree == null) head.Left = head;
        else
        {
            head.Left = tree; prenode = head;
        }
    }
    /// <summary>
    /// 中序線索化的遞迴實現
    /// </summary>
    /// <param name="t"></param>
    private void InThreading(IBinNode t)
    {
        if (t == null)
            return;
        else
        {
            InThreading(t.Left);
        }
    }
}

技巧與心得

樹在C#中使用TreeView控制元件來表示,TreeView控制元件,又稱為樹檢視控制元件,它可以為使用者顯示節點層次結構,而每個節點又可以包含子節點,包含子節點的節點叫父節點,其效果就像在Windows作業系統的Windows資源管理器功能的左視窗中顯示檔案和資料夾一樣。

相關文章