JS数据结构和算法2

82 阅读1分钟

数据结构和算法

数组及单链表的缺点

image.png

单链表的优势

image.png

单链表到底是什么?

image.png

单链表封装

  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 LinkedList() {
      // 内部类:节点类
      function Node(data) {
        this.data = data;
        this.next = null;
      }
      // 属性
      this.head = null;
      this.length = 0;

      // 1. 添加节点
      LinkedList.prototype.append = function (data) {
        // 判断是否添加的是第一个节点
        var newNode = new Node(data);
        if(this.length === 0) {
          // 是第一个节点
          this.head = newNode;
        } else {
          var current = this.head;
          while (current.next) {
            // 不是第一个节点,获取最后一个节点
            current = current.next;
          }
          current.next = newNode;
        }

        // 添加新节点之后,将链表长度加一
        this.length += 1;
      }

      // 2. toString方法,将每个节点取出data,拼接成字符串
      LinkedList.prototype.toString = function () {
        var linkStr = "";
        var current = this.head;
        while (current) {
          linkStr += ' ' + current.data;
          current = current.next;
        }
        return linkStr.trim();
      }

      // 3. insert 方法
      LinkedList.prototype.insert = function (position, data) {
        // 1. 对 position 进行判断
        if (position < 0 || position > this.length) {
          // 不能是负数,且不能超过链表长度
          return false
        }

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

        // 3. 判断插入的位置
        if (position === 0) {
          // 第一个位置
          newNode.next = this.head;
          this.head = newNode;
        } else {
          // 中间或末尾插入
          var index = 0;
          var current = this.head;
          var previous = null;
          while(index < position) {
            previous = current;
            current = current.next;
            index ++;
          }
          newNode.next = current;
          previous.next = newNode;
        }
        // 4. this.length 加一
        this.length += 1;
        return true;
      }

      // 4. 获取对应位置的元素
      LinkedList.prototype.get = function (position) {
        // 1. 判断position是否有效
        if (position < 0 || position >= this.length) {
          return null;
        }

        var index = 0;
        var current = this.head;
        while (index < position) {
          current = current.next;
          index ++;
        }
        return current;
      }

      // 5. 通过data获取对应的下标值
      LinkedList.prototype.indexOf = function (data) {
        var current = this.head;
        var index = 0;
        while (current) {
          if (current.data === data) {
            return index;
          }
          current = current.next;
          index += 1;
        }
        return -1;
      }

      // 6. update(position)
      LinkedList.prototype.update = function (position, data) {
        // 1. 判断position是否有效
        if (position < 0 || position >= this.length) {
          return false;
        }

        // 2. 获取到当前位置的元素
        var current = this.head;
        var index = 0;
        while (index < position) {
          current = current.next;
          index += 1;
        }
        current.data = data;
      }

      // 7. removeAt(postion) 删除某位置节点
      LinkedList.prototype.removeAt = function (position) {
        // 1. 判断position是否有效
        if (position < 0 || position >= this.length) {
          return false;
        }
        
        // // 2. 判断是否是第一个节点
        var current = this.head;
        if (position === 0) {
          this.head = current.next;
        } else {
          var index = 0;
          var prevNode = null;
          while (index < position) {
            prevNode = current;
            current = current.next;
            index += 1;
          }
          prevNode.next = current.next;
        }

        this.length -= 1;
        return true;
      }

      // 8. remove(data) 根据data删除节点
      LinkedList.prototype.remove = function (data) {
        // 也可以利用写好的indexOf 和 removeAt方法

        var current = this.head;
        var prevNode = null;
        var index = 0;
        while (current) {
          if (current.data === data) {
            // prevNode = current
            if (index === 0) {
              this.head = current.next;
            } else {
              prevNode.next = current.next;
            }
            return true;
          }
          prevNode = current;
          current = current.next;
          index += 1;
        }
        return false;
      }

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

      // 10. size() 返回链表的长度,节点个数
      LinkedList.prototype.size = function () {
        return this.length;
      }
    }

    var list = new LinkedList();
    list.append(123);
    list.append(234);
    console.log("list.length", list.length);
    console.log("list.head", list.head);
    console.log("list.toString", list.toString())

    // 在开头插入
    list.insert(0, "开头");
    console.log("开头插入新节点", list.toString())

    // 中间插入新节点
    list.insert(2, "中间");
    console.log("中间插入新节点", list.toString())

    // 末尾插入新节点
    list.insert(4, "末尾");
    console.log("末尾插入新节点", list.toString())

    // 获取对应位置的节点
    console.log(list.get(0))
    console.log(list.get(1))

    // indexOf(data)
    console.log(list.indexOf("中间"))
    console.log(list.indexOf("末尾"))
    console.log(list.indexOf(123))
    console.log("末尾插入新节点", list.toString())

    // update(position, data)
    list.update(0, "hello")
    console.log(list.toString())

    // removeAt(position) 根据位置删除节点
    list.removeAt(0);
    console.log(list.length)
    list.removeAt(4);
    console.log(list.toString())

  </script>
</body>
</html>