JavaScript数据结构之链表

简述

链表:就类似于火车一样,一节一节的链接起来,从火车头链接到火车尾,添加数据时只能在链表尾部添加,获取想要的数据时(查找也是只能从头部到尾部一节一节的查找,不能跳节
链表

简单实现常用链表方法

append(node){}
insert(pos, node) { }
get(pos) { }
indexOf(node) { }
update(pos,node) { }
removeAt(pos) { }
remove(node) { }

node 节点

我们先定义一个 node 节点,用来存放的数据

class Node {
constructor(node){
	this.node = node;
	// 默认创建的节点 next 指向空
	this.next = null;
}

链表 Linked 实现

创建 Linked 类

class Linked {
	// 初始化时默认为空,没有数据,定义一个 head 及 length 长度为 0
	construcrot() {
		this.__head = null
		this.__length = 0
	}
}	

append 方法实现

/**
 * 向列表后添加
 * @param {*} node 节点
*/
append(node) {
  // 1.创建节点
  const newNode = new Node(node)
  // 判断当前链表是否是第一个节点
  if (this.isEmpty()) {
    this.__head = newNode
  } else {
    // 找最后一个节点
    let currentNode = this.__head
    while (currentNode.next) {
      currentNode = currentNode.next
    }
    // 最后一个节点的 next 指向最新节点
    currentNode.next = newNode
  }
  // 节点长度++
  this.__length++
}

insert 方法实现

  /**
   *  链表插入数据
   * @param {number} pos 要插入的位置 0 - 当前链表长度
   * @param {*} node 要插入的节点
   */
  insert(pos, node) {
    // 对下标判断
    if (pos < 0 || pos > this.size()) { return false }

    // 创建节点
    const newNode = new Node(node)

    // 根据位置插入数据 区分为 0 跟不为 0
    // - 0:将新节点的 next 指向下一个节点,修正 head 指向新节点
    // - 1:分别定义变量接收当前节点跟上一个节点,新节点的 next 指向当前节点,前一个节点指向新节点
    if (pos === 0) {
      newNode.next = this.__head
      this.__head = newNode
    } else {
      let index = 0
      let currentNode = this.__head
      let prevNode = null
      while (index++ < pos) {
        prevNode = currentNode
        currentNode = currentNode.next
      }
      newNode.next = currentNode
      prevNode.next = newNode
    }
    this.__length++
    return true
  }

get方法实现

通过下标位置查找对应的节点信息

  /**
   * 返回指定下标的节点
   * @param {number} pos 链表下标
   */
  get(pos) {
    // 临界值判断
    if (pos < 0 || pos >= this.size()) { return null }
    // 定义变量接收当前节点信息
    let currentNode = this.__head
    // 遍历获取到符合条件的节点信息
    let index = 0
    while (index++ < pos) {
      currentNode = currentNode.next
    }
    return currentNode.node
  }

indexOf 方法实现

  /**
   * 根据节点信息返回下标值
   * @param {*} node 节点信息
   */
  indexOf(node) {
    let currentNode = this.__head
    // 定义下标
    let index = 0
    // 遍历节点相等时 返回对应的下标
    while (currentNode) {
      if (currentNode.node === node) {
        return index
      }
      currentNode = currentNode.next
      index++
    }
  }

update方法的实现

  /**
   * 修改链表指定下标
   * @param {number} pos 要修改的下标
   * @param {*} node 修改传递的值
   * @returns 修改后的值
   */
  update(pos, node) {
    // 越界判断
    if (pos < 0 || pos >= this.size()) { return false }
    let currentNode = this.__head
    let index = 0
    // 遍历找到对应下标的数据
    while (index++ < pos) {
      currentNode = currentNode.next
    }
    // 更新数据并返回
    return currentNode.node = node
  }

removeAt 方法实现

 /**
   * 删除给定下标的数据 
   * @param {number} pos 要删除的下标指针
   */
  removeAt(pos) {
    // 临界值判断
    if (pos < 0 || pos >= this.size()) { return null }
    let currentNode = this.__head
    // 为 0 时 直接操作 head 即可
    if (pos === 0) {
      this.__head = currentNode.next
    } else {
      // 不为 0 时 需要记录当前的及上一个数据
      let prevNode = null
      let index = 0
      while (index++ < pos) {
        prevNode = currentNode
        currentNode = currentNode.next
      }
      // 将上一个数据的 next 指向当前的 next
      prevNode.next = currentNode.next
    }
    // 删除成功后 长度 -1
    this.__length -= 1
    // 返回被删除的数据
    return currentNode.node
  } 

remove方法实现

  /**
 * 删除给定数据
 * @param {*} node 传递的节点信息
 */
remove(node) {
  return this.removeAt(this.indexOf(node))
}

其他方法


	// 是否为空
  isEmpty() {
    return this.__length === 0
  }
  // 当前链表大小
  size() {
    return this.__length
  }
  // 字符串输出
  toString() {
    let currentNode = this.__head
    let result = ''
    while (currentNode) {
      result += currentNode.node + ' '
      currentNode = currentNode.next
    }
    return result
  }

下面附上完整的

/**
 * 节点 
 */
class Node {
  constructor(node) {
    this.node = node;
    this.next = null
  }
}

class Linked {

  constructor() {
    this.__head = null
    this.__length = 0
  }

  /**
   * 向列表后添加
   * @param {*} node 节点
   */
  append(node) {
    // 1.创建节点
    const newNode = new Node(node)
    // 判断当前链表是否是第一个节点
    if (this.isEmpty()) {
      this.__head = newNode
    } else {
      // 找最后一个节点
      let currentNode = this.__head
      while (currentNode.next) {
        currentNode = currentNode.next
      }
      // 最后一个节点的 next 指向最新节点
      currentNode.next = newNode
    }
    // 节点长度++
    this.__length++

  }
  /**
   * 指定位置插入节点
   * @param {number} pos 要插入的位置 0 - 当前链表长度
   * @param {*} node 要插入的节点
   */
  insert(pos, node) {
    // 对下标判断
    if (pos < 0 || pos > this.size()) { return false }

    // 创建节点
    const newNode = new Node(node)

    // 根据位置插入数据 区分为 0 跟不为 0
    if (pos === 0) {
      newNode.next = this.__head
      this.__head = newNode
    } else {
      let index = 0
      let currentNode = this.__head
      let prevNode = null
      while (index++ < pos) {
        prevNode = currentNode
        currentNode = currentNode.next
      }
      newNode.next = currentNode
      prevNode.next = newNode
    }
    this.__length++
    return true
  }

  /**
   * 返回指定下标的节点
   * @param {number} pos 链表下标
   */
  get(pos) {
    // 临界值判断
    if (pos < 0 || pos >= this.size()) { return null }
    let currentNode = this.__head
    let index = 0
    while (index++ < pos) {
      currentNode = currentNode.next
    }
    return currentNode.node
  }
  /**
   * 根据节点信息返回下标值
   * @param {*} node 节点信息
   */
  indexOf(node) {
    let currentNode = this.__head
    let index = 0
    while (currentNode) {
      if (currentNode.node == node) {
        return index
      }
      currentNode = currentNode.next
      index++
    }
  }
  /**
   * 修改链表指定下标
   * @param {number} pos 要修改的下标
   * @param {*} node 修改传递的值
   * @returns 修改后的值
   */
  update(pos, node) {
    // 越界判断
    if (pos < 0 || pos >= this.size()) { return false }
    let currentNode = this.__head
    let index = 0
    // 遍历找到对应下标的数据
    while (index++ < pos) {
      currentNode = currentNode.next
    }
    // 更新数据并返回
    return currentNode.node = node
  }
 /**
   * 删除给定下标的数据 
   * @param {number} pos 要删除的下标指针
   */
  removeAt(pos) {
    // 临界值判断
    if (pos < 0 || pos >= this.size()) { return null }
    let currentNode = this.__head
    // 为 0 时 直接操作 head 即可
    if (pos === 0) {
      this.__head = currentNode.next
    } else {
      // 不为 0 时 需要记录当前的及上一个数据
      let prevNode = null
      let index = 0
      while (index++ < pos) {
        prevNode = currentNode
        currentNode = currentNode.next
      }
      // 将上一个数据的 next 指向当前的 next
      prevNode.next = currentNode.next
    }
    // 删除成功后 长度 -1
    this.__length -= 1
    // 返回被删除的数据
    return currentNode.node
  } 

  /**
   * 删除给定数据
   * @param {*} node 传递的节点信息
   */
  remove(node) {
    return this.removeAt(this.indexOf(node))
  }
  isEmpty() {
    return this.__length === 0
  }
  size() {
    return this.__length
  }
  toString() {
    let currentNode = this.__head
    let result = ''
    while (currentNode) {
      result += currentNode.node + ' '
      currentNode = currentNode.next
    }
    return result
  }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

放逐的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值