活学活用 DFS

一、前言

今天小伙伴给我截了个图,吐糟公司的恶心的需求,需要将一个大的、嵌套列表展开(平铺)成一级列表,然后,哼哧哼哧写完后,给我看。不给我看还不要紧,一给我看,我立马小怒,这是干了多年开发写出来的代码么?废话不多说,先上图片:

N级嵌套.jpeg

二、深度优先搜索 DFS(Depth First Search)

如果各位大一学习过《数据结构》,我记得应该是清华大学出版的(当初是个紫色的封面),现在可能已经改了N版。该书我们在学习完二叉树后,就是学习栈、堆,再然后就是学习 DFS / BFS,之后就是图(Graph)。

因为图比较难(分为无向图和有向图),因此,才先学习 DFS / BFS,图的用处很广(小到社区便利设施搭建,大到城市道路规划、高铁站等),因此,掌握了 DFS,至少对理解图是很有用的,而很多算法题,也涉及到 DFS。

那说了这么多,什么是 DFS ?先来看个图:

dfs.png

如果我们要完整的遍历该结构(所有路径,每个节点只能访问一次),方法是:

  • A -> B -> E (深度优先);
  • A -> B -> C -> D (广度优先);

两种优先的思想:

  • 深度优先很简单:先沿着一条路遍历下去,直到没有路;
  • 广度优先则是:先遍历当前节点的所有子节点(A的子节点就是 B、C、D);然后,再依次遍历子节点的子节点;

很明显,上面这个图,我们用 DFS 更简单,也更快速:

  1. A -> B -> E;
  2. C -> F -> G -> H -> D;

遇到 A时结束;

三、基于 DFS 优化代码逻辑

我们先来通过代码截图,来了解该数据结构:

  • projects 是个列表,每个元素都是 sites;
  • sites 也是个列表,每个元素都是 countries;
  • countries也是列表,每个元素含有 locals 和 currencies;

将列表展开,最终组合为一个列表,每个对象都含有:

[
    {
        project: project.name,
        siteId: site.siteId,
        countryCode: country.countryCode,
        localCode: local.localCode,
        currencyCode: currency.currencyCode,
        host: site.host
    },
    ......
]

思想嘛,就是从头开始遍历,一直遍历到叶子节点,即 country,那么简单了,我给出了 DFS 的 demo,并没有帮他去写这段逻辑(不想因为是拿来主义)。

<!DOCTYPE html>
<html>
<head>
    <title>test</title>
</head>
<body>

    <script type="text/javascript">
         // DFS
        function combines (obj, kvs = [], list, comb = {}) {
            // 如果 kvs 为 0,表明已经到了叶子节点
            // 加入到 list 中,返回上一级,继续 DFS
            if (kvs.length === 0) {
                list.push(Object.assign({}, comb));
                return;
            }

            // 从 kvs 中取出首元素(KV)
            const keyAndValue = kvs.shift();
            let k = Object.keys(keyAndValue)[0], v = keyAndValue[k];

            const data = obj[k];
            if (Array.isArray(data)) {
                // 深度遍历
                for (let i = 0; i < data.length; i ++) {
                    comb[v] = data[i][v];
                    combines(data[i], kvs, list, comb);
                }
            }
            // 返回到上一级时,我们需要将该 kv 放回到数组首位置
            // 否则上一级的下一个元素遍历时,kvs 就空了(因为 kvs 是索引传递,不是值拷背传递)
            kvs.unshift(keyAndValue);
        }

        // 构造测试数据
        var ks = ['project', 'site', 'city'];
        function genData (index) {
            let list = [];
            for (let i = 0; i < 10; i ++) {
                var obj = {};
                obj[ks[index] + 'Id'] = Math.random();
                if (index+1 < ks.length) {
                    obj[ks[index+1] + 's'] = genData(index+1);
                }
                list[i] = obj;
            }
            return list;
        }

        // 构造大对象,分别嵌套 ks
        var o = {projects: genData(0)};

        // 平铺成一级列表 list
        var list = []
        // 将 o 转化为 list
        combines(o, [{projects: 'projectId'},{sites: 'siteId'},{citys: 'cityId'}], list)
        console.log(list);
    </script>
</body>
</html>

当然,该算法只是给了朋友去参考,实际,怎么也得动手稍微修改一个 combines 的 kvs,来满足他自己的需求。

这里的 DFS 还是最简单,最基本的,并没有考虑数据重复后,要『剪枝』的情况,因为,朋友的实际项目不存在构造出来的数据是重复的。

要想真正学习 DFS 并掌握,还是有一定难度的,多看看算法方面的题,多想多练才能逐渐掌握!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容