js 双向链表 01

文章目录

  • 认识双向链表
  • 图解
  • 双向链表结构封装
  • 双向链表的常见操作
    • append实现 -- 尾部添加项
    • 字符串方法实现
    • insert实现 -- 指定位置插入

认识双向链表

js 双向链表 01_第1张图片
js 双向链表 01_第2张图片

图解

js 双向链表 01_第3张图片

双向链表结构封装

代码

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Documenttitle>
head>
<body>
  <script>
    function DoublyLinkedList(){
      // 属性
      this.head = null;
      this.tail = null;
      this.length = 0;

      // 内部类
      function Node(data){
        this.data = data;
        this.prev = null;
        this.next = null;
      }
    }
  script>
body>
html>

菜鸟反正现在感觉写这个结构封装很轻松,因为只要明白了需要哪些参数指向哪里,然后内部类就是节点的封装,里面封装的就是节点内容!

双向链表的常见操作

js 双向链表 01_第4张图片
其实和单向链表差不多,只是封装的方式不同,提供给外面使用的方法大致是一致的,毕竟都是链表,都是增删改查!其实你又会发现链表的方法又和数组的很像,毕竟链表就是用来在某些时候代替数组而使操作更加简单!

append实现 – 尾部添加项

菜鸟看视频,结果发现这个没有视频,只好自己写了,思路和单链表一样,后面找到了视频代码,发现自己写复杂了!

我的代码

// 1 append方法
DoublyLinkedList.prototype.append = function(data){
  // 创建节点
  let newNode = new Node(data);

  // 判断插入地点
  if(this.length === 0){
    this.head = newNode;
    this.tail = newNode;
  }else{
    let current = this.head;
    // 找到最后一个节点
    while(current.next){
      current = current.next;
    }
    current.next =newNode;
    newNode.prev = current;
  }

  // length+1
  this.length += 1;
}

视频代码

// 2 append2方法 视频
DoublyLinkedList.prototype.append2 = function(data){
  // 1 创建节点
  let newNode = new Node(data);

  // 2 判断添加的是否是第一个节点
  if(this.length === 0){
    this.head = newNode;
    this.tail = newNode;
  }else{
    newNode.prev = this.tail;
    this.tail.next =newNode;
    this.tail = newNode;
  }

  // length+1
  this.length += 1;
}

其实这里是菜鸟没有跳出单链表的思维,毕竟这里都已经有一个参数指向最后一个节点了,结果菜鸟还在靠循环去找,哈哈哈哈!

字符串方法实现

代码

// 3 backwardString方法 -- 从前往后
DoublyLinkedList.prototype.backwardString = function(){
  // 定义变量
  let current = this.head;
  let string = '';

  // 依次向后遍历
  while(current){
    string += current.data + " ";
    current = current.next;
  }

  return string;
}

// 4 forwardString方法 -- 从后往前
DoublyLinkedList.prototype.forwardString = function(){
  let current = this.tail;
  let string = '';
  // 依次向前遍历
  while(current){
    string += current.data + " ";
    current = current.prev;
  }
  return string;
}

// 5 toStirng方法
DoublyLinkedList.prototype.toString = function(){
  return this.backwardString();
}

insert实现 – 指定位置插入

这个相比于单链表,要考虑更多的指针指向,更多的情况(多了一个tail指针),但是利用好tail、head,可以简化代码!还有就是要考虑指针的变动,如果变动了而使后面的无法找到就要改变顺序!

代码

// 6 insert方法
DoublyLinkedList.prototype.insert = function(position,data){
  // 1 越界判断
  if(position < 0 || position > this.length) return false;

  // 创建节点
  let newNode = new Node(data);

  // 判断原来的链表是否为空
  if(this.length === 0){
    this.head = newNode;
    this.tail = newNode;
  }else{
    // 判断position是否为0
    if(position === 0){
      newNode.next = this.head;
      // 写单链表多了就容易忘记这一步
      this.head.prev = newNode; 
      this.head = newNode;
    }else if(position === this.length){
      // 这一步和单向链表不一样,不能和插入中间归为一类,因为tail
      // 也不需要调用this.append,重复了一部分操作
      newNode.prev = this.tail;
      this.tail.next =newNode;
      this.tail = newNode;
    }else{
      let current = this.head;
      let index = 0;
      while(index++ < position){
        current = current.next;
      }
      // 修改指针 -- 4个 -- 第二和第四的顺序不能乱了(其它无所谓),不然会因为指向改变而出错
      newNode.next = current;
      current.prev.next = newNode;
      newNode.prev = current.prev;
      current.prev = newNode;
    }
  }

  this.length += 1;
  return true;
}

你可能感兴趣的:(#,数据结构,算法,双向链表)