【问题标题】:Circular, doubly linked list, how to manage the node to object relationship?循环,双向链表,如何管理节点到对象的关系?
【发布时间】:2014-04-02 05:38:56
【问题描述】:

这个 LinkedList 函数使用一种非常狡猾的方法来避免客户端代码需要了解链接节点。每个列表创建一个唯一的字符串,用于将属性插入到添加到列表中的对象中。有谁知道更好的方法来做到这一点?我应该提一下,在恒定时间内移除对象是一项要求。

这确实意味着客户端代码看起来像:

var myList = new LinkedList()

var a = new Something()
var b = new SomethingElse()

myList.addTail(a)
myList.addTail(b)

myList.remove(a)
myList.remove(b)

这很好并且可读,但是将属性插入对象(可能与现有属性冲突)是不稳定的,至少可以说(尽管它可以被记录并且属性名称前缀可以传递给 LinkedList构造函数)。

这是链表代码:

var LinkedList = (function() {

    var id = 0

    var Node = function(obj, p, n) {
        this.item = obj
        this.prev = p
        this.next = n
    }

    var list = function() {
        this.length = 0
        this.nodeName = '_' + id++ + 'lnn'
        this.root = new Node(null)
        this.root.next = this.root
        this.root.prev = this.root
    }

    list.prototype = {

        insertBefore : function(obj, item) {
            var node = new Node(item, obj.prev, obj)
            obj.prev.next = node
            obj.prev = node
            item[this.nodeName] = node
            ++this.length
        },

        insertAfter : function(obj, item) {
            var node = new Node(item, obj, obj.next)
            obj.next.prev = node
            obj.next = node
            item[this.nodeName] = node
            ++this.length
        },

        addTail : function(item) {
            this.insertBefore(this.root, item)
        },

        addHead : function(item) {
            this.insertAfter(this.root, item)
        },

        remove : function(item) {
            var node = item[this.nodeName]
            node.prev.next = node.next
            node.next.prev = node.prev
            delete node.item[this.nodeName]
            --this.length
        },

        popHead : function() {
            if(this.length > 0) {
                var node = this.root.next
                node.prev.next = node.next
                node.next.prev = node.prev
                delete node.item[this.nodeName]
                --this.length
                return node.item
            }
            return null
        },

        popTail : function() {
            if(this.length > 0) {
                var node = this.root.prev
                node.prev.next = node.next
                node.next.prev = node.prev
                delete node.item[this.nodeName]
                --this.length
                return node.item
            }
            return null
        },

        forEach : function(callback, context) {
            var node = this.root.next
            var index = 0
            while(node !== this.root) {
                var next = node.next
                if(callback.call(context, node.item, index) === false) {
                    return false
                }
                node = next
                ++index
            }
            return true
        },

        removeIf : function(callback, context) {
            var node = this.root.next
            while(node !== this.root) {
                var next = node.next
                if(callback.call(context, node.item) === true) {
                    node.prev.next = next
                    node.next.prev = node.prev
                    delete node.item[this.nodeName]
                    --this.length
                }
                node = next
            }
        },

        toString : function() {
            var s = this.length.toString()
            var sep = ':<'
            this.forEach(function(i, index) {
                s += sep + i.toString()
                sep = ','
            })
            return s + '>'
        }
    }

    return list
})()

【问题讨论】:

  • 这就是你想要的吗?
  • 不完全——我需要不断地删除任意元素,我认为你不会给我。
  • 这不是普通链表的工作方式。应该包括在问题中
  • 啊,好点,为清楚起见进行了编辑
  • 在问题描述中仍然不清楚具体问题是什么,也没有在示例代码中。循环/双向链表通常仍然没有固定时间删除或任意元素 - 只有您有迭代器的元素......请不要在人们将工作代码示例输入到您的原始问题后更改问题。

标签: javascript linked-list doubly-linked-list


【解决方案1】:

这是我的实现:

function LinkedList(initialValues){
  var head = null,
    version = 0,
    list = {
      push: function(){
        var args = [].slice.call(arguments, 0),
          pushable = null;
        while(args.length && (pushable = args.shift()))
          head = new Node(pushable).append(head);
        version++;
        return this;
      },
      pop: function(){
        var popped = head;
        head = head.next();
        version++;
        return popped.value();
      },
      peek: function(){
        return head && head.value();
      },
      iterator: function(){
        return new Iterator(head, version);
      },
      toString: function(){
        var vals = [],
          iter = new Iterator(head, version);
        while(iter.node()){
          vals.push(iter.node().toString());
          iter.step();
        }
        return ["("].concat(vals).concat(")").join(" ");
      },
      size: function(){
        var iter = new Iterator(head, version);
        while(iter.node()){
          iter.step();
        }
        return iter.index();
      }
    };
  return list.push.apply(list, initialValues);

  function Node(input){
    var content = input,
      next = null;
    return {
      next: function(){
        return next;
      },
      value: function(){
        return content;
      },
      append: function(node){
        next = node;
        return this;
      },
      set: function(val){
        return content = val;
      },
      toString: function(){
        return content.toString();
      }
    };
  }

  function Iterator(base, v){
    var current = base, index = 0,
      checkSafe = function(){
        if(v === version)
          return true;
        else
          throw "The iterator is no longer valid, list modified.";
      };
    return {
      node: function(){
        checkSafe();
        return current;
      },
      step: function(){
        checkSafe();
        current = current.next();
        index++;
        return this;
      },
      index: function(){
        checkSafe();
        return index;
      }
    };
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    相关资源
    最近更新 更多