JS中广度深度优先遍历应用拷贝函数
程序员文章站
2022-05-23 19:43:56
...
广度优先遍历和深度优先遍历应用——实现对象深拷贝
//判断要复制的对象的类型,仅考虑对象和数组两种复杂数据类型
function getEmpty(obj) {
if (Object.prototype.toString.call(obj) === '[object Object]') {
return {};
} else if (Object.prototype.toString.call(obj) === '[object Array]') {
return [];
}
return obj; //基本数据类型处理
}
//广度优先遍历
function bfsCopy(origin) {
let queue = [];
let map = new Map(); //记录出现过的对象,用于处理环
let ans = getEmpty(origin);
if (ans !== origin) {
queue.push([origin, ans]);
map.set(origin, ans);
}
while (queue.length) {
let [ori, ans] = queue.shift();
for (let key in ori) {
if (map.get(ori[key])) { //说明此时的键值已经被设置过了,此时不需要再对其内部进行递归操作,否则会陷入死循环
ans[key] = map.get(ori[key]);
continue;
}
ans[key] = getEmpty(ori[key]);
if (ans[key] !== ori[key]) {
queue.push(ori[key]);
map.set(ori[key], ans[key]);
}
}
}
return ans;
}
//深度优先遍历,递归
dfsCopy1.prototype.map = new Map(); //再原型中存储变量map使得每层递归调用中都能访问到map
function dfsCopy1(origin) {
let ans = getEmpty(origin);
dfsCopy1.prototype.map.set(origin, ans);
if (ans === origin) {
return ans;
}
for (let key in origin) {
if (dfsCopy1.prototype.map.get(origin[key])) { //环处理
ans[key] = dfsCopy1.prototype.map.get(origin[key]);
continue;
}
ans[key] = dfsCopy1(origin[key]);
}
return ans;
}
//深度优先遍历非递归
function dfsCopy2(origin) {
let stack = [];
let map = new Map();
let ans = getEmpty(origin);
if (ans === origin) return ans;
stack.push([origin, ans]);
while (stack.length) {
let [childori, childans] = stack.pop();
for (let key in childori) {
if (map.get(childori[key])) { //环处理
childans[key] = childori[key];
continue;
}
childans[key] = getEmpty(childori[key]);
if (childans[key] !== childori[key]) {
stack.push([childori[key], childans[key]]);
map.set(childori[key], childans[key]);
}
}
}
return ans;
}
let obj = {
a: 2,
b: {
c: 3
}
}
obj.b.d = obj;
console.log(bfsCopy(obj.b.d.a)); // 2
上一篇: JS树形数据结构遍历--深度优先遍历和广度优先遍历
下一篇: 图