JS数据结构和算法3

110 阅读1分钟

JS数据结构和算法

认识双向链表

image.png

image.png

image.png

双向链表封装

  1. 属性和内部类
<script>
    // 封装双向链表
    function DoublyLinkedList() {
      // 内部类:节点类
      function Node(data) {
        this.data = data;
        this.prev = null;
        this.next = null;
      }

      // 属性
      this.head = null; // 指向第一个节点
      this.tail = null; // 指向最后一个节点
      this.length = 0;  // 链表长度
    }
  </script>
  1. 双向链表方法

image.png

  1. 双向链表方法实现
<!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>双向链表</title>
</head>
<body>
  <script>
    // 封装双向链表
    function DoublyLinkedList() {
      // 内部类:节点类
      function Node(data) {
        this.data = data;
        this.prev = null;
        this.next = null;
      }

      // 属性
      this.head = null; // 指向第一个节点
      this.tail = null; // 指向最后一个节点
      this.length = 0;  // 链表长度

      // 1. append(data) 添加节点
      DoublyLinkedList.prototype.append = function (data) {
        var newNode = new Node(data);
        if (this.length === 0) {
          this.head = newNode;
          this.tail = newNode;
        } else {
          newNode.prev = this.tail;
          this.tail.next = newNode;
          this.tail = newNode;
        }
        this.length += 1;
      }

      // 2. toString() 将链表内容拼接成字符串输出
      // 2.1 forwardString() 向前遍历
      DoublyLinkedList.prototype.forwardString = function () {
        var current = this.tail;
        var forwardStr = '';
        while (current) {
          forwardStr += ' ' + current.data;
          current = current.prev;
        }
        return forwardStr.trim();
      }

      // 2.2 backString() 向后遍历
      DoublyLinkedList.prototype.backString = function () {
        var current = this.head;
        var backStr = '';
        while (current) {
          backStr += ' ' + current.data;
          current = current.next;
        }
        return backStr.trim();
      }

      // 3. insert(position, data) 插入节点
      DoublyLinkedList.prototype.insert = function (position, data) {
        // 1. position 有效值判定
        if (position < 0 || position > this.length) {
          return false;
        }

        // 2. 创建新节点
        var newNode = new Node(data);

        // 3. 判断链表是否为空
        if (this.length === 0) {
          this.head = newNode;
          this.tail = newNode;
        } else {
          if (position === 0) {
            // 在开头插入
            newNode.next = this.head;
            this.head.prev = newNode;
            this.head = newNode;
          } else if (position === this.length) {
            // 在结尾插入
            newNode.prev = this.tail;
            this.tail.next = newNode;
            this.tail = newNode;
          } else if(position <= this.length/2) {
            // 在中上位置插入
            console.log("中上位置")
            var index = 0;
            var current = this.head;
            while (index < position) {
              current = current.next;
              index += 1;
            }
            newNode.prev = current.prev;
            current.prev.next = newNode;
            newNode.next = current;
            current.prev = newNode;
          } else {
            // 在中下位置插入
            console.log("中下位置")
            var index = this.length - 1;
            var current = this.tail;
            while (index > position) {
              current = current.prev;
              index -= 1;
            }
            newNode.prev = current.prev;
            current.prev.next = newNode;
            newNode.next = current;
            current.prev = newNode;
          }
        }
        this.length += 1;
        return true;
      }

      // 4. get(position)
      DoublyLinkedList.prototype.get = function (position) {
        // 1. 越界判断
        if (position < 0 || position >= this.length || typeof position !== 'number') {
          return false;
        }

        // 2. 获取元素
        var current = this.head;
        var index = 0;
        while (index < position) {
          current = current.next;
          index += 1;
        }
        return current.data;
      }

      // 5. indexOf(data)
      DoublyLinkedList.prototype.indexOf = function (data) {
        var current = this.head;
        // if (this.length === 0) {
        //   return -1;
        // }
        var index = 0;
        while (current) {
          if (current.data === data) {
            return index;
          }
          current = current.next;
          index += 1;
        }
        return -1;
      }

      // 5. update(position, data)
      DoublyLinkedList.prototype.update = function (position, data) {
        // 1. position 有效值判断
        if (position < 0 || position >= this.length || typeof position !== 'number') {
          return false;
        }

        // 2. 获取元素
        var current = this.head;
        var index = 0;
        while (index < position) {
          current = current.next;
          index += 1;
        }

        // 3. 修改元素
        current.data = data;

        return true;
      }

      // 5. removeAt(position)
      DoublyLinkedList.prototype.removeAt = function (position) {
        // 1. position 有效值判断
        if (position < 0 || position >= this.length || typeof position !== 'number') {
          return null;
        }

        // 2. 判断是否只有一个节点
        var current = this.head;
        if (this.length === 1) {
          this.head = null;
          this.tail = null;
        } else {
          // 2.1 删除第一个几点
          if (position === 0) {
            this.head.next.prev = null;
            this.head = this.head.next;
          } else if (position === this.length - 1) {
            // 删除最后一个节点
            current = this.tail;
            this.tail.prev.next = null;
            this.tail = this.tail.prev;
          } else {
            // 删除中间节点
            var index = 0;
            while (index < position) {
              current = current.next;
              index += 1;
            }
            current.prev.next = current.next;
            current.next.prev = current.prev;
          }

        }
        // 3. length 减一
        this.length -= 1;
        return current.data;
      }

      // remove(data) 根据内容删除
      DoublyLinkedList.prototype.remove = function (data) {
        var position = this.indexOf(data);
        return this.removeAt(position);
      }

      // isEmpty() 判断链表是否为空
      DoublyLinkedList.prototype.isEmpty = function () {
        return this.length === 0;
      }

      // size() 获取链表的长度
      DoublyLinkedList.prototype.size = function () {
        return this.length;
      }
    }

    // 添加节点
    var dlist = new DoublyLinkedList();
    dlist.append(123);
    dlist.append(456);
    dlist.append(789);
    console.log(dlist);

    // backString
    console.log(dlist.backString());
    // forwardString
    console.log(dlist.forwardString());

    dlist.insert(0, "first");
    console.log(dlist.backString())
    dlist.insert(4, "last");
    console.log(dlist.backString())
    dlist.insert(2, "insert-Index-2");
    console.log(dlist.backString())

    dlist.insert(5, "insert-Last-2");
    console.log(dlist.backString())

    // removeAt
    console.log(dlist.removeAt(0));
    console.log(dlist.removeAt(12));
  </script>
</body>
</html>