The list! More suitable than the array of operations on data structures deletions

What is the list?

  • Compare lists and arrays: In most languages, size of the array is fixed, added from the start or middle of the array or remove elements very high cost because of the need to move elements.
  • Each element of a linked list in memory is not placed consecutively, and its left and right sides of the elements does not matter.
  • Each element has its own node at a reference point and a storage element's composition.
  • With respect to the array, the list of benefits that add or delete elements of time without moving other elements.
  • In the array we can directly access any element in any position, but in order to access the list of one element, you need the required elements from the start (head of the list) iterates the list until you find.

For chestnut: a train is composed of a series of compartments. Each car or wagon are connected to each other, you can easily separate a trunk, to change its position, add or remove it. Each car is equivalent to the elements of the list, between the docking compartment buckle is a reference element.

Creating a class list

const defaultCompare = function (a, b) { // 一个比较函数 if (a === b) return 0; return a < b ? -1 : 1; } class Node { // 一个助手类,用来表示我们想要添加到链表中的元素 constructor(element, next) { this.element = element; // 元素的值 this.next = next; // 指向链表中下一个元素的指针 } } class LinkedList { // 链表类 constructor(equalsFn = defaultEquals) { this.equalsFn = equalsFn; // 比较链表中的元素是否相等,默认a===b this.count = 0; // 链表中的元素数量 this.head = undefined; // 表头 } } 

Create a list of several methods

  1. Add an element to the end of the list
push(element) {
    const node = new Node(element); // 创建node项
    let current; // 声明一个指向链表中的临时项 if (this.head == undefined) { // 如果链表头为空,即链表为空 this.head = node; // 直接让表头等于当前元素就好了,下一项(next)未传,因此为undefined } else { current = this.head; // 先让current等于第一个元素 while (current.next != null) { // 只要当前元素的下一项元素不是假的,便继续循环 current = current.next; } current.next = node; // 找到最后一个元素后,让它的下一个元素等于传进来的元素 } this.count++;// 最后把总长度自增就好了 } 
  • First class initialization node, the element as the value passed.
  • Add the tail elements are divided into two cases, one is the list is empty, one is there value chain, while the latter, because the reference list only the head of the list, so when you add an element to the tail of the list, we need a circular list, until you find the last element, for which we need a linked list variable current entry point.
  • If the head of the list did not indicate the value of the first element added to the list, directly to the header is equal to the current element is like, the next item of reference (next) does not pass, therefore undefined
  • Then is the second case, let current equal to the head of the list, and then iterate through the list until you find the last element, then it is to make reference to the last element pointing to the next item you want to add a node to the list.
  • Finally, the total length of the increment just fine
  1. Removing an element from a particular location
removeAt(index) {
    if (index >= 0 && index < this.count) { // 检查越界值
      let current = this.head; if (index === 0) { // 如果是表头 this.head = current.next; // 就让表头等于下一个引用 } else { let previous; for (let i = 0; i < index; i++) { // 嗯,开始迭代把~~~ previous = current; current = current.next; } previous.next = current.next; // 上一个的下一个等于现在的下一个,,,(现在内心os:我是谁,我在哪???)当前节点就会被丢弃在计算机内存中,等着被垃圾回收器移除 } this.count--;// 长度自减 return current.element; // 返回移除的元素 } return undefined; } 
  • Since this method need to remove the element index (position), we need to verify that the index is from 0 to the length between the linked list. If not, it returns undefined.
  • If you remove the first element of the list, we should let the head pointing to the second element of the list. We will create a reference to the current variable first element of the list. Such current variable is a reference to the first element of the list. If this time is assigned if the head current.next, the first element will be removed. We can also directly assign the head to head.next, do not use current.
  • If we are to be removed is the last element of the list or in the middle of an element. We need to iterate the list until you reach the target position.
  • After reaching the target position, current will become variable node we want to remove from the list. Therefore, the current element is removed from the list, to do is to previous.next and current.next linked. Thus, the current node will be discarded in the computer memory, waiting to be garbage collector.
  1. Loop iterates until the target location list
getElementAt(index) {
    if (index >= 0 && index <= this.count) return undefined; // 检查越界值 let node = this.head; // 默认等于表头 for (let i = 0; i < index && node != null; i++) { // 嗯,开始迭代把~~~ node = node.next; } return node; } 
  • In the remove method, we need to iterate through the list until you reach our destination index index (position). Fragment recycled to the target index in the list will be frequently used in the process. Therefore, we can separate this part logically independent way, so that you can reuse it in different places.
  • Then we can use the method getElementAt just created to reconstruct the remove method
if(index===0){
    // 第一个位置的逻辑
} else {
    const previous = this.getElementAt(index - 1); current = previous.next; previous.next = current.next; } this.count--; 
  1. Insert element in any position
insert(element, index) {
    if (index >= 0 && index <= this.count) { // 边界处理
      const node = new Node(element); // 实例化当前元素 if (index === 0) { // 如果插在表头 const current = this.head;// 声明一个变量,等于原来的表头 node.next = current;// 传入元素的下一个引用等于current this.head = node; // 当前表头等于传入的元素 } else { const previous = this.getElementAt(index - 1);// 找到传入索引的上一个值 previous.next = node;// 上一个的引用等于传入的值 node.next = previous.next;// 传入值的下一个引用等于上一个的下一个引用 } this.count++;// 总长度自增 return true; // 最后返回true } return false; // 如果位置未找到返回false } 
  • Practice what to do first boundary processing.
  • First, if it is inserted in the list head, let's declare a variable equal to the original list head, let the insert element to a reference current is equal to the original variables, and let the meter is equal to the current element passed.
  • If it is the end or we need to find the location of a target element method with getElementAt in the middle of the list, and then let the incoming equal to a reference value. Then passed under a reference value equal to a next reference. Finally, we must remember to add a total length, returns true
  1. Returns the position of an element
indexOf(element) {
    let current = this.head; // 等于表头
    for (let i = 0; i < this.size() && current != null; i++) { // 循环迭代所有元素 if (this.equalsFn(element, current.element)) { // 找到和当前元素相等的第一个元素 return i;// 返回索引 } current = current.next;// 如果不相等,就继续迭代下一个 } return -1; // 如果都没找到,就返回-1 } 
  • indexOf method of receiving a value of the element, if it is found in the list, it returns the position of the element, otherwise -1.
  • As always, you need a variable to help us iterate through the list. This variable is the current, its initial value is the head
  • Then iterative element, starting from the head of the list until the list length. To ensure that does not happen when you run error, we can verify current variable is null or undefined.
  • Loop iterates until it finds all the elements and the first element equal to the current element and returns its location
  • If not found, returns -1
  1. Remove the element passed
remove(element) { 
    const index = this.indexOf(element); // 先找到这个元素的第一个索引
    return this.removeAt(index); // 利用删除指定位置元素的方法,搞掉它 } 
  • We've got a method used to remove a given element's position, has also been indexOf methods. Using the indexOf method to find its position, the position of the element Removes the specified methods, get rid of it.
  1. Check if empty, length, acquiring the list head
isEmpty() {
    return this.size() === 0;
  }
  size() {
    return this.count; } getHead() { return this.head; } 
  • It is quite simple.
  1. Convert all the elements into a string
toString() {
    if (this.head == null) { // 如果列表为空,就返回空字符串
      return ''; } let objString = `${this.head.element}`; // 创建一个变量,先让他等于表头的元素 let current = this.head.next; // 等于表头的下一个引用 for (let i = 1; i < this.size() && current != null; i++) { // 循环迭代所有元素 objString = `${objString},${current.element}`; // 让这个字符串等于原来的字符串加上当前元素 current = current.next; // 当前元素等于当前的下一个引用 } return objString; // 最后把这个字符串返回 } 
  • First, if the list is empty, we return an empty string.
  • If we have a string value with the value of the first element of the list returned by the last method to initialize.
  • Then we iterate over all other elements of the list, add the element value to the string.
  • Finally, the return string.

At last

  • Today's hand notes on the record here, and so I will have time to write an article about various enhanced version of the list. In short, after I finish reading this chapter that compared to an array of linked lists, more suitable for additions and deletions operation, while the array is more suitable for storing some of the ordered set of relatively fixed.

Guess you like

Origin www.cnblogs.com/xingyongwang/p/11125934.html