javascript封装一个单向链表

单向链表

单向链表类似于火车,有一个火车头,火车头会连接一个节点,节点上有乘客,并且这个节点会连接下一个节点,以此类推。

  • 链表的火车结构
    在这里插入图片描述

  • 链表的数据结构
    head 属性指向链表的第一个节点。
    链表中的最后一个节点指向 null。当链表中一个节点也没有的时候,head 直接指向 null。
    在这里插入图片描述

链表的数据结构

  • 给火车加上数据后的结构
    在这里插入图片描述
    链表中的常见操作

  • append(element) 向链表尾部添加一个新的项。

  • insert(position, element) 向链表的特定位置插入一个新的项。

  • get(position) 获取对应位置的元素。

  • indexOf(element) 返回元素在链表中的索引。如果链表中没有该元素就返回-1。

  • update(position, element) 修改某个位置的元素。

  • removeAt(position) 从链表的特定位置移除一项。

  • remove(element) 从链表中移除一项。

  • isEmpty() 如果链表中不包含任何元素,返回 trun,如果链表长度大于 0 则返回 false。

  • size() 返回链表包含的元素个数,与数组的 length 属性类似。

  • toString() 由于链表项使用了 Node 类,就需要重写继承自 JavaScript 对象默认的 toString 方法,让其只输出元素的值。

单向链表的封装

创建单向链表类

先创建单向链表类 LinkedList,添加基本属性,再逐步实现单向链表的常用方法。

  function LinkedList() {
      function NewNode(data) {
        this.data = data
        this.next = null
      }
      this.head = null
      this.length = 0
  }

实现 append() 方法

 LinkedList.prototype.append = function(data){
    let node = new NewNode(data)
    if(this.length === 0){
      this.head = node
    } else {
      let current = this.head
      while(current.next){
        current = current.next
      }
      current.next = node
    }
    this.length += 1
 }

过程图解

  • 首先让 currentNode 指向第一个节点。
    在这里插入图片描述
  • 通过 while 循环使 currentNode 指向最后一个节点,最后通过 currentNode.next = newNode,让最后一个节点指向新节点 newNode。
    在这里插入图片描述
    代码测试
let linkedList = new LinkedList()
// 测试 append 方法
linkedList.append("A");
linkedList.append("B");
linkedList.append("C");
console.log(linkedList);

在这里插入图片描述
实现 toString() 方法

LinkedList.prototype.toString = function(){
    let str = ''
    let current = this.head
     // 遍历所有的节点,拼接为字符串,直到节点为 null
    while(current){
      str += current.data + ' '
      current = current.next
    }
    return str
}

代码测试
// 测试 toString 方法

console.log(linkedList.toString()); //--> AA BB CC

实现 insert() 方法

      LinkedList.prototype.insert = function(position, data) {
        // 越界判断
        if(position < 0 || position > this.length) return false;
        const newNode = new Node(data);
        if(position === 0){
          newNode.next = this.head;
          this.head = newNode;
        } else {
          let index = 0;
          let current = this.head;
          let previous = null;
          while(index++ < position){
            previous = current;
            current = current.next;
          }
          newNode.next = current;
          previous.next = newNode;
        }
        this.length += 1;
      }

代码测试
// 测试 insert 方法

linkedList.insert(0, "123");
linkedList.insert(2, "456");
console.log(linkedList.toString()); //--> 123 AA 456 BB CC

实现 get() 方法
获取指定位置(position)的 data。

LinkedList.prototype.get = function(position) {
    if(position < 0 || position >= this.length) return null
    let index = 0
    let current = this.head
    while(index++ < position){
      current = current.next
    }
    return current.data
 }

代码测试
// 测试 getData 方法

console.log(linkedList.get(0)); //--> 123
console.log(linkedList.get(1)); //--> AA

实现 indexOf() 方法
indexOf(data) 返回指定 data 的 index,如果没有,返回 -1。
代码实现

LinkedList.prototype.indexOf = function(data) {
    let index = 0
    let current = this.head
    while(current){
      if(current.data === data){
        return index
      }
      current = current.next
      index += 1
    }
    return -1
}

代码测试
// 测试 indexOf 方法

console.log(linkedList.indexOf("AA")); //--> 1
console.log(linkedList.indexOf("ABC")); //--> -1

实现 update() 方法
update(position, data) 修改指定位置节点的 data。
代码实现

  LinkedList.prototype.update = function(position, newData) {
    // 越界判断
    if(position < 0 || position >= this.length) return false;
    let current = this.head;
    let index = 0;
    while(index++ < position){
      current = current.next;        
    }
    current.data = newData;
    return true;
  }

代码测试
// 测试 update 方法

linkedList.update(0, "12345");
console.log(linkedList.toString()); //--> 12345 AA 456 BB CC
linkedList.update(1, "54321");
console.log(linkedList.toString()); //--> 12345 54321 456 BB CC

实现 removeAt() 方法
removeAt(position) 删除指定位置的节点。
代码实现

LinkedList.prototype.removeAt = function(position) {
    // 越界判断
    if(position < 0 || position >= this.length) return null;
    let current = this.head;
    if(position == 0){
      this.head = this.head.next;
    } else {
      let index = 0;
      let previous = null;
      while(index++ < position){
        previous = current;
        current = current.next;
      }
      previous.next = current.next;
    }     
    this.length -= 1;   
    return current.data;
  }

代码测试
// 测试 removeAt 方法

linkedList.removeAt(3);
console.log(linkedList.toString()); //--> 12345 54321 456 CC

实现 remove() 方法
remove(data) 删除指定 data 所在的节点。
代码实现

LinkedList.prototype.remove = function(data) {
    // 获取data在列表中的位置
    const position = this.indexOf(data)
    return this.removeAt(position)
}

代码测试
// 测试 remove 方法

linkedList.remove("CC");
console.log(linkedList.toString()); //--> 12345 54321 456

实现 isEmpty() 方法
isEmpty() 判断链表是否为空。
代码实现

LinkedList.prototype.isEmpty = function() {
  return this.length == 0;
}

代码测试
// 测试 isEmpty 方法

console.log(linkedList.isEmpty()); //--> false

实现 size() 方法
size() 获取链表的长度。
代码实现

LinkedList.prototype.size = function() {
    return this.length;
}

代码测试
// 测试 size 方法

console.log(linkedList.size()); //--> 3

完整实现

function LinkedList(){
      // 内部类,节点类
      function Node(data){
        this.data = data;
        this.next = null;
      }

      // 属性
      this.head = null;
      this.length = 0;

      LinkedList.prototype.append = function(data) {
        // 创建一个新节点
        const newNode = new Node(data);
        //判断是否添加的第一个节点
        if(this.length == 0){ // 是第一个节点
          this.head = newNode;
        } else { // 不是第一个节点
          let current = this.head;
          while(current.next){ // current.next为null,表示找到了最后一个元素
            current = current.next;
          }
          current.next = newNode;
        }
        this.length += 1;
      }

      LinkedList.prototype.toString = function() {
        let current = this.head;
        let linkString = ''
        while(current){
          linkString += current.data + ' ';
          current = current.next;
        }
        return linkString;
      }

      LinkedList.prototype.insert = function(position, data) {
        // 越界判断
        if(position < 0 || position > this.length) return false;
        const newNode = new Node(data);
        if(position == 0){
          newNode.next = this.head;
          this.head = newNode;
        } else {
          let index = 0;
          let current = this.head;
          let previous = null;
          while(index++ < position){
            previous = current;
            current = current.next;
          }
          newNode.next = current;
          previous.next = newNode;
        }
        this.length += 1;
      }

      LinkedList.prototype.get = function(position) {
        // 越界判断
        if(position < 0 || position >= this.length) return null;
        let current = this.head;
        let index = 0;
          while(index++ < position){
            current = current.next;
          }
          return current.data
      }

      LinkedList.prototype.indexOf = function(data) {
        let current = this.head;
        let index = 0;
        while(current){
          if(current.data === data){
            return index;
          }
          current = current.next;
          index += 1;
        }
        return -1;
      }

      LinkedList.prototype.update = function(position, newData) {
        // 越界判断
        if(position < 0 || position >= this.length) return false;
        let current = this.head;
        let index = 0;
        while(index++ < position){
          current = current.next;        
        }
        current.data = newData;
        return true;
      }

      LinkedList.prototype.removeAt = function(position) {
        // 越界判断
        if(position < 0 || position >= this.length) return null;
        let current = this.head;
        if(position == 0){
          this.head = this.head.next;
        } else {
          let index = 0;
          let previous = null;
          while(index++ < position){
            previous = current;
            current = current.next;
          }
          previous.next = current.next;
        }     
        this.length -= 1;   
        return current.data;
      }

      LinkedList.prototype.remove = function(data) {
        // 获取data在列表中的位置
        const position = this.indexOf(data)
        return this.removeAt(position)
      }

      LinkedList.prototype.isEmpty = function() {
        return this.length == 0;
      }

      LinkedList.prototype.size = function() {
        return this.length;
      }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值