Estructura de datos JavaScript de Angry Liver - Lista vinculada (2)

¡Acostúmbrate a escribir juntos! Este es el día 11 de mi participación en el "Nuevo plan diario de Nuggets · Desafío de actualización de abril", haga clic para ver los detalles del evento .

Hola a todos, mi nombre es Yang Chenggong.

push En el último artículo, presentamos el concepto de lista enlazada y  luego implementamos los removeAt dos métodos. Aunque estos dos métodos son solo funciones básicas, las ideas de realización son muy críticas. Debido a que comprende los principios de estos dos métodos, puede comprender cómo una lista vinculada implementa una "colección ordenada".

Si todavía se siente un poco mareado, lea primero el artículo anterior: Estructura de datos de JavaScript de Angry Liver - Lista vinculada (1)

El código que se ha implementado en el artículo anterior es el siguiente:

class Node {
  constructor(value) {
    this.value = value;
    this.next = undefined;
  }
}

class linkedList {
  constructor() {
    this.count = 0;
    this.head = undefined;
  }
  push(item) {
    // 向末尾添加元素
  }
  removeAt(index) {
    // 移除指定位置的元素
  }
}
复制代码

Continuemos con esta parte y sigamos mejorando la función de lista enlazada.

Método de lista enlazada perfecta

Los métodos que deben implementarse en la lista enlazada son los siguientes:

  • getItemAt: Obtiene el elemento en una posición específica en la lista enlazada
  • insert: Inserta un elemento en una posición específica en la lista enlazada
  • indexOf: devuelve el índice del elemento en la lista enlazada
  • remove: elimina un elemento de la lista enlazada
  • isEmpty: Determinar si la lista enlazada está vacía
  • size: determina la longitud de la lista enlazada
  • toString: Devuelve una cadena de todos los elementos de la lista enlazada

método getItemAt

El método getItemAt es obtener el elemento bajo un cierto índice en la lista enlazada. Tiene un parámetro que indexrepresenta índice.

El  index valor es un valor numérico, pero el rango de valores debe ser mayor o igual a cero y menor o igual a la longitud de la lista vinculada, para que el índice pueda ser un índice válido dentro de la lista vinculada.

De hecho, este método es relativamente simple, siempre y cuando se repita hasta que se encuentre el elemento de destino.

getItemAt(index) {
  if(index >= 0 && index <= this.count) {
    let current = this.head
    for(let i = 0; i < index; i++) {
      current = current.next
    }
    return current
  }
  return undefined;
}
复制代码

Si no se encuentra el elemento, devuelve indefinido directamente.

método de inserción

La función del método de inserción es insertar un elemento en cualquier posición de la lista enlazada. Tiene dos parámetros, el primer parámetro itemindica el elemento a insertar, y el segundo parámetro indexindica la posición para insertar el elemento.

indexEl índice aquí es el mismo que el índice en el método getItemAt anterior, y la lógica de juicio también es la misma. Asegúrese de que el parámetro de índice esté dentro del rango válido.

El código de implementación es el siguiente:

insert(item, index) {
  if(index >= 0 && index <= this.count) {
    let node = new Node(item)
    let current = this.head;
    if(index == 0) {
      node.next = current
      this.head = node
    } else {
      let previous = this.getItemAt(index - 1)
      current = previous.next
      node.next = current
      previous.next = node
    }
    this.count++;
    return true;
  }
  return false;
}
复制代码

代码中,发现和上一篇的 removeAt 方法有一个共同点,就是先要判断 index 是否为 0,然后再分情况处理。

如果为零,则只需要新建一个元素,将新元素的 next 指向原来的表头,然后再将 head 属性赋值为新元素即可。

如果大于零,则需要获取当前元素 current 和前一个元素 previous。前一个元素直接用上面写的 getItemAt 方法获取即可。

接着将新元素的 next 指向索引位置的元素,再将前一个元素的 next 属性指向新元素,这样就在两个元素 previous 和 current 之间链接了新元素。

最后,再将表示链表长度的 count 属性自增一。

indexOf 方法

indexOf 方法与数组的同名方法作用是一样的,参数是一个元素,然后在链表中寻找这个元素的位置,找到就返回索引,找不到返回 -1

这里有一个关键点:元素参数要与链表中的参数做对比,判断是否相等。如果元素是基本类型,那直接判断等于即可。如果元素是引用类型,则不同数据的判断方式不同,就要自定义判断的方法了。

所以我们要修改下 linkedList 类,添加一个自定义方法,接受类初始化时的传参:

class linkedList {
  constructor(whereFn) {
    let defun = (value, next)=> value === next;
    this.equalFn = whereFn || defun
  }
}
复制代码

这里的参数 whereFn 就是一个自定义的对比元素的函数。

有了 equalFn 属性,indexOf 方法就好实现了:

indexOf(item) {
  let current = this.head;
  for(let i = 0; i < this.count; i++) {
    if(this.equalFn(item, current.value)) {
      return i;
    }
    current = current.next;
  }
  return -1;
}
复制代码

循环便利,用自定义的方法判断两个元素是否相等,相等则终止循环返回索引。

remove 方法

remove 方法的作用是删除一个元素,参数直接是这个元素,需要我们在链表中找到并删除。

有了上面的 indexOf 方法,remove 方法实现起来就更简单了:

remove(item) {
  let index = this.indexOf(item);
  return this.removeAt(index)
}
复制代码

isEmpty, size 方法

这几个方法更简单:

isEmpty() {
  return this.count == 0
}
size() {
  return this.count;
}
复制代码

método toString

El método toString, como el método de matriz del mismo nombre, coloca todos los elementos en una cadena separados por comas.

Aquí está la implementación del código:

toString() {
  if(!this.head) {
    return ''
  }
  let current = this.head
  let string = current.value
  for(let i = 0; i < this.count; i++) {
    string += `,${current.value}`
    current = current.next
  }
  return string
}
复制代码

De hecho, la lógica es también la longitud de la lista circular enlazada y luego las cadenas de empalme.

usar lista enlazada

El código completo de la lista vinculada es relativamente largo, lo puse en la dirección en línea, haga clic en prueba en línea

Primero crea una instancia, agrega dos elementos:

let linked = new linkedList();
linked.push("北京");
linked.push("上海");
console.log(linked.toString()); // 北京,上海
复制代码

Luego inserte Shenzhen en 1la :

linked.insert('深圳', 1)
console.log(linked.toString()); // 北京,深圳,上海
复制代码

Luego mira el índice del elemento:

console.log(linked.indexOf('上海')); // 2
console.log(linked.indexOf('武汉')); // -1
复制代码

Finalmente elimine el elemento:

linked.remove('深圳');
console.log(linked.toString()); // 北京,上海
复制代码

Quedó perfecto, ¡y listo!

Resumir

Después de leer este artículo, el contenido relacionado de la lista vinculada ha terminado. De hecho, después de aprender las listas enlazadas, las listas enlazadas son una muy buena alternativa a los problemas de rendimiento de las matrices que encontramos antes.

Se recomienda que escriba a mano el código publicado en el texto para captar la esencia.

La fuente de este artículo es la cuenta oficial: Programmer Success . Este es el décimo artículo sobre el aprendizaje de estructuras de datos y algoritmos de JavaScript. Esta serie se actualizará durante un mes seguido. Bienvenido a prestar atención a la cuenta oficial y haga clic en " Agregar grupo " para unirse a nuestro equipo de aprendizaje ~

Supongo que te gusta

Origin juejin.im/post/7085747191805345800
Recomendado
Clasificación