一、数组和链表的特点

1.1数组

  • 优点:直接通过下标访问元素

  • 缺点:内存空间连续,大小固定,扩容、插入和删除性能低

1.2链表

  • 优点:内存空间不必连续,指针连接,大小不固定,插入和删除性能高
  • 缺点:查找性能低

二、链表的实现

1.1链表的属性

  • head

  • data、next

1.2链表的实现

function LinkedList() {
  this.head = null;
  this.length = 0;
}
LinkedList.prototype = {
  constructor: LinkedList,
  Node: function Node(ele) {
    this.data = ele;
    this.next = null;
  },
  /* 向列表尾部添加一个新的项 */
  append(ele) {
    const node = new this.Node(ele);
    if (this.length === 0) {
      this.head = node;
      this.length++;
      return;
    }
    let prev = this.head;
    while (prev.next) {
      prev = prev.next;
    }
    prev.next = node;
    this.length++;
  },
  /* 向列表特定位置插入一个新的项 */
  insert(position, ele) {
    position--;
    const node=new this.Node(ele),
    prev = this.get(position),
    next=prev.next;
    prev.next=node;
    node.next=next;
    this.length++;
  },
  /* 返回元素在列表中的索引 */
  indexOf(ele){
    let i=0;
    let find=this.head;
    while(find!=null&&find.data!=ele){
      i++;
      find=find.next;
    }
    
    return i>=this.length?-1:i;

  },
  /* 修改某个位置的元素 */
  update(position,data){
    this.get(position).data=data;
  },
  /* 移除某个位置的元素 */
  removeAt(position){
    if(position>this.length-1){
      throw new Error('位置越界');
    }
    if(position===0){
      this.head=this.head.next;
    }else if(position===this.length-1){
      this.get(this.length-2).next=null;
    }else{
      this.get(position-1).next=this.get(position+1);
    }
    this.length--;
  },
  /* 移除某个元素 */
  remove(ele){
    let prev=this.head,
      next=prev;
    while(next&&next.data!=ele){
      prev=next;
      next=next.next;
    }
    if(!next){
      console.log(`${ele}不在列表中,移除失败`);
      return;
    }
    this.removeAt(this.indexOf(next.data));
    this.length--;
  },
  size(){
    return this.length;
  },
  isEmpty(){
    return this.length==0;
  },
  /* 获取对应位置的元素 */
  get(i) {
    if (i > this.length-1||i<0) {
      throw new Error('位置越界');
      return;
    }
    let index = 0,
      ele = this.head;
    while (i != index) {
      index++;
      ele = ele.next;
    }
    return ele;
  },
  toString() {
    let prev = this.head;
    let str = `${prev&&prev.data}->`;
    while (prev&&prev.next) {
      prev = prev.next;
      str += `${prev.data}->`;
    }
    return str.substr(0, str.length - 2);
  },
  clear(){
    this.head=null;
  }
}
/*const list = new LinkedList();
list.append('a');
list.append('b');
list.append('c');
list.append('d');
list.append('e');
console.log(list.toString());
list.insert(1,'insert');
console.log(list.toString());
list.update(5,'INSERT');
console.log(list.toString());
list.removeAt(5);
console.log(list.toString());
list.remove('b');
console.log(list.toString());
list.clear();
console.log(list.toString());*/