算法洗脑系列(8篇)——第六篇 回溯思想

 记得广告中经常听到过,抱着试试看的态度买了3个疗程,效果不错........  也经常听人说过什么车到山前必有路,船到桥头自然直。

哈哈,这种思想就是回溯思想,也可称为试探思想。

 

一: 思想

       有时我们要得到问题的解,先从其中某一种情况进行试探,在试探过程中,一旦发现原来的选择是错误的,那么就退回一步重新选择,

   然后继续向前试探,反复这样的过程直到求出问题的解。

 

二:场景

      回溯思想是一个非常重要的思想,应用场景也是非常广泛。

      ①   “下棋”:  每一次走棋的位置都要考虑到是否是损人利己,如果是害人害己的走法就要回撤,找下一步损人利己的走法。

      ②   “迷宫”:  这种问题用试探法来解决相信我也不用向大家介绍了,其实迷宫问题抽象起来就是“对图的遍历问题“,当然对

                        图的遍历我先前的文章是有的,有兴趣的可以自己看一看。

 

三:举例

      记得我写第一篇文章的时候有园友希望我能找些实际的项目案例,这不,今天就给大家带来了,首先就拿博客园的“网站分类”层级菜单

 来说吧,首先上图:

 

针对这样的层级结构我们设计数据表一般都会设计成无限极分类,如下图:

 

那么问题来了,针对这样的数据,我们该如何在页面上呈现呢?

      码农的做法就是点击一个父节点然后异步去数据库读取子节点,好一点的做法就会有人把数据放在xml里面,但是都逃避不了多次与

服务器进行交互,带来比较大的性能问题。

      我们这里要讲的当然是减轻服务器的压力,页面呈现的时候直接Load出所有数据,然后序列化为Json,就如上面的图中一样,我们用

算法来解剖上面的json数据。

    

      首先上面的json数据是由多个多叉树组成的森林,画图如下:

那么接下来如何遍历这个森林,数据结构中,森林是可以转化为二叉树的,然后采用”先序,中序  或者 后序”,当然对森林遍历也可以

采用“深度优先,广度优先”。

 

好了,分析了这么多,其实也就是二步走:

   第一: 将Json数据变成森林的数据结构模型。

   第二:对森林进行遍历,这里就采用深度优先。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function () {

            var zNodes = [
            { id: 1, pId: 0, name: ".Net技术" },
            { id: 2, pId: 0, name: "编程语言" },
            { id: 3, pId: 0, name: "软件设计" },
            { id: 4, pId: 1, name: ".Net新手区" },
            { id: 5, pId: 1, name: "Asp.Net" },
            { id: 6, pId: 1, name: "C#" },
            { id: 7, pId: 1, name: "WinForm" },
            { id: 8, pId: 4, name: ".Net码畜区" },
            { id: 9, pId: 2, name: "Java" },
         ];

            var setting = ["id", "pId"];

            //第一步: 转化数据结构模型
            var result = ToForest(zNodes, setting);

            var mynode = "<ul>" + GetNodes(result) + "</ul>";

            $("body").append(mynode);

        });

        var html = "";

        //第二步:深度优先(这里面的html格式可以自己更改)
        function GetNodes(result) {
            for (var i = 0; i < result.length; i++) {

                html += "<li>" + result[i].name;

                if (result[i].childs != undefined) {
                    html += "<ul>";
                    GetNodes(result[i].childs);
                    html += "</ul>";
                }

                html += "</li>";
            }

            return html;
        }

        //setting的格式:[ID,Name,PID]
        function ToForest(sNodes, setting) {
            var i, l,

            //主键ID
            key = setting[0];

            //parentID
            parentKey = setting[1];

            //childs
            childsKey = "childs";

            //参数检查
            if (!key || key == "" || !sNodes)
                return [];

            if ($.isArray(sNodes)) {

                //存放森树形式的数据模型
                var r = [];

                //存放以ID为key,ID对应的实体为value
                var tmpMap = [];

                //赋值操作
                for (i = 0; i < sNodes.length; i++) {
                    //获取当前的id
                    var id = sNodes[i][key];

                    tmpMap[id] = sNodes[i];
                }

                //对json逐层遍历确定层级关系
                for (i = 0; i < sNodes.length; i++) {

                    //获取当前的pid
                    var pid = sNodes[i][parentKey];

                    //判断是否是顶级节点
                    if (tmpMap[pid]) {
                        //判断该节点是否有孩子节点
                        if (!tmpMap[pid][childsKey])
                            tmpMap[pid][childsKey] = [];
                        //将此节点放在该节点的孩子中
                        tmpMap[pid][childsKey].push(sNodes[i]);
                    } else {
                        //如果是顶级节点直接存放
                        r.push(sNodes[i]);
                    }
                }
                return r;
            } else {
                return [sNodes];
            }
        }
    </script>
</head>
<body>
</body>
</html>

 

时间: 2024-10-31 21:33:05

算法洗脑系列(8篇)——第六篇 回溯思想的相关文章

算法洗脑系列(8篇)——第八篇 概率思想

    今天写最后一篇来结束这个系列,我们知道很多算法解决问题的步骤都是固定的,而概率算法每一步的选择都是随机的, 当在某些领域问题中通常比最优选择省时,所以就大大提高了算法的效率,降低了复杂度.   一:思想       这里主要讲一下"数值概率算法",该算法常用于解决数值计算问题,并且往往只能求得问题的近似解,同一个问题同样的概率算法 求解两次可能得到的结果大不一样,不过没关系,这种"近似解"会随时间的增加而越接近问题的解.   二:特征      现实生活中,

算法洗脑系列(8篇)——第二篇 递归思想

   今天说说递归思想,在我们编码时,有的时候递归能够让我们的算法更加通俗易懂,并且代码量也是大大的减少.比如我先前的系列中说到了 关于树的"先序,中序和后序"遍历,那么看看用递归来描叙这个问题是多少的简洁,多么的轻松. #region 二叉树的先序遍历 /// <summary> /// 二叉树的先序遍历 /// </summary> /// <typeparam name="T"></typeparam> ///

算法洗脑系列(8篇)——第七篇 动态规划

     今天跟大家分享下算法思想中比较难的一种"动态规划",动态规划给人像是作战时常用的"迂回战术",或者说是 游击战,在运动中寻找突破口.   一: 思想    首先要了解"动态规划",必须先知道什么叫做"多阶段决策",百科里面对这个问题解释的很全,我就load一段出来, 大家得要好好品味,好好分析.   上面图中最后一句话就定义了动态规划是要干什么的问题.   二:使用规则     现在我们知道动态规划要解决啥问题了,那

算法洗脑系列(8篇)——第五篇 分治思想

  由于最近工作比较忙,好长时间都没有更新博客了,今天就分享下分治思想.   一: 思想      有时候我们处理一个复杂的问题,可能此问题求解步骤非常杂,也可能是数据非常多,导致我们当时很难求出或者无法求出,古语有云: 步步为营,各个击破,这个思想在算法中称为分治思想,就是我们可以将该问题分解成若干个子问题,然后我们逐一解决子问题,最后将子问题 的答案组合成整个问题的答案.   二: 条件      当然各个思想都有它的使用领域,所以玩这场分治游戏就要遵守它的游戏规则.        ①  

数据结构与算法(C#实现)系列---演示篇(一)

数据|数据结构|算法 数据结构与算法(C#实现)系列---演示篇(一) Heavenkiller(原创) 这一篇主要是针对以后各篇的数据类型进行一个实质性的演示.因此希望大家具体看了各种数据结构的分析之后再看这篇. 主要包括如下几个方面的演示: 1. 堆栈. 演示了一个利用堆栈作的RPN计算器 2. 排序表.演示了一个利用排序表做的多项式表达式的加法运算 3. 广义树.演示了深度遍历和广度遍历 4. N叉树.演示了N叉树的生成插入删除等基本操作 5. 表达式树.演示了一个用二叉树和堆栈做的可以将

数据结构与算法(C#实现)系列---演示篇(二)

数据|数据结构|算法 数据结构与算法(C#实现)系列---演示篇(二) Heavenkiller(原创) public static void ShowGeneralTree_travel() { IEnumerator tmpIEnum; Tree.TraversalType travelType=0; //---------------------提示---------------------------- Console.WriteLine("please choose a the No.

数据结构与算法(C#实现)系列---演示篇(三)

数据|数据结构|算法 数据结构与算法(C#实现)系列---树(二) Heavenkiller(原创) public class InOrder:IPrePostVisitor { private IVisitor visitor; public InOrder(IVisitor _vis){visitor=_vis;} #region IPrePostVisitor 成员 public void PreVisit(object _obj) { // TODO: 添加 InOrder.PreVis

再谈星巴克的危机公关和社交网络战略:品牌洗脑术

品牌最重要的事儿不仅是卖出溢价,还要黏住客户,并且让消费者获得高于商品价格的体验--而这,才是"品牌"能够成为品牌的奥秘. 1 星巴克被曝"高价"的大新闻很快就过去了.央视一本正经的新闻批判"腔调"来自民间的吐槽很轻松的化解了:再加上国内国际大新闻不断的大环境下,人们的心思可能早已经被呼叫转移到其他方面. 这是一个碎片化的时代,我们接触和试图弄清某一个事儿是很少有耐心的,这轮星巴克的风波就这么悄然的快被我们遗忘了. 对于星巴克的事儿,之前写了篇&

你好,GoogleSitelink系列(下)设置篇

续上一篇<你好,Google Sitelink系列(上)原理篇>, 今天说<Google Sitelink设置篇>. 今天要做的是通过Google管理员工具,把上海SEO实验室的Sitelink中显示不理想的链接去掉(拦截掉), 如下图: 第一步: 首先进入GG管理员工具,进入左边"链接"->" 网站链接",如果您的网站没有出现Sitelink,界面如下: 上图中红色部分写着"Google 尚未针对您的网站生成任何网站链接.