Ejemplo de estructura de árbol --- realizar la conversión de matriz y estructura de árbol

Un árbol es una estructura de datos sin hash y, al igual que una tabla sin hash, es muy útil para almacenar datos que deben buscarse rápidamente.

Un árbol es un modelo abstracto para datos jerárquicos . El ejemplo más común de un árbol en la vida real es un árbol genealógico o la estructura organizativa de una empresa.

Este artículo describirá un ejemplo de la construcción de un árbol para realizar la conversión mutua entre una matriz y un árbol, que a menudo se encuentra en la estructura de árbol del front-end.

Escenario de demanda:

Convierta una matriz en una estructura de árbol y convierta una estructura de árbol en una matriz

formación

const list= [
    { id: 1001, parentId: 0, name: 'AA' },
    { id: 1002, parentId: 1001, name: 'BB' },
    { id: 1009, parentId: 1005, name: 'II' },
    { id: 1003, parentId: 1001, name: 'CC' },
    { id: 1004, parentId: 1003, name: 'DD' },
    { id: 1005, parentId: 1003, name: 'EE' },
    { id: 1006, parentId: 1002, name: 'FF' },
    { id: 1007, parentId: 1002, name: 'GG' },
    { id: 1008, parentId: 1004, name: 'HH' },
    
];

analizar:

La lista de matrices se ordena de manera irregular, pero después del análisis, se puede ver que es un árbol relacionado por parentId, entonces, ¿cómo darse cuenta?

Una estructura de árbol es un objeto, tiene un nodo raíz y tiene una serie de métodos, como insertar nodos, eliminar nodos, obtener nodos, obtener profundidad, etc.

Un nodo también es un objeto con ciertos atributos, y los atributos de los nodos también pueden ser otros árboles.

Luego, primero podemos construir un nodo de objeto de nodo, cada nodo tiene atributos id, parentId, name, childNodes

Construya un árbol listTree, primero encuentre el nodo raíz en la matriz (parentId === 0)

Agregue los elementos en la matriz de lista a listTree hasta que se complete la adición y obtenga la estructura de árbol

Pasos de implementación:

1. Nodo de construcción

class Node {
    constructor(options){
        let { id, parentId, name } = options
        this.id = id || null;
        this.parentId = parentId;
        this.name = name || null;
        this.childNodes = []
    }
    getId(){
        return this.id;
    }
    ...
}

2. Construya el árbol listTree

Al crear listTree, inicialice this.root y genere this.root (generateRoot)

Dado que el nodo se agrega en la raíz, se agrega el método insertNode y se debe encontrar el parentId utilizado en la raíz al insertar

el código se muestra a continuación:

class listTree{
    constructor(arr){
        this.root = new Node(arr.find(item => item.parentId === 0))
        this.generateRoot(arr)
    }

    generateRoot(arr){
        // ...
    }
    getNodeById(id){
        // ...

    }
    insertNode(node, id){
        let targetNode = this.getNodeById(id)
        // ...
    }
    // ...
}

3. Mejorar el árbol de listas

getNodeById(id): Atraviese this.root para encontrar el elemento correspondiente.Aquí, se adopta el recorrido horizontal para reducir la cantidad de cálculo

Implementación de InsertNode: encuentre el nodo principal de acuerdo con el parentId del nodo que se insertará y luego agregue el nodo que se insertará en la matriz de nodos principales

 generar raíz: después de agregar un nodo al árbol listTree, elimine el elemento en la matriz de destino hasta que la matriz de destino esté vacía

el código se muestra a continuación:

class listTree{
    constructor(arr){
        this.root = new Node(arr.find(item => item.parentId === 0))
        this.generateRoot(arr)
    }
    generateRoot(arr){
        let arrRest = arr;
        let self = this;
        let rootIndex = arr.findIndex(item => item.parentId === 0)
        arrRest.splice(rootIndex,1)
        reduceArrRest()
        function reduceArrRest(){
            arrRest.forEach((node,index) => {
                let result = self.insertNode(new Node(node),node.parentId)
                if(result){
                    arrRest.splice(index,1)
                }
            })
            // 有剩余的元素没有插入到树结构, 继续循环插入
            if(arrRest.length > 0){
                reduceArrRest()
            }
        }
    }
    getNodeById(id){
        if(this.root && this.root.id === id){
            return this.root
        }
        let targetNode = null;
        compareNodeId(id,this.root.childNodes)
        return targetNode;
        function compareNodeId(id, NodeList){
            // 在遍历下一个节点时,先判断是否已经找到targetNode
            if(targetNode){
                return targetNode
            }
            // 先遍历NodeList数组(采取的广度遍历)
            for ( let node of NodeList){
                if(node.id === id){
                    targetNode = node
                    break
                }
            }
            // NodeList数组中没找到,再到NodeList每个node的child中查找
            if(!targetNode){
                for ( let node of NodeList){
                    if(node.childNodes.length>0){
                        compareNodeId(id,node.childNodes)
                    }
                }
            }
            return targetNode
        }

    }

    insertNode(node, id){
        let targetNode = this.getNodeById(id)
        if(targetNode){
            targetNode.childNodes.push(node)
            return true
        } else {
            return false
        }
    }
}

4, realice la conversión de la estructura del árbol en matriz

Atraviesa recursivamente la estructura de árbol

class listTree{
    constructor(arr){
        this.root = new Node(arr.find(item => item.parentId === 0))
        
    }
    // ...
    toArray(){
        let list = [];
        pushNode(this.root)
        function pushNode(node){
            let { id, parentId, name } = node;
            list.push({id, parentId, name})
            if(node.childNodes.length>0){
                for ( let nodeItem of node.childNodes){
                    pushNode(nodeItem) 
                }
            }
        }
        return list
        
    }
}

Lo anterior ha logrado las funciones básicas.

manifestación

function listToTree(arr){
    let ListTree = new listTree(arr)
    console.log(JSON.stringify(ListTree.root,null, 2))
    console.log(JSON.stringify(ListTree.toArray(),null,2))
}

listToTree(list)

resultado de la operación:

estructura de árbol:

{
  "id": 1001,
  "parentId": 0,
  "name": "AA",
  "childNodes": [
    {
      "id": 1002,
      "parentId": 1001,
      "name": "BB",
      "childNodes": [
        {
          "id": 1007,
          "parentId": 1002,
          "name": "GG",
          "childNodes": []
        },
        {
          "id": 1006,
          "parentId": 1002,
          "name": "FF",
          "childNodes": []
        }
      ]
    },
    {
      "id": 1003,
      "parentId": 1001,
      "name": "CC",
      "childNodes": [
        {
          "id": 1005,
          "parentId": 1003,
          "name": "EE",
          "childNodes": [
            {
              "id": 1009,
              "parentId": 1005,
              "name": "II",
              "childNodes": []
            }
          ]
        },
        {
          "id": 1004,
          "parentId": 1003,
          "name": "DD",
          "childNodes": [
            {
              "id": 1008,
              "parentId": 1004,
              "name": "HH",
              "childNodes": []
            }
          ]
        }
      ]
    }
  ]
}

formación:

[
  {
    "id": 1001,
    "parentId": 0,
    "name": "AA"
  },
  {
    "id": 1002,
    "parentId": 1001,
    "name": "BB"
  },
  {
    "id": 1007,
    "parentId": 1002,
    "name": "GG"
  },
  {
    "id": 1006,
    "parentId": 1002,
    "name": "FF"
  },
  {
    "id": 1003,
    "parentId": 1001,
    "name": "CC"
  },
  {
    "id": 1005,
    "parentId": 1003,
    "name": "EE"
  },
  {
    "id": 1009,
    "parentId": 1005,
    "name": "II"
  },
  {
    "id": 1004,
    "parentId": 1003,
    "name": "DD"
  },
  {
    "id": 1008,
    "parentId": 1004,
    "name": "HH"
  }
]

Resumen: hay muchas formas de estructura de árbol, pero aún se trata de nodos de árbol y métodos de árbol .

Guess you like

Origin blog.csdn.net/qdmoment/article/details/107438747