每日前端手写题--day10

以下题目来自掘金等其它博客,但是问题的答案都是根据笔者自己的理解做出的。如果你最近想要换工作或者巩固一下自己的前端知识基础,不妨和我一起参与到每日刷题的过程中来,如何?

第10天要刷的手写题如下:

  1. 数组转树
  2. 树转数组
  3. 使用js实现冒泡排序 下面是我自己写的答案:

1. 数组转树

  • 给定如下数组:
js 复制代码
let source = [{
    id: 1,
    pid: 0,
    name: 'body',
}, {
    id: 2,
    pid: 1,
    name: 'title',
}, {
    id: 3,
    pid: 2,
    name: 'div',
}, {
    id: 4,
    pid: 0,
    name: 'html',
}, {
    id: 5,
    pid: 4,
    name: 'div',
}, {
    id: 6,
    pid: 5,
    name: 'span',
}, {
    id: 7,
    pid: 5,
    name: 'img',
}, ]
  • 将其转成如下的树结构:
js 复制代码
[{
    id: 1,
    pid: 0,
    name: 'body',
    children: [{
        id: 2,
        pid: 1,
        name: 'title',
        children: [{
            id: 3,
            pid: 2,
            name: 'div'
        }],
    }, ],
}, {
    id: 4,
    pid: 0,
    name: 'html',
    children: [{
        id: 5,
        pid: 4,
        name: 'div',
        children: [{
            id: 7,
            pid: 5,
            name: 'img'
        }],
    }, ],
}]

分析 策略 实现

  • 循环遍历:很明显,对原来的数组进行一次遍历很难达到目的,原因在于,遍历到某个元素A的时候,不能保证其父元素已经被遍历过了,所以这实际上是一个循环遍历的问题
  • 处理循环遍历问题的策略是:队列数据结构,从队列尾部弹出,经过检查函数,如果符合就弹出下一个,如果不符合就放到队列头部等待下次检查;直到队列中没有元素
  • 具体来说:
    • 创建一张哈希表tree,索引为各个元素的id值
    • 循环遍历队列中的元素,对每一个元素做如下处理:
      *
      1. 判断此元素是否在哈希表中,如果没有的话,添加进哈希表
        1. 判断此元素的父元素是否在哈希表中:
        • (1) 如果在的话就加入到父元素的children属性中去;
        • (2) 如果不再的话,说明子元素在父元素之前被遍历到了,这个时候需要将此元素移动至队列头部等待下次遍历检查
  • 结果:最后返回的树是一颗完整的树,保存了所有的父子关系!
js 复制代码
function convert(arr) {
    let tree = {
        0: {
            id: 0,
            pid: null,
            children: [],
        }
    };
    const _queue = [...arr];
    while (_queue.length) {
        // 当前元素
        const _cur = _queue.pop();
        const {
            pid,
            id
        } = _cur;

        // 将id-item映射保存到记录中,方便通过id找到此元素
        tree[id] = tree[id] ?? _cur;

        // 将顶层元素添加到tree当中
        // 此时先尝试性找到其父元素,如果找到了就加入到父元素的children数组中去
        const _p = tree[pid];
        if (_p) {
            if (_p.children) {
                _p.children.push(_cur);
            } else {
                _p.children = [_cur];
            }
        } else {
            // 如果找不到的话,说明深层元素在其父元素之前出现,时机不对,将其位置修改至队列头部
            _queue.unshift(_cur);
        }
    }
    return tree[0].children;
}

console.log(convert(source));

2. 树转数组

  • 给定如下的树结构:
js 复制代码
[{
    id: 1,
    pid: 0,
    name: 'body',
    children: [{
        id: 2,
        pid: 1,
        name: 'title',
        children: [{
            id: 3,
            pid: 2,
            name: 'div'
        }],
    }, ],
}, {
    id: 4,
    pid: 0,
    name: 'html',
    children: [{
        id: 5,
        pid: 4,
        name: 'div',
        children: [{
            id: 7,
            pid: 5,
            name: 'img'
        }],
    }, ],
}]
  • 将其转成如下数组:
js 复制代码
let source = [{
    id: 1,
    pid: 0,
    name: 'body',
}, {
    id: 2,
    pid: 1,
    name: 'title',
}, {
    id: 3,
    pid: 2,
    name: 'div',
}, {
    id: 4,
    pid: 0,
    name: 'html',
}, {
    id: 5,
    pid: 4,
    name: 'div',
}, {
    id: 6,
    pid: 5,
    name: 'span',
}, {
    id: 7,
    pid: 5,
    name: 'img',
}, ]

分析 策略 实现

  • 这个是一个深度优先遍历问题,直接使用递归就可以实现了
  • 遍历每一个元素,如果这个元素没有children属性就直接加入到结果数组中去;如果有children属性,就对children递归,将递归结果加入到结果数组中去,然后删除此元素的children属性,并加入到结果数组中去。
js 复制代码
function tree2arr (tree) {
    const rst = [];

    tree.forEach(
        item => {
            const {children} = item;
            if(children){
                rst.push(...tree2arr(children));
                delete item['children'];
            }
            rst.push(item);
        }
    )

    return rst;
}

console.log(tree2arr(source2).sort(function(a,b){return a.id-b.id}))

3. 使用js实现冒泡排序

考这个主要是考细节,就是考两层循环的起始位置和结束位置

  • 原理:遍历元素,如果前面的比后面的大,就交换二者顺序
  • 外层遍历起始位置为0,结束位置为length;内层循环以外层循环因子作为起始值,结束位置也为length
js 复制代码
function bubbleSort (source) {
    const rst = [...source];
    const len = rst.length;
    
    const swap = (i,j) => {
        [rst[i], rst[j]] = [rst[j], rst[i]];
    }

    for (let i = 0; i < len; i++) {
        for (let j = i; j < len; j++) {
            if(rst[i] > rst[j]){
                swap(i,j);
            }
        }
    }
    return rst;
}

上面的程序改一个字就可以编程倒序排序,你知道在哪里吗?

相关推荐
发现一只大呆瓜3 分钟前
Vite凭什么这么快?3分钟带你彻底搞懂 Vite 热更新的幕后黑手
前端·面试·vite
Maimai1080815 分钟前
React如何用 @microsoft/fetch-event-source 落地 SSE:比原生 EventSource 更灵活的实时推送方案
前端·javascript·react.js·microsoft·前端框架·reactjs·webassembly
candyTong18 分钟前
Claude Code 的 Edit 工具是怎么工作的
javascript·后端·架构
kyriewen2 小时前
产品经理把PRD写成“天书”,我用AI半小时重写了一遍,他当场愣住
前端·ai编程·cursor
Patrick_Wilson2 小时前
知识沉淀的四层模型:从个人笔记到企业资产,让文档真正长出复利
面试·程序员·ai编程
humcomm2 小时前
元框架的工作原理详解
前端·前端框架
canonical_entropy3 小时前
Attractor Before Harness: AI 大规模开发的方法论
前端·aigc·ai编程
橙序员小站3 小时前
人人都在鼓吹的OPC,我想给你泼盆冷水
面试·创业
zhangxingchao3 小时前
多 Agent 架构到底怎么选?从 Claude Agent Teams、Cognition/Devin 到工程落地原则
前端·人工智能·后端
IT_陈寒3 小时前
SpringBoot那个自动配置的坑,害我排查到凌晨三点
前端·人工智能·后端