深度优先遍历 and 广度优先遍历

深度优先遍历 and 广度优先遍历

遍历在前端的应用场景不多,多数是处理DOM节点数或者 深拷贝。下面笔者以深拷贝为例,简单说明一些这两种遍历。 ?

深度优先遍历

想象有一颗节点树,从某个顶点开始,一直往下遍历,直到遍历到的节点都访问过后,往回走,遍历没有访问的节点,感觉很像递归。下面笔者就用递归实现 深度优先遍历。


function DFS(target,visiteds){
    var Type = Object.prototype.toString.call(target).slice(8,-1);
    console.log(Type)
    var copy = Type == 'Array'?[]:{};
    visiteds = visiteds|| []; //处理环形数据,防止无限循环
    switch(Type){
        case 'Array':
        case 'Object':
            var index = visiteds.indexOf(target);
            if(index>-1){
                copy = visiteds[index];
            }else{
                visiteds.push(target);
                for(var key in target){
                    copy[key] = DFS(target[key],visiteds);
                }
            }
        break;
        default:
            copy = target;
        break; 

    }
    return copy;
};

广度优先遍历

如果把深度优先遍历看成纵向遍历,那么广度优先遍历就是横向遍历,一层一层的往下遍历。下面用队列(FIFO)来实现。


function getEmpty(o){
    if(Object.prototype.toString.call(o) === '[object Object]'){
        return {};
    }
    if(Object.prototype.toString.call(o) === '[object Array]'){
        return [];
    }
    return o;
}

function BFS(target){
    var queue = [];
    var targetMap = []; //处理环形数据,防止无限循环
    var copy = getEmpty(target);
    if(copy!==target){
        queue.push([target,copy]);
    }
    while(queue.length>0){
        var [_target,_copy] = queue.shift();  //*
        for(var key in _target){
            var index = targetMap.indexOf(_target[key]);
            if(index>-1){
                _copy[key] = targetMap[index]
                continue;
            }
            _copy[key] = getEmpty(_target[key])
            if(_copy[key]!==_target[key]){
                queue.push([_target[key],_copy[key]]); //*
                targetMap.push(_target[key]);
            }
        }
    }
    return copy
}

总结

上面用两种不同的方法实现了深拷贝,但是只针对Object,Array的情况,其他的复杂对象没有考虑到,当然你也可以添加更多的处理,但笔者认为目前这样已经足够用了。。。
深度优先遍历,关键在于理解递归,而广度优先遍历,关键在于理解,queue.shift出去的数据保存着原来数据的引用,所以才能够在不断的进栈出栈中修改值(间接修改值) ?

转载于:https://www.cnblogs.com/blogs-xlf/p/11193748.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值