Angry Liver JavaScript Data Structure - Linked List (2)

Get into the habit of writing together! This is the 11th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .

Hello everyone, my name is Yang Chenggong.

push In the last article, we introduced the concept of linked list, and  then implemented the removeAt two methods. Although these two methods are only basic functions, the realization ideas are very critical. Because you understand the principles of these two methods, you can understand how a linked list implements an "ordered collection".

If you still feel a little dizzy, please read the previous article first: Angry Liver JavaScript Data Structure - Linked List (1)

The code that has been implemented in the previous article is as follows:

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

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

Let's continue with this part and continue to improve the linked list function.

Perfect linked list method

The methods that need to be implemented in the linked list are as follows:

  • getItemAt: Get the element at a specific position in the linked list
  • insert: Insert an element to a specific position in the linked list
  • indexOf: returns the index of the element in the linked list
  • remove: remove an element from the linked list
  • isEmpty: Determine if the linked list is empty
  • size: Determine the length of the linked list
  • toString: Returns a string of all elements of the linked list

getItemAt method

The getItemAt method is to get the element under a certain index in the linked list. It has one parameter indexrepresenting index.

The  index value is a numerical value, but the value range must be greater than or equal to zero and less than or equal to the length of the linked list, so that the index can be a valid index within the linked list.

In fact, this method is relatively simple, as long as it loops until the target element is found.

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;
}
复制代码

If the element is not found, return undefined directly.

insert method

The role of the insert method is to insert an element at any position in the linked list. It has two parameters, the first parameter itemindicates the element to be inserted, and the second parameter indexindicates the position to insert the element.

indexThe index here is the same as the index in the getItemAt method above, and the judgment logic is also the same. Make sure that the index parameter is within the valid range.

The implementation code is as follows:

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;
}
复制代码

toString method

The toString method, like the array method of the same name, puts all the elements into a string separated by commas.

Here is the code implementation:

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
}
复制代码

In fact, the logic is also the length of the circular linked list, and then splicing strings.

use linked list

The complete linked list code is relatively long, I put it in the online address, please click online test

First instantiate, add two elements:

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

Then insert Shenzhen at 1the position:

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

Then look at the index of the element:

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

Finally remove the element:

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

It turned out perfect, and you're done!

Summarize

After reading this article, the related content of the linked list is over. In fact, after learning linked lists, linked lists are a very good alternative to the performance problems of arrays we encountered before.

It is recommended that you type the code posted in the text by hand to grasp the essence.

The source of this article is the official account: Programmer Success . This is the 10th article on learning JavaScript data structures and algorithms. This series will be updated for a month in a row. Welcome to pay attention to the official account and click " Add Group " to join our learning team~

Guess you like

Origin juejin.im/post/7085747191805345800