- 什么是广度优先遍历?
-
是一种用于遍历或搜索树或图的算法。它从根节点开始,逐层遍历节点,先访问根节点,然后访问根节点的所有子节点,再访问子节点的子节点,以此类推,直到遍历完所有节点。
-
广度优先遍历通常使用队列数据结构来实现。具体步骤如下:
-
- 将根节点放入队列中。
-
- 从队列中取出一个节点,访问该节点。
-
- 将该节点的所有未访问过的子节点放入队列中。
-
- 重复步骤2和步骤3,直到队列为空。
-
广度优先遍历保证了在同一层级的节点会先被访问,然后才是下一层级的节点。这种遍历方式适用于寻找最短路径、查找特定节点等问题。
// 将一维数据变成el-tree需要的多维数组
// 思路: 将服务端返回的平级数组,处理成tree需要的多层结构
// 使用循环和哈希表来实现,定义一个arr和map遍历原始数组 arr
// 将每个节点存储到哈希表 map 中再次遍历arr,根据 parentId 找到其父节点
// 并将当前节点添加到父节点的 children 属性中
// 如果节点没有 parentId,则将其作为根节点添加到 tree
// 数组中最后返回tree
//广度优先遍历
function convertToTree(arr) {
const tree = [];
const map = {};
arr.forEach(item => {
map[item.id] = {
label: item.label,
id: item.id,
children: []
};
});
arr.forEach(item => {
const node = map[item.id];
if (item.parentId) {
const parent = map[item.parentId];
parent.children.push(node);
} else {
tree.push(node);
}
});
return tree;
}
const flatArray = [
{ id: 1, label: 'Node 1', parentId: null },
{ id: 2, label: 'Node 1.1', parentId: 1 },
{ id: 3, label: 'Node 1.2', parentId: 1 },
{ id: 4, label: 'Node 1.2.1', parentId: 3 },
{ id: 5, label: 'Node 2', parentId: null },
{ id: 6, label: 'Node 2.1', parentId: 5 },
{ id: 7, label: 'Node 2.2', parentId: 5 },
];
const treeData = convertToTree(flatArray);
console.log(treeData);
// 递归
function convertToTree(arr, parentId = null) {
const tree = [];
arr.forEach(item => {
if (item.parentId === parentId) {
const children = convertToTreeRecursive(arr, item.id);
if (children.length > 0) {
item.children = children;
}
tree.push(item);
}
});
return tree;
}
const treeData = convertToTree(flatArray);
console.log(treeData);
// 将el-tree(多维数组)打平成一维数组
const data = [{
id: 1111,
label: 'Node 1',
children: [{
id: 2,
label: 'Node 1.1'
},
{
id: 345,
label: 'Node 1.2',
children: [
{
id: 4,
label: 'Node 1.2.1',
}
]
}
],
},{
id: 565,
label: 'Node 2',
children: [{
id: 69,
label: 'Node 2.1'
},
{
id: 78,
label: 'Node 2.2',
}
],
}
]
// 广度优先遍历
// 没有节点parentId
function flattenData(data) {
const flatArray = [];
const stack = [...data];
while (stack.length > 0) {
const node = stack.shift();
flatArray.push({
id: node.id,
label: node.label,
});
if (node.children && node.children.length > 0) {
stack.push(...node.children);
}
}
return flatArray;
}
// 有节点parentId
function flattenData(data) {
const flatArray = [];
const stack = data.map(node => ({ ...node, parentId: null }));
while (stack.length > 0) {
const { id, label, children, parentId } = stack.shift();
flatArray.push({
id,
label,
parentId
});
if (children && children.length > 0) {
stack.push(...children.map(child => ({ ...child, parentId: id })));
}
}
return flatArray;
}
console.log(flattenData(data));
// 递归
function flattenData(data) {
const flatArray = [];
function flatten(node) {
flatArray.push({
id: node.id,
label: node.label,
parentId: node.parentId
});
if (node.children && node.children.length > 0) {
node.children.forEach(child => {
flatten({
...child,
parentId: node.id
});
});
}
}
data.forEach(node => {
flatten(node);
});
return flatArray;
}
console.log(flattenData(data))
// el-tree 里面的slot ,插入节点的上移下移,前端通过点击实现视图的变化(即实现上下移动)
const obj = {
id: 122,
label: 'Node 1.2.2',
level: 3,
sequence: 2,
parentId: 12,
}
const data = [
{
id: 1,
label: 'Node 1',
level: 1,
sequence: 1,
parentId: null,
children: [
{
id: 11,
label: 'Node 1.1',
level: 2,
sequence: 1,
parentId: 1,
},
{
id: 12,
label: 'Node 1.2',
level: 2,
sequence: 2,
parentId: 1,
children: [
{
id: 121,
label: 'Node 1.2.1',
level: 3,
sequence: 1,
parentId: 12,
},
{
id: 122,
label: 'Node 1.2.2',
level: 3,
sequence: 2,
parentId: 12,
},
{
id: 123,
label: 'Node 1.2.3',
level: 3,
sequence: 3,
parentId: 12,
},
]
},
{
id: 13,
label: 'Node 1.3',
level: 2,
sequence: 3,
parentId: 1,
},
],
},
{
id: 2,
label: 'Node 2',
level: 1,
sequence: 1,
parentId: null,
children: [
{
id: 21,
label: 'Node 2.1',
level: 2,
sequence: 1,
parentId: 2,
},
{
id: 22,
label: 'Node 2.2',
level: 2,
sequence: 2,
parentId: 2,
},
{
id: 23,
label: 'Node 2.2',
level: 2,
sequence: 3,
parentId: 2,
},
{
id: 24,
label: 'Node 2.4',
level: 2,
sequence: 4,
parentId: 2,
},
],
}
];
// 上下移动
let targetArray = null;
function findParent(array, parentId) {
for (let i = 0; i < array.length; i++) {
const item = array[i];
if (item.id === parentId) {
targetArray = item.children;
break;
}
if (item.children) {
findParent(item.children, parentId);
}
}
}
findParent(data, obj.parentId);
console.log("找到的数组:", targetArray);
if (targetArray.length > 0) {
const index = targetArray.findIndex(item => item.id === obj.id);
// 上移
// if (index > 0) {
// console.log('上移')
// const temp = targetArray[index];
// targetArray[index] = targetArray[index - 1];
// targetArray[index - 1] = temp;
// }
// 下移
if (index < targetArray.length - 1) {
console.log('下移')
const temp = targetArray[index];
targetArray[index] = targetArray[index + 1];
targetArray[index + 1] = temp;
}
}
console.log("last数组:", data);
// el-tree 里面的slot ,插入节点编辑,替换掉原tree数组里面的内容
const obj = {
id: 122,
label: '替换显示的内容',
level: 3,
sequence: 2,
parentId: 12,
}
const data = [
{
id: 1,
label: 'Node 1',
level: 1,
sequence: 1,
parentId: null,
children: [
{
id: 11,
label: 'Node 1.1',
level: 2,
sequence: 1,
parentId: 1,
},
{
id: 12,
label: 'Node 1.2',
level: 2,
sequence: 2,
parentId: 1,
children: [
{
id: 121,
label: 'Node 1.2.1',
level: 3,
sequence: 1,
parentId: 12,
},
{
id: 122,
label: 'Node 1.2.2',
level: 3,
sequence: 2,
parentId: 12,
},
{
id: 123,
label: 'Node 1.2.3',
level: 3,
sequence: 3,
parentId: 12,
},
]
},
{
id: 13,
label: 'Node 1.3',
level: 2,
sequence: 3,
parentId: 1,
},
],
},
{
id: 2,
label: 'Node 2',
level: 1,
sequence: 1,
parentId: null,
children: [
{
id: 21,
label: 'Node 2.1',
level: 2,
sequence: 1,
parentId: 2,
},
{
id: 22,
label: 'Node 2.2',
level: 2,
sequence: 2,
parentId: 2,
},
{
id: 23,
label: 'Node 2.2',
level: 2,
sequence: 3,
parentId: 2,
},
{
id: 24,
label: 'Node 2.4',
level: 2,
sequence: 4,
parentId: 2,
},
],
}
];
// 广度优先遍历
function replaceData(data, obj) {
const newData = [...data];
const stack = [...newData];
while (stack.length > 0) {
const item = stack.pop();
if (item.id === obj.id) {
Object.assign(item, obj);
}
if (item.children) {
stack.push(...item.children);
}
}
return newData;
}
console.log(replaceData(data,obj))
// 递归
function replaceData(array, targetObj) {
for (let i = 0; i < array.length; i++) {
const item = array[i];
if (item.id === targetObj.id) {
array[i] = targetObj;
break;
}
if (item.children) {
replaceData(item.children, targetObj);
}
}
}
replaceData(data, obj);
console.log("替换后的数组:", data);