C# 數據結構 之 樹


樹(Tree)是n(n>=0)個相同類型的數據元素的有限集合。樹中的數據元素叫結點(Node)。n=0的樹稱為空樹(Empty Tree);對於n>0的任意非空樹T有:

1.有且只有一個特殊的結點稱為樹的根(Root)結點,根沒有前驅結點。

2.若n>1,則除根結點外,其余結點被分成了m(m>0)個互不相交的集合T1,T2,T3,...Tm,其中每個集合Ti(1<=i<=m)本身又是一棵樹。樹T1,T2,...Tm稱為這棵樹的子樹(Subtree)。

由樹的定義可知,樹的定義是遞歸的,用樹來定義樹,因此,樹的許多運算都使用過了遞歸。

樹的相關術語

結點(Node)。表示樹中的數據元素,由數據項和數據元素之間的關系組成。

結點的度。結點所擁有的子樹的個數。

樹的度。樹中各結點度的最大值。

葉子結點。度為0的結點,也叫終端結點。

其他術語參考二叉樹。

用多重鏈表表示法存儲樹

每個結點指針域的個數等於樹的度數。

Tree
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DataStructure
{

    public interface ITree<T>
    {
        T Root();                                //求樹的根結點
        T Parent(T t);                           //求結點t的雙親結點
        T Child(T t, int i);                     //求結點t的第i個子結點
        T RightSibling(T t);                     //求結點t第一個右邊兄弟結點
        bool Insert(T s, T t, int i);            //將樹s加入樹中作為結點t的第i顆子樹
        T Delete(T t, int i);                    //刪除結點t的第i顆子樹
        void Traverse(int TraverseType);         //按某種方式遍歷樹
        void Clear();                            //清空樹
        bool IsEmpty();                          //判斷是否為空
        int GetDepth(T t);                          //求樹的深度
    }


    /// <summary>
    /// 循環順序隊列
    /// </summary>
    /// <typeparam name="T"></typeparam>
    class CSeqQueue<T>
    {
        private int maxsize;       //循環順序隊列的容量
        private T[] data;          //數組,用於存儲循環順序隊列中的數據元素
        private int front;         //指示最近一個已經離開隊列的元素所占有的位置 循環順序隊列的對頭
        private int rear;          //指示最近一個進入隊列的元素的位置           循環順序隊列的隊尾

        public T this[int index]
        {
            get { return data[index]; }
            set { data[index] = value; }
        }

        //容量屬性
        public int Maxsize
        {
            get { return maxsize; }
            set { maxsize = value; }
        }

        //對頭指示器屬性
        public int Front
        {
            get { return front; }
            set { front = value; }
        }

        //隊尾指示器屬性
        public int Rear
        {
            get { return rear; }
            set { rear = value; }
        }

        public CSeqQueue()
        {

        }

        public CSeqQueue(int size)
        {
            data = new T[size];
            maxsize = size;
            front = rear = -1;
        }

        //判斷循環順序隊列是否為滿
        public bool IsFull()
        {
            if ((front == -1 && rear == maxsize - 1) || (rear + 1) % maxsize == front)
                return true;
            else
                return false;
        }

        //清空循環順序列表
        public void Clear()
        {
            front = rear = -1;
        }

        //判斷循環順序隊列是否為空
        public bool IsEmpty()
        {
            if (front == rear)
                return true;
            else
                return false;
        }

        //入隊操作
        public void EnQueue(T elem)
        {
            if (IsFull())
            {
                Console.WriteLine("Queue is Full !");
                return;
            }
            rear = (rear + 1) % maxsize;
            data[rear] = elem;
        }

        //出隊操作
        public T DeQueue()
        {
            if (IsEmpty())
            {
                Console.WriteLine("Queue is Empty !");
                return default(T);
            }
            front = (front + 1) % maxsize;
            return data[front];
        }

        //獲取對頭數據元素
        public T GetFront()
        {
            if (IsEmpty())
            {
                Console.WriteLine("Queue is Empty !");
                return default(T);
            }
            return data[(front + 1) % maxsize];//front從-1開始
        }

        //求循環順序隊列的長度
        public int GetLength()
        {
            return (rear - front + maxsize) % maxsize;
        }
    }

    /// <summary>
    /// 樹的多鏈表結點類
    /// </summary>
    /// <typeparam name="T"></typeparam>
    class MLNode<T>
    {
        private T data;                   //存儲結點的數據
        private MLNode<T>[] childs;       //存儲子結點的位置

        public MLNode(int max)
        {
            childs = new MLNode<T>[max];
            for (int i = 0; i < childs.Length; i++)
            {
                childs[i] = null;
            }
        }

        public T Data
        {
            get { return data; }
            set { data = value; }
        }

        public MLNode<T>[] Childs
        {
            get { return childs; }
            set { childs = value; }
        }
    }



    class MLTree<T> : ITree<MLNode<T>>
    {
        private MLNode<T> head;

        public MLNode<T> Head
        {
            get { return head; }
            set { head = value; }
        }

        public MLTree()
        {
            head = null;
        }

        public MLTree(MLNode<T> node)
        {
            head = node;
        }

        //求樹的根結點
        public MLNode<T> Root()
        {
            return head;
        }

        public void Clear()
        {
            head = null;
        }

        //待測試!!!
        public int GetDepth(MLNode <T> root)
        {
            int len;
            if (root == null)
            {
                return 0;
            }
            for (int i = 0; i < root.Childs.Length; i++)
            {
                if (root.Childs[i] != null)
                {
                    len = GetDepth(root.Childs[i]);
                    return len + 1;
                }
            }
            return 0;
        }

        public bool IsEmpty()
        {
            return head == null;
        }

        //求結點t的雙親結點,如果t的雙親結點存在,返回雙親結點,否則返回空
        //按層序遍歷的算法進行查找
        public MLNode<T> Parent(MLNode<T> t)
        {
            MLNode<T> temp = head;
            if (IsEmpty() || t == null) return null;
            if (temp.Data.Equals(t.Data)) return null;
            CSeqQueue<MLNode<T>> queue = new CSeqQueue<MLNode<T>>(50);
            queue.EnQueue(temp);
            while (!queue.IsEmpty())
            {
                temp = (MLNode<T>)queue.DeQueue();
                for (int i = 0; i < temp.Childs.Length; i++)
                {
                    if (temp.Childs[i] != null)
                    {
                        if (temp.Childs[i].Data.Equals(t.Data))
                        {
                            return temp;
                        }
                        else
                        {
                            queue.EnQueue(temp.Childs[i]);
                        }
                    }
                }
            }
            return null;
        }

        //求結點t的第i個子結點。如果存在,返回第i個子結點,否則返回空
        //i=0時,表示求第一個子節點
        public MLNode<T> Child(MLNode<T> t, int i)
        {
            if (t != null && i < t.Childs.Length)
            {
                return t.Childs[i];
            }
            else
            {
                return null;
            }
        }

        //求結點t第一個右邊兄弟結點,如果存在,返回第一個右邊兄弟結點,否則返回空
        public MLNode<T> RightSibling(MLNode<T> t)
        {
            MLNode<T> pt = Parent(t);
            if (pt != null)
            {
                int i = FindRank(t);
                return Child(pt, i + 1);
            }
            else
            {
                return null;
            }
        }

        //查找結點t在兄弟中的排行,成功時返回位置,否則返回-1
        private int FindRank(MLNode<T> t)
        {
            MLNode<T> pt = Parent(t);
            for (int i = 0; i < pt.Childs.Length; i++)
            {
                MLNode<T> temp = pt.Childs[i];
                if (temp != null && temp.Data.Equals(t.Data))
                {
                    return i;
                }
            }
            return -1;
        }

        //查找在樹中的結點t,成功是返回t的位置,否則返回null
        private MLNode<T> FindNode(MLNode<T> t)
        {
            if (head.Data.Equals(t.Data)) return head;
            MLNode<T> pt = Parent(t);
            foreach (MLNode<T> temp in pt.Childs)
            {
                if (temp != null && temp.Data.Equals(t.Data))
                {
                    return temp;
                }
            }
            return null;
        }

        //把以s為頭結點的樹插入到樹中作為結點t的第i顆子樹。成功返回true
        public bool Insert(MLNode<T> s, MLNode<T> t, int i)
        {
            if (IsEmpty()) head = t;
            t = FindNode(t);
            if (t != null && t.Childs.Length > i)
            {
                t.Childs[i] = s;
                return true;
            }
            else
            {
                return false;
            }
        }

        //刪除結點t的第i個子樹。返回第i顆子樹的根結點。
        public MLNode<T> Delete(MLNode<T> t, int i)
        {
            t = FindNode(t);
            MLNode<T> node = null;
            if (t != null && t.Childs.Length > i)
            {
                node = t.Childs[i];
                t.Childs[i] = null;
            }
            return node;
        }


        //先序遍歷
        //根結點->遍歷根結點的左子樹->遍歷根結點的右子樹 
        public void preorder(MLNode<T> root)
        {
            if (root == null)
                return;
            Console.WriteLine(root.Data + " ");
            for (int i = 0; i < root.Childs.Length; i++)
            {
                preorder(root.Childs[i]);
            }
        }


        //后序遍歷
        //遍歷根結點的左子樹->遍歷根結點的右子樹->根結點
        public void postorder(MLNode<T> root)
        {
            if (root == null)
            { return; }
            for (int i = 0; i < root.Childs.Length; i++)
            {
                postorder(root.Childs[i]);
            }
            Console.WriteLine(root.Data + " ");
        }


        //層次遍歷
        //引入隊列 
        public void LevelOrder(MLNode<T> root)
        {
            Console.WriteLine("遍歷開始:");
            if (root == null)
            {
                Console.WriteLine("沒有結點!");
                return;
            }

            MLNode<T> temp = root;

            CSeqQueue<MLNode<T>> queue = new CSeqQueue<MLNode<T>>(50);
            queue.EnQueue(temp);
            while (!queue.IsEmpty())
            {
                temp = (MLNode<T>)queue.DeQueue();
                Console.WriteLine(temp.Data + " ");
                for (int i = 0; i < temp.Childs.Length; i++)
                {
                    if (temp.Childs[i] != null)
                    {
                        queue.EnQueue(temp.Childs[i]);
                    }
                }
            }
            Console.WriteLine("遍歷結束!");
        }

        //按某種方式遍歷樹
        //0 先序
        //1 后序
        //2 層序
        public void Traverse(int TraverseType)
        {
            if (TraverseType == 0) preorder(head);
            else if (TraverseType == 1) postorder(head);
            else LevelOrder(head);
        }
    }
    class Tree
    {

        static void Main(string[] args)
        {
            MLTree<string> tree = new MLTree<string>();
            char ch;
            do
            {
                Console.WriteLine("1.添加結點");
                Console.WriteLine("2.刪除結點");
                Console.WriteLine("3.遍歷樹");
                Console.WriteLine("4.添加子結點");
                Console.WriteLine("5.退出");
                Console.WriteLine();
                ch = Convert.ToChar(Console.ReadLine());
                switch (ch)
                {
                    case '1':
                        Console.WriteLine("輸入父結點:");
                        string str = Convert.ToString(Console.ReadLine());
                        MLNode<string> pt = new MLNode<string>(4);
                        pt.Data = str;
                        Console.WriteLine("輸入子結點:");
                        str = Convert.ToString(Console.ReadLine());
                        MLNode<string> ct = new MLNode<string>(4);
                        ct.Data = str;
                        Console.WriteLine("輸入插入子結點的位置:");
                        int i = Convert.ToInt32(Console.ReadLine());
                        bool ok = tree.Insert(ct, pt, i);
                        if (ok)
                        {
                            Console.WriteLine("插入{0}成功", ct.Data);
                            Console.WriteLine(tree.GetDepth(pt));
                        }
                        break;
                    case '2':
                        Console.WriteLine("輸入要刪除的結點:");
                        str = Convert.ToString(Console.ReadLine());
                        pt = new MLNode<string>(4);
                        pt.Data = str;
                        tree.Delete(pt, 0);
                        break;
                    case '3':
                        tree.Traverse(2);
                        break;
                }

            } while (ch != '5');
        }
    }
}

樹的遍歷

1.先序遍歷

 訪問數的根結點->按照從左到右的順序先序遍歷樹中的每一顆樹

2.后序遍歷

按照從左到右的順序后序遍歷樹中的每一顆子樹->訪問根結點

3.層序遍歷

按照樹的結構從上到下 從左到右的順序訪問樹的結點。

樹的存儲方式

雙親表示法

孩子鏈表表示法

多重鏈表表示法

雙親孩子表示法

孩子兄弟表示法

注:本文整理自《數據結構(C#語言版)》!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM