Javascript中的链表

单向链表
/**
 * @desc 单向链表
 */

class Node { // 链表节点
  constructor(element) {
    this.data = element  // 节点数据
    this.next = null  // 下一个节点的指针
  }
}

class NodeList { // 链表
  constructor(item) {
    this.head = new Node(item); //初始化链表的头节点
  }

  /**
   * @descript 插入元素
   * @param {需要插入的元素} newItem
   * @param {插入到某一个元素之后} beforeItem
   */
  insertInNext(newItem, beforeItem) {
    let newNode = new Node(newItem)
    if(beforeItem) {
      let currNode = this.find(beforeItem)
      newNode.next = currNode.next
      currNode.next = newNode
    } else {
      let lastNode = this.findLastNode()
      lastNode.next = newNode
    }
  }

  /**
   * @description 删除元素
   * @param {删除的元素} newItem
   */
  remove(item) {
    let preNode = this.findPreNode(item)
    if(preNode.next != null) {
      preNode.next = preNode.next.next
    }
  }

  /**
   * @description 查找元素的节点
   * @param {查找的元素} item
   */
  find(item) { //  根据元素查找节点
    let currNode = this.head;
    while (currNode.element !== item && currNode) {
      if (currNode.next) {
        currNode = currNode.next;
      } else {
        currNode = null;
      }
    }
    return currNode;
  }

  /**
   * @description 查找最后一个节点
   */
  findLastNode() {
    let currNode = this.head
    while(currNode.next) {
      currNode = currNode.next
    }
    return currNode
  }

  /**
   * @description 查找元素的前一个节点
   * @param {查找的元素} item
   */
  findPreNode(item) {
    let currNode = this.head
    while(currNode && currNode.next.element !== item) {
      if(currNode.next) {
        currNode = currNode.next
      } else {
        currNode = null
      }
    }
    return currNode
  }

  toString() {
    let currNode = this.head
    let strList = []
    while(currNode.next) {
      strList.push(JSON.stringify(currNode.element))
      currNode = currNode.next
    }
    strList.push(JSON.stringify(currNode.element))
    return strList.join('->')
  }
}

let ming = { name: '小明', score: 100 },
  hongs = { name: '小红', score: 88 },
  jun = { name: '小军', score: 66 },
  li = { name: '小李', score: 50 };

let nList = new NodeList(ming);

// nList.insertInNext(hongs);
// nList.insertInNext(li);
// nList.insertInNext(jun, hongs);

console.log(nList);
双向链表
class Node {
  constructor(data) {
    // data为当前节点所储存的数据
    this.data = data
    // next指向下一个节点
    this.next = null
    // prev指向前一个节点
    this.prev = null
  }
}

class DoublyLinkedList {
  constructor() {
    // 双向链表的开头
    this.head = null
    // 双向链表的结尾
    this.tail = null
  }

  add(item) {
    // 实例化一个节点
    let node = new Node(item)

    // 如果当前链表还没有头
    if(!this.head) {
      this.head = node
      this.tail = node
    }
    // 如果当前链表已经有了头,则只需要在尾部加上该节点
    else {
      node.prev = this.tail
      this.tail.next = node
      this.tail = node
    }
  }

  addAt(index, item) {
    let current = this.head

    let counter = 1
    let node = new Node(item)

    // 如果在头部插入
    if(index === 0) {
      this.head.prev = node
      this.next = this.head
      this.head = node
    }

    // 如果在非头部插入,则需要从头开始找寻插入位置
    else {
      while(current) {
        current = current.next
        if(counter === index) {
          node.prev = current.prev
          current.prev.next = node
          node.next = current
          current.prev = node
        }
        counter++
      }
    }
  }

  remove(item) {
    let current = this.head

    while(current) {
      // 找到了目标节点
      if(current.data === item) {
        // 目标链只有当前目标项,即目标节点既是链表头又是链表尾
        if(current == this.head && current == this.tail) {
          this.head = null
          this.tail = null
        }

        // 目标节点为链表头
        else if(current == this.head) {
          this.head = this.head.next
          this.head.prev = null
        }

        // 目标节点为链表尾
        else if(current == this.tail) {
          this.tail = this.tail.prev
          this.tail.next = null
        }

        // 目标节点在链表首尾之间,即中部
        else {
          current.prev.next = current.next
          current.next.prev = current.prev
        }
      }
      current = current.next
    }
  }

  removeAt(index) {
    // 都是从头开始遍历
    let current = this.head
    let counter = 1

    // 删除链表头部
    if(index === 0) {
      this.head = this.head.next
      this.head.prev = null
    }
    else {
      while(current) {
        current = current.next
        // 如果目标节点在链表尾部
        if(curent == this.tail) {
          this.tail = this.tail.prev
          this.tail.next = null
        }
        else if(counter === index) {
          current.prev.next = current.next
          current.next.prev = current.prev
          break
        }
        counter++
      }
    }
  }

  reverse() {
    let current = this.head
    let prev = null

    while(current) {
      let next = current.next

      // 前后倒置
      current.next = prev
      current.prev = next

      prev = current
      current = next
    }

    this.tail = this.head
    this.head = prev
  }

  swap(index1, index2) {
    // 使index1始终小于index2,方便后面查找交换
    if(index1 > index2) {
      return this.swap(index2, index1)
    }

    let current = this.head
    let counter = 0
    let firstNode

    while(current !== null) {
      // 找到第一个节点,并储存起来
      if(counter === index1) {
        firstNode = current
      }

      // 找到第二个节点,并进行数据交换
      else if(counter === index2) {
        // ES提供了更简洁的交换数据的方式,这里用传统方式实现更为直观
        let temp = current.data
        current.data = firstNode.data
        firstNode.data = temp
      }

      current = current.next
      counter++
    }
    return true
  }

  isEmpty() {
    return this.length() < 1
  }

  length() {
    let current = this.head
    let counter = 0
    while(current !== null) {
      counter++
      current = current.next
    }
    return counter
  }

  traverse(fn){
    let current = this.head
    while(current !== null) {
      fn(current)
      current = current.next
    }
    return true
  }

  search(item) {
    let current = this.head
    let counter = 0

    while(current) {
      if(current.data == item) {
        return counter
      }
      current = current.next
      counter++
    }
    return false
  }
}
参考:

单向链表
[前端开发核心知识进阶]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值