zoukankan      html  css  js  c++  java
  • 递归有环问题解决方案

     场景引入

           今天碰到一个问题:当用户使用某个功能的时候,系统就直接挂了,一开始还以为是啥问题,最后发现是递归有环。

          业务场景:有个功能需要获取地区树,刚刚好地区树里面由于人为修改的原因,造成了环。

           A(广东,44)-->B(韶关,4402)-->C(南雄,44) 这种就是有环,会发生堆栈溢出,如果代码不处理,就会由于堆栈溢出,整个服务器直接挂了。

          直接上代码,模拟情况:

                 1、建两个类,后面要使用

     public class DictRegion
        {
            public string RegionCode { get; set; }
    
            public string RegionName { get; set; }
    
            public string ParentCode { get; set; }
    
            public string ParentName { get; set; }
        }
    
    
        public class TreeNode
        {
            public string RegionCode { get; set;  }
            public string RegionName { get; set; }
            public List<TreeNode> Childs { get; set; }
        }

            2、递归函数的编写

        static void GetTreeNode(List<DictRegion> regions,string parentCode,List<TreeNode> nodes)
        {
                var regionArr=regions.Where(d=>d.ParentCode == parentCode).ToList();
                foreach(var region in regionArr)
                {
    
                    var node = new TreeNode()
                    {
                        RegionCode = region.RegionCode,
                        RegionName = region.RegionName,
                        Childs = new List<TreeNode>()
                    };
                    GetTreeNode(regions,region.RegionCode,node.Childs);
                    nodes.Add(node);
                }
            }

           3、准备数据以及调用

     var regions = new List<DictRegion>() {
                        new DictRegion(){RegionCode="ROOT",RegionName="中国",ParentCode="",ParentName=""},
                        new DictRegion() { RegionCode = "44", RegionName = "广东", ParentCode = "ROOT", ParentName = "中国" },
                        new DictRegion() { RegionCode = "43", RegionName = "湖南", ParentCode = "ROOT", ParentName = "中国" },
                        new DictRegion() { RegionCode = "45", RegionName = "广西", ParentCode = "ROOT", ParentName = "中国" },
    
                        new DictRegion() { RegionCode = "4401", RegionName = "广州", ParentCode = "44", ParentName = "广东" },
                        new DictRegion() { RegionCode = "4402", RegionName = "韶关", ParentCode = "44", ParentName = "广东" },
                        new DictRegion() { RegionCode = "4403", RegionName = "深圳", ParentCode = "44", ParentName = "广东" },
    
                        new DictRegion() { RegionCode = "4501", RegionName = "南宁", ParentCode = "45", ParentName = "广西" },
                        new DictRegion() { RegionCode = "4502", RegionName = "柳州", ParentCode = "45", ParentName = "广西" },
                        new DictRegion() { RegionCode = "4503", RegionName = "桂林", ParentCode = "45", ParentName = "广西" },
    
                        new DictRegion() { RegionCode = "4301", RegionName = "长沙", ParentCode = "43", ParentName = "湖南" },
                        new DictRegion() { RegionCode = "4302", RegionName = "株洲", ParentCode = "43", ParentName = "湖南" },
                        new DictRegion() { RegionCode = "4303", RegionName = "湘潭", ParentCode = "43", ParentName = "湖南" },
    
                        new DictRegion() { RegionCode = "440111", RegionName = "从化", ParentCode = "4401", ParentName = "广州" },
                        new DictRegion() { RegionCode = "440112", RegionName = "天河", ParentCode = "4401", ParentName = "广州" },
                        new DictRegion() { RegionCode = "440113", RegionName = "增城", ParentCode = "4401", ParentName = "广州" },
    
                        new DictRegion() { RegionCode = "440211", RegionName = "仁化", ParentCode = "4402", ParentName = "韶关" },
                        new DictRegion() { RegionCode = "440212", RegionName = "乐昌", ParentCode = "4402", ParentName = "韶关" },
                        new DictRegion() { RegionCode = "44", RegionName = "南雄", ParentCode = "4402", ParentName = "韶关" },
                };
    
    
                //现在要求是,把中国下的一级节点都打展开。
                var treeNodes = new List<TreeNode>();
    
                GetTreeNode(regions, "ROOT", treeNodes);

            如红色部分,当我们调用获取地区树的方法时,就会发生堆栈溢出。

      解决方案

            1、限制递归调用的深度,简单,但是不好控制这个深度,如果写得太深,很浪费CPU,如果写得太浅,可能会导致需要的业务数据没有查出来。

                 定义一个公共的变量

                    //#region 限制递归深度
    
                    //         _depth++;
                    //        if (_depth >= 10000)
                    //        {
                    //            throw new Exception("递归超出深度");
                    //         }
                    //#endregion

           2、判断一下递归是否有环,在进行递归之前,把数据根据RegionCode进行查重处理,发现了有多个相同RegionCode即,报错。

           3、有同事提出,想在框架层面解决这个问题:

                 简单的解决方案:建表的时候,对于regionCode这种字段,要不设置为主键,要不设置为唯一索引,可能更多时候,对于这种字典类的数据可以考虑这种方案。

                 复杂的解决方案:暂无。。。,希望大家补充和分享

    终极目标:世界大同
  • 相关阅读:
    December 23rd 2016 Week 52nd Friday
    December 22nd 2016 Week 52nd Thursday
    December 21st 2016 Week 52nd Wednesday
    December 20th 2016 Week 52nd Tuesday
    December 19th 2016 Week 52nd Sunday
    December 18th 2016 Week 52nd Sunday
    uva294(唯一分解定理)
    uva11624Fire!(bfs)
    fzu2150Fire Game(双起点bfs)
    poj3276Face The Right Way
  • 原文地址:https://www.cnblogs.com/gdouzz/p/15513932.html
Copyright © 2011-2022 走看看