zoukankan      html  css  js  c++  java
  • JavaScript的数据结构快速学-链表的实现

    1-单项链表

        function LinkedList() {
            let Node = function(element) { // 辅助类,表示要添加到链表中的项
              this.element = element;
              this.next = null; //next属性是只想链表的下一个节点的指针
            };
    
            let length = 0,
                head = null;  // 头指针
            this.append = function(element) {}; // 向链表尾部添加一个新的项
            this.insert = function(element, position) {}; // 向指定位置插入一个新的项
            this.removeAt = function(position) {}; // 移除链表中的指定项
            this.remove = function(element) {}; // 移除值为element的项
            this.indexOf = function(element) {}; // 返回元素在链表中的索引,如果没有则返回-1
            this.isEmpty = function() {}; // 判断链表中是否为空
            this.size = function() {}; // 链表的长度
            this.clear = function() {}; // 清空链表
            this.print = function() {}; //输出链表的值
        }

    append实现:向链表尾部添加一个新的项

            this.append = function(element) { //向链表尾部添加一个新的项
                let node = new Node(element),
                           current;
                if (head === null) { // 链表中的第一个节点
                    head = node;
                } else {
                    current = head;
                    while (current.next) { // 循环链表,直到找到最后一项
                      current = current.next;
                    }
                    current.next = node; // 找到最后一项,将next赋值为node,建立连接
                }
                length += 1; //更新链表长度
            };

    print实现:输出链表的值

        this.print = function() {
          let current = head;
              for (let i = 0; i < length; i++) {
                console.log(`第${i+1}个值:${current.element}`);
                current = current.next;
                }
            };

    insert实现:向指定位置插入一个新的项

    向指定位置插入一个新的项,步骤如下:

    • 先进行position的越界判断!!
    • case1: 当position=0的时候,那就是直接将当前head指向的节点变成新建node的next指向,head指向新建的node上
    • case2: 除case1外的情况,先遍历到如下图所示的情况,我们设置两个指针,每次遍历都是current将值赋给previous,然后current向后推进,直到current指向position的位置,previous指向position的前一个

    • 然后将新建的node,插入其中,然后改变其中的指针指向,具体看代码
    • 最后将length加一
        this.insert = function(element, position) { // 向指定位置插入一个新的项
          if (position >= 0 && position <= length) { // 检查越界值
            let node = new Node(element),
            current = head, // 设置两指针
            previous;
            if (position === 0) { // 在第一个位置添加
              node.next = head;
              head = node;
            }else {
              for (let i = 0; i < position; i++) {
                // 使得current定在要插入的位置,previous定在要插入位置的前一个位置
                previous = current; 
                current = current.next;
              }
              // 将新项node插入进去
              node.next = current;
              previous.next = node;
            }
          }else {
            return 0;
          }
          length += 1;
        };
    对于函数参数含有position这类的位置参数,一定要注意越界判断

    removeAt实现:移除链表中的指定位置项

    removeAt的思想和前面的insert方法很相似,唯一的不同就是移除指定项时,改变指针指向的代码不同previous.next = current.next;

    • 具体思想如图:将current指向的项(其实也就是position指向的项)移除,那就将图中红色叉的指针指向取消,然后用新的代替
    • 然后将lenght减一

    • 只有previous.next = current.next;和insert方法不同,其他思想和做法都一样
                this.removeaAt = function(position) { // 移除链表中的指定项
                  if (position >= 0 && position <= length) {
                    let current = head,
                        previous;
                    if (position === 0) {
                        head = head.next;
                    }else {
                      for (let i = 0; i < position; i++) { //此处循环到current指向要移除的位置,同insert方法
                        previous = current;
                        current = current.next;
                        }
                        // 通过将previous的next变化到current.next,将指定项移除
                      previous.next = current.next;
                    }
                  }else {
                    return 0;
                  }
                  length -= 1;
                };

    indexOf实现:返回元素在链表中的索引,如果没有则返回-1

            this.indexOf = function(element) { // 返回元素在链表中的索引,如果没有则返回-1
              let current = head; //
              for (let i = 0; i < length; i++) {
                if (current.element === element) {
                  return i;
                }
                current = current.next;
              }
              return -1;
            };

    remove实现:移除值为element的项

    this.remove = function(element) { // 移除值为element的项
        // remove方法可以直接通过复用 this.indexOf(element) 和 this.removeAt(position) 方法实现
        let index = this.indexOf(element);
        return this.removeaAt(index);
    };

    isEmpty、size、clear实现

    this.isEmpty = function() { // 判断链表中是否为空
        return length === 0;
    };
    
    this.size = function() { // 链表的长度
        return length;
    };
    
    this.clear = function() { // 清空链表
        let current = head;
        for (let i = 0; i < length; i++) {
            this.removeAt(i);
        }
        length = 0;
        head = null;
    };

    测试函数

        (function LinkedListTest() {
          let linked = new LinkedList();
          linked.append(2);
          linked.append(3);
          linked.append(4);
          linked.print(); // 第1个值:2  第2个值:3  第3个值:4
          
          linked.insert(5, 1); // 位置从0开始
          linked.print(); // 第1个值:2   第2个值:5   第3个值:3   第4个值:4
          linked.removeAt(1); // 相当于将上面插入的5再删除
          linked.print(); // 第1个值:2   第2个值:3   第3个值:4
          
          console.log(linked.indexOf(3)); // 1
          console.log(linked.indexOf(10)); // -1
          console.log(linked.size()); // 3
          console.log(linked.isEmpty()); // false
          linked.clear();
          console.log(linked.isEmpty()); // true
        })();
  • 相关阅读:
    Vue--vue-Router
    Vue--vue中的组件、组件绑定事件和数据、私有组件、子组件,父子组件参数互传
    CF 631C report
    生日Party 玄学多维DP
    HDU-6376 度度熊剪纸条
    CF 1012C Dp
    CF 997A
    HDU-1051 一个DP问题
    偶尔间看到,来开心一下
    合并石子
  • 原文地址:https://www.cnblogs.com/magicg/p/13389413.html
Copyright © 2011-2022 走看看