单向链表、双向链表

本文详细介绍了链表和数组的区别,重点讲解了单向链表和双向链表的结构特点。讨论了链表的常见操作,如插入、删除、查找等,并提供了单向链表和双向链表的封装方法,包括结点定义、常用操作的实现。最后,提到了双向链表虽然实现稍复杂,但其便利性使得这些缺点变得次要。
摘要由CSDN通过智能技术生成

单向链表

链表和数组一样,都可以用于存储一系列的元素。链表的每个结点(最后一个结点除外)由一个存储元素本身的结点的数据和一个指向下一个元素的引用(指针)组成。

这有点类似于一个火车,火车的每节车厢都装着自己的东西并连接着下一节车厢(最后一节车厢除外)。

在这里插入图片描述
链表通常有一个head 属性(头指针)一直指向第一个结点,最后一个结点指向 null

数组与链表的对比

数组
  • 内存中是一块连续的空间,一般需要提前分配固定的空间大小,空间利用率不高
  • 在数组的起始位置插入和删除数据效率低,改变一个数据需要移动后续所有的数据
  • 随机访问的效率高,查找速度快
链表
  • 空间是分散的不连续的,空间利用率高
  • 任意位置的插入和删除数据的效率较高
  • 查找效率低,每次查找都需要从头结点开始查找

常见操作

  • push(data):向链表尾部添加新的结点
  • getNode(position):根据位置返回相应的结点(从0开始)
  • indexOd(data):根据结点返回对应的位置,没有则返回 -1
  • insert(data, position):向链表的特定位置插入数据
  • updateByData(data, newData):通过数据修改数据
  • updateByPosition(position, newData):通过下标修改数据
  • toString(separator = ’ '):将所有的数据输出,默认分割方式为空格
  • isEmpty():是否为空
  • size():大小

单向链表的封装

结点的定义

class Node {
   
  constructor(data) {
   
    this.data = data;
    this.next = null;
  }
}

属性的定义

constructor() {
   
  this.length = 0;
  this.head = null;
}

push方法

// 向链表末尾添加数据
push(data) {
   
  const newNode = new Node(data);
  let current = this.head;
  // 判断第一个结点是否为空
  if (this.length === 0) {
   
    this.head = newNode;
  } else {
   
    // 第二个结点不为空,则找到最后一个结点
    while (current.next) {
   
      current = current.next;
    }
    // 找到后将next 指向新的结点
    current.next = newNode;
  }
  this.length++;
}

toString方法

toString(separator = ' ') {
   
  // separator:分割符,数据之间以什么符号进行分割,默认空格
  let str = '';
  let temp = this.head;
  while (temp) {
   
    str += temp.data;
    if (temp.next) {
   
      str += separator
    }
    temp = temp.next;
  }
  return str;
}

insert方法

insert(data, position) {
   
  if (position < 0 || position > this.length) {
   
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值