JS实现的单向链表

论坛 期权论坛 脚本     
已经匿名di用户   2022-7-2 21:59   2540   0

今天突发奇想地查了一下链表相关的资料,看到很多别人用javascript实现过的链表,然后就又想重复造轮子了,于是乎就自己也来写了一个,实现了插入(尾插入/某项之前/某项之后)、替换、移除、取值、交换、迭代、所有值等方法,一下是代码:

/**
 * 单项链表
 * 实现了单项链表的Insert、InsertBefore、InsertAfter、replace、remove、get、swap、getIterator(包含hasNext和next方法)、all方法
 * 分别为插入(尾插入/某项之前/某项之后)、替换、移除、取值、交换、迭代、所有值,
 * Created by Nick on 14-5-15.
 *
 */
(function (window) {
  /**
   * 链表节点对象
   * @param data
   * @constructor
   */
  var Node = function (data) {
    this.data = data;
    this.next = null;
  };
  /**
   * 链表对象
   * @constructor
   */
  var LinkedList = function () {
    this.size = 0;
    this.head = null;
  };

  /**
   * 链表原型方法
   * @type {{_testIndex: _testIndex, insert: insert, insertBefore: insertBefore, insertAfter: insertAfter, replace: replace, remove: remove, get: get, swap: swap, getIterator: getIterator, all: all}}
   */
  LinkedList.prototype = {
    constructor: LinkedList,
    /**
     * 查询index是否越界
     * @param index
     * @private
     */
    _testIndex: function (index) {
      if (isNaN(index)) {
        throw  Error('Index must be a Integer');
      }
      if (index > this.size - 1 || index < 0) {
        throw Error('List Index Out Of Bounds');
      }
    },
    /**
     * 向链表末尾插入数据
     * @param data
     * @returns {LinkedList}
     */
    insert: function (data) {
      this.size++;
      var node = new Node(data);
      if (this.head == null) {
        this.head = node;
      } else {
        var tmp = this.head;
        while (tmp.next != null) {
          tmp = tmp.next;
        }
        tmp.next = node;
      }
      return this;
    },
    /**
     * 在某个位置前插入一个数据
     * @param index
     * @param data
     * @returns {LinkedList}
     */
    insertBefore: function (index, data) {
      this._testIndex(index);
      this.size++;
      var node = new Node(data);
      var pos = 0;
      var prev = this.head;
      var current;
      while (pos < index - 1) {
        prev = prev.next;
        pos++;
      }
      current = prev.next;
      if (index == 0) {
        this.head = node;
        current = prev;
      } else {
        prev.next = node;
      }
      node.next = current;
      return this;
    },
    /**
     * 在某个位置后插入一个数据
     * @param index
     * @param data
     * @returns {LinkedList}
     */
    insertAfter: function (index, data) {
      this._testIndex(index);
      this.size++;
      var node = new Node(data);
      var pos = 0;
      var current = this.head;
      var next;
      while (pos < index) {
        current = current.next;
        pos++;
      }
      next = current.next;
      current.next = node;
      node.next = next;
      return this;
    },
    /**
     * 将某个位置的数据替换掉
     * @param index
     * @param data
     * @returns {LinkedList}
     */
    replace: function (index, data) {
      this._testIndex(index);
      var node = new Node(data);
      var pos = 0;
      var prev = this.head;
      var current;
      var next;
      while (pos < index - 1) {
        prev = prev.next;
        pos++;
      }
      current = prev.next;
      next = current.next;
      if (index == 0) {
        this.head = node;
        next = current;
      } else {
        prev.next = node;
      }
      node.next = next;
      return this;
    },
    /**
     * 将某个位置的数据删除
     * @param index
     * @returns {LinkedList}
     */
    remove: function (index) {
      this._testIndex(index);
      this.size--;
      if (index == 0) {
        this.head = this.head.next;
      } else {
        var pos = 0;
        var prev = this.head;
        var current;
        var next;
        while (pos < index - 1) {
          prev = prev.next;
          pos++;
        }
        current = prev.next;
        next = current.next;
        prev.next = next;
      }
      return this;
    },
    /**
     * 获取某个位置的数据
     * @param index
     * @returns {*}
     */
    get: function (index) {
      this._testIndex(index);
      var pos = 0;
      var current = this.head;
      while (pos < index) {
        current = current.next;
        pos++;
      }
      return current.data;
    },
    /**
     * 将某两个位置的数据交换
     * @param indexA
     * @param indexB
     * @returns {LinkedList}
     */
    swap: function (indexA, indexB) {
      if (indexA == indexB) return this;
      this._testIndex(indexA);
      this._testIndex(indexB);
      if (indexA > indexB) {
        var tmp = indexA;
        indexA = indexB;
        indexB = tmp;
      }
      var posA = 0;
      var posB = 0;
      var prevA = this.head;
      var prevB = this.head;
      var currentA;
      var currentB;
      var nextA;
      var nextB;
      while (posA < indexA - 1) {
        prevA = prevA.next;
        posA++;
      }
      currentA = prevA.next;
      nextA = currentA.next;
      while (posB < indexB - 1) {
        prevB = prevB.next;
        posB++;
      }
      currentB = prevB.next;
      nextB = currentB.next;
      if (indexA == 0) {
        nextA = currentA;
        currentA = prevA;
        this.head = currentB;
      } else {
        currentB = prevB.next;
        nextB = currentB.next;
        prevA.next = currentB;
      }
      currentB.next = nextA;
      prevB.next = currentA;
      currentA.next = nextB;
      return this;
    },
    /**
     * 获取迭代器对象
     * @returns {{hasNext: hasNext, next: next}}
     */
    getIterator: function () {
      var that = this;
      var tmp;
      var next;
      return {
        hasNext: function () {
          return (tmp || that.head).next != null;
        },
        next: function () {
          if (!tmp) {
            next = that.head;
          } else {
            next = tmp.next;
          }
          tmp = next;
          return next.data;
        }
      };
    },
    /**
     * 获取链表中的所有数据
     * @returns {{}}
     */
    all: function () {
      var result = {};
      var iterator = this.getIterator();
      var pos = 0;
      while (iterator.hasNext()) {
        result[pos] = iterator.next();
        pos++;
      }
      return result;
    }
  };
  window.LinkedList = LinkedList;
})(window);

如果需要引用的话可以将下面的js引入即可:

https://raw.githubusercontent.com/thesadboy/js-lib/master/linked-list/linkedlist.js


分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP