C#一颗简单多叉树的实现(原理、广度优先遍历、深度优先遍历)

http://blog.csdn.net/guigenyi/article/details/46761273

实现原理:

多叉树中的节点有两个域,分别表示节点名以及一个链表,该链表存储其子节点的地址。根据用户输入进行深度递归调用建树。另外还实现了一个层次优先遍历函数。该函数用一个队列实现该多叉树的层次优先遍历。首先将根节点入队列,然后检测队列是否为空,如果不为空,将队列出队列,访问出队列的节点,然后该节点的子节点指针入队列,依次循环下去,直至队列为空,终止循环,从而完成整个多叉树的层次优先遍历。
首先用户的多叉树数据存储在一个文件中,输入格式如下:
8aA 4 g cC z bBbB
z 2 f i
g 1 d
d 3 x e j
每行的第一个元素指定一个节点,期中第一行指定了该多叉树的根节点。第二个元素表示该节点有几个子节点,紧接着后面跟了几个子节点。
根据以上数据,其对应的多叉树应该是如下:

我们想实现结果按深度精心输出,从最深的节点开始输出如: xej dfi gcCzbBbB aA
另我们想得到从根节点开始到叶子节点直接所有节点名字加起来最长的一个路径,在这里计时aAbBbB

以下是代码:

public class MTreeNode  
    {  
        private string _name;//节点名  
        private int _nChildren;//子节点数  
        private int _level = -1;// 记录该节点在多叉树中的层数  
        List<MTreeNode> _children;// 指向其自身的子节点,children一个链表,该链表中的元素是MTreeNode类型的指针  
  
        public MTreeNode()  
        {  
            _children=new List<MTreeNode>();  
        }  
  
        public string Name  
        {  
            get { return _name; }  
            set { _name = value; }  
        }  
  
        public int NChildren  
        {  
            get { return _nChildren; }  
            set { _nChildren = value; }  
        }  
  
        public int Level  
        {  
            get { return _level; }  
            set { _level = value; }  
        }  
  
        public List<MTreeNode> Children  
        {  
            get { return _children; }  
            set { _children = value; }  
        }  
    }  
  
    public class MultiTree  
    {  
        private Stack<MTreeNode> t_stack;  
        private Queue<MTreeNode> queue_t = new Queue<MTreeNode>();  
  
  
        /// <summary>  
        /// 深度优先遍历查找  
        /// </summary>  
        /// <param name="name">查找内容</param>  
        /// <param name="head">当前节点(从首节点开始)</param>  
        /// <returns>目标节点</returns>  
        private static MTreeNode search_node_r(string name, MTreeNode head)  
        {  
            MTreeNode temp = null;  
            if (head != null)  
            {  
                if (name.Equals(head.Name))  
                {  
                    temp = head; //如果名字匹配  
                }  
                else //如果不匹配,则查找其子节点  
                {  
                    for (int i = 0; i < head.NChildren && temp == null; i++)  
                    {  
                        temp = search_node_r(name, head.Children[i]);  
                    }  
                }  
            }  
            return temp;  
        }  
  
        /// <summary>  
        /// 从文件中读取多叉树数据,并建立多叉树  
        /// </summary>  
        /// <param name="head">多叉树根节点</param>  
        /// <param name="filePath">文件路径</param>  
        public static void read_file(ref MTreeNode head, string filePath)  
        {  
            MTreeNode temp = null;  
            int n;  
            string name, child;  
            using (StreamReader sr = new StreamReader(filePath))  
            {  
                //一行行读取直至为NULL  
                string strLine = string.Empty;  
                while ((strLine = sr.ReadLine())!=null)  
                {  
                    string[] strings = strLine.Split(' ');  
                    name = strings[0];  
                    n = int.Parse(strings[1]);  
                    if (head == null) //若为空  
                    {  
                        //让temp和head引用同一块内存空间  
                        temp = head = new MTreeNode(); //生成一个新节点  
                        temp.Name = name; //赋名  
                    }  
                    else  
                    {  
                        temp = search_node_r(name, head);  
                        //这里默认数据文件是正确的,一定可以找到与name匹配的节点  
                        //如果不匹配,那么应该忽略本行数据  
                    }  
                    //找到节点后,对子节点进行处理  
                    temp.NChildren = n;  
                    for (int i = 0; i < n; i++)  
                    {  
                        child = strings[i + 2];  
                        temp.Children.Add(new MTreeNode());  
                        temp.Children[i].Name = child;  
                    }  
                }  
            }  
  
        }  
  
        /// <summary>  
        /// 实现函数1  
        /// 将多叉树中的节点,按照深度进行输出  
        /// 实质上实现的是层次优先遍历  
        /// </summary>  
        /// <param name="head">首节点</param>  
        private static void f1(MTreeNode head)  
        {  
            MTreeNode tMTreeNode;  
            Queue<MTreeNode> queue = new Queue<MTreeNode>(100); //将队列初始化大小为100  
            Stack<MTreeNode> stack = new Stack<MTreeNode>(100); //将栈初始化大小为100  
            head.Level = 0; //根节点的深度为0  
  
            //将根节点入队列  
            queue.Enqueue(head);  
  
            //对多叉树中的节点的深度值level进行赋值  
            //采用层次优先遍历方法,借助于队列  
            while (queue.Count != 0) //如果队列q不为空  
            {  
                tMTreeNode = queue.Dequeue(); //出队列  
                for (int i = 0; i < tMTreeNode.NChildren; i++)  
                {  
                    tMTreeNode.Children[i].Level = tMTreeNode.Level + 1; //对子节点深度进行赋值:父节点深度加1  
                    queue.Enqueue(tMTreeNode.Children[i]); //将子节点入队列  
                }  
                stack.Push(tMTreeNode); //将p入栈  
            }  
  
            while (stack.Count != 0) //不为空  
            {  
                tMTreeNode = stack.Pop(); //弹栈  
                System.Diagnostics.Debug.WriteLine("   {0} {1}", tMTreeNode.Level, tMTreeNode.Name);  
            }  
        }  
  
        /// <summary>  
        /// 实现函数2  
        /// 找到从根节点到叶子节点路径上节点名字字母个数最大的路径  
        /// 实质上实现的是深度优先遍历  
        /// </summary>  
        /// <param name="head">首节点</param>  
        /// <param name="str">临时字符串</param>  
        /// <param name="strBest">从根节点到叶子节点路径上节点名字字母个数最大的路径</param>  
        /// <param name="level">当前深度</param>  
        private static void f2(MTreeNode head, string str, ref string strBest, int level)  
        {  
            if (head == null) return;  
            var tmp = str + head.Name;  
  
            if (head.NChildren == 0)  
            {  
                if (strBest == null || tmp.Length > strBest.Length)  
                {  
                    strBest = tmp;  
                }  
            }  
            for (var i = 0; i < head.NChildren; i++)  
            {  
                f2(head.Children[i], tmp, ref strBest, level + 1);  
            }  
        }  
  
        private void free_tree_r(MTreeNode head)  
        {  
            if (head == null)  
                return;  
            head = null;  
        }  
  
        static void Main(string[] args)  
        {  
            MTreeNode head = null;  
            string strBest = null;  
            read_file(ref head, "TextFile1.txt");  
            System.Diagnostics.Debug.WriteLine("f1:");  
            f1(head);  
            f2(head, "", ref strBest, 0);  
            System.Diagnostics.Debug.WriteLine("f2:\n   {0}", strBest);  
            Console.ReadKey();  
        }  
    }  

输出结果:
f1:
   3 j
   3 e
   3 x
   2 i
   2 f
   2 d
   1 bBbB
   1 z
   1 cC
   1 g
   0 aA
aAbBbB: f2:
   {0}
以下是本Demo参考的C++版本的多叉树实现。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值