在LinkedList

时间:2018-01-07 15:45:31

标签: c# reference linked-list

我的问题:嗨,method-LinkedList.Remove(LinkedListNode n)是否更改了LinkedList中其他元素的引用?

应用程序有点复杂,所以至少我会尝试解释我是如何到达这里的,但也许会让人感到困惑

  

我有一个存储引用的程序(来自的LinkedListNodes)   LinkedList)到另一个可迭代类。在某些方面,   应用程序开始删除这些LinkedListNodes   method-Remove(LinkedListNode节点)并从中删除此元素   我的类存储这些引用。它运行良好一段时间,但是   在某些方面它会松开我班上的一个参考,我得到了   当我想调用时,null引用(在myNode中)   LinkeList.AddAfter(myNode,value),错误:“LinkedList节点   不属于当前LinkedList“。

修改

我正在翻译笔记等等...... 所以我使用BinarySearchTree进行快速搜索,使用LinkedList进行正常迭代,使用QUEUE进行删除旧元素。

这是插入我的Tree类:

 public Node Insert(DictionaryPair dictionaryPair, LinkedList<DictionaryPair> dictionary)
    {
        Node currentNode = nodeRoot;
        while (true)
        {
            if (currentNode == null)    //if i inserting 1st element
            {
                nodeRoot = new Node();   //creating node(root)
                dictionary.AddFirst(dictionaryPair);    //inserting into Linked list on 1st place
                nodeRoot.dictionaryNode = dictionary.First;  //and taking a reference
                return nodeRoot;  //end while
            }
            else if (currentNode.dictionaryNode.Value.CompareTo(dictionaryPair) >= 0)
            {   //sending element into left
                if (currentNode.left == null)   // and is empty
                {
                    currentNode.left = new Node();  //creating new node
                    currentNode.left.myParent = currentNode;    //reference to parent
                    currentNode.left.dictionaryNode = dictionary.AddBefore(currentNode.dictionaryNode, dictionaryPair);
                    //and inserting into dictionary (Before) current node and save the refence on it to left
                    return currentNode.left;  //end while
                }
                else
                {   //or shift to left
                    currentNode = currentNode.left;
                }
            }
            else
            {   //sending element into right
                if (currentNode.right == null)   // is null
                {
                    currentNode.right = new Node();  //create new node
                    currentNode.right.myParent = currentNode;   //reference on parent
                    currentNode.right.dictionaryNode = dictionary.AddAfter(currentNode.dictionaryNode, dictionaryPair);
                    //and insert into dictionary (After) current node and save  the refence on it to right
                    return currentNode.right;  //endwhile
                }
                else
                {   //or shift to right side
                    currentNode = currentNode.right;
                }
            }
        }            
    }

类节点:

    public LinkedListNode<DictionaryPair> dictionaryNode;
    public Node left;
    public Node right;
    public Node myParent;

我可以在我的节点上调用delete方法:

public LinkedListNode<DictionaryPair> DeleteMe()
    { 
        LinkedListNode<DictionaryPair> deletedNode = this.dictionaryNode;
        if (this.left == null && this.right == null)
        {   //Delete leaf
            if(myParent.left == this)
            {
                myParent.left = null;
            }
            else // else if(myParent.right == this)
            {
                myParent.right = null;
            }
        }
        else if (this.left != null && this.right == null)
        {
            this.right = this.left.right;
            this.dictionaryNode = this.left.dictionaryNode;
            this.left = this.left.left;               

        }
        else if (this.left == null && this.right != null)
        {
            this.left = this.right.left;                
            this.dictionaryNode = this.right.dictionaryNode;
            this.right = this.right.right;
        }
        else
        {   //on left and right are tries
            Node currentNode = this.left; //throught the left side
            bool oneCycle = false;  //possibility of not iterating once thought the left side into the right (so it would be left)
            while (currentNode.right != null)
            {    //searching element most to the right
                currentNode = currentNode.right;
                oneCycle = true;
            }
            if (currentNode.left == null)
            {   //i am leaf
                if (oneCycle)
                {
                    currentNode.myParent.right = null;   //deleting refence on me
                    this.dictionaryNode = currentNode.dictionaryNode;   //and change a value
                }
                else
                {
                    currentNode.myParent.left = null;   //deleting refence on me
                    this.dictionaryNode = currentNode.dictionaryNode;   //and change a value
                }
            }
            else
            {   //im not leaf
                if (oneCycle)
                {
                    currentNode.myParent.right = currentNode.left;  //change refence on my tree
                    this.dictionaryNode = currentNode.dictionaryNode;   //and change value
                }
                else
                {
                    currentNode.myParent.left = currentNode.left;  //change refence on my tree
                    this.dictionaryNode = currentNode.dictionaryNode;   //and change value
                }
            }             
        }
        return deletedNode;
    }

这是我使用数组MyDictionary的主要类,它有

    private LinkedList<DictionaryPair> data;    //for iterating search
    private Tree binarySearchTree;  //for quick search
    private Queue<Node> queue;   //references on added nodes 
    //in binarySearchTree... they are ready to be deleted
    private int maxCount;
    private bool maxCountReached;

当我插入MyDictionary时,我调用了这个方法

public void Insert(DictionaryPair input)
    {
        if (!maxCountReached)
        {
            if (queue.Count() >= maxCount)
            {
                maxCountReached = true;
            }
        }
        if (maxCountReached)
        {
            data.Remove(queue.Dequeue().DeleteMe());
        }
        queue.Enqueue(binarySearchTree.Insert(input, data));
    }

2 个答案:

答案 0 :(得分:1)

  

[...]方法LinkedList.Remove(LinkedListNode n)是否更改了LinkedList中其他[s]元素的引用?

当我们查看LinkedList.Remove方法的source code时,我们发现除了调整prevnext指针之外,框架不会混淆其他元素(为了弥补删除造成的差距,并根据链表原则的定义。)

除了边境案例,它只是

node.next.prev = node.prev;
node.prev.next = node.next;

item操作不会修改其他元素的对象(内部数据结构中的Remove)。 Remove操作本身所针对的对象也不会受到直接影响。当节点与列表分离时,如果没有其他生物对象保留引用,则它有资格进行垃圾回收。

您看到的例外是generated here

if ( node.list != this) {
    throw new InvalidOperationException(SR.GetString(SR.ExternalLinkedListNode));
}

如果此验证在AddAfter中失败,则可能意味着:

  • 调用代码正在尝试引用未附加到任何LinkedList的现有节点,例如先前从列表中删除的节点。在您发布的代码中,这将是currentNode.dictionaryNode,并且我专注于调试时分配的行
  • 调用代码正在尝试引用属于另一个LinkedList实例的现有节点。

答案 1 :(得分:0)

我在BinarySearchTree中实现了DeleteMe方法时发现了一个错误。我没有改变父节点对找到的currentNode下的节点的引用。但是谢谢你的帮助。祝你有美好的一天......