C # - LinkedList - How to delete all nodes after the specified node?

I use a cancel / redo buffer with a common LinkedList.

In this state:
[Up]
state4 (canceled)
state3 (canceled)
state2 <- current state of
State1
[Bottom]

When I do Push, I would like to delete all the states after the current one and press the new one.

My current bypass is to do it while (currentState != list.last), list.removeLast();, but it sucks

LinkedList just supports removal, RemoveFirst and removeLast ...

I would like something like RemoveAllNodesAfter (LinkedListNode ...)?

How can I encode it correctly without repeating all nodes? Maybe with extensions? ...

+3
source share
7

LinkedList<T>, . PowerCollections C5 , , LinkedList. , " ".

+5

, .

.RemoveAllNodesAfter(node) .SplitAfter(node), , node node. , . RemoveAllNodesAfter, SplitAfter .

:

public LinkedList<T> SplitAfter(Node node)
{
    Node nextNode = node.Next;

    // break the chain
    node.Next = null;
    nextNode.Previous = null;

    return new LinkedList<T>(nextNode);
}

public void RemoveAllNodesAfter(Node node)
{
    SplitAfter(node);
}
+5

( ) . , , , ( ) .

. .

public class SingleLinkedListNode<T>
{
    private readonly T value;
    private SingleLinkedListNode<T> next;

    public SingleLinkedListNode(T value, SingleLinkedListNode<T> next)
    {
        this.value = value;
    }

    public SingleLinkedListNode(T value, SingleLinkedListNode<T> next)
        : this(value)
    {
        this.next = next;
    }

    public SingleLinkedListNode<T> Next
    {
        get { return next; }
        set { next = value; }
    }

    public T Value
    {
        get { return value; }
    }
}

, SingleLinkedList.

public class SingleLinkedList<T>
{
    private SingleLinkedListNode<T> head;
    private SingleLinkedListNode<T> tail;

    public SingleLinkedListNode<T> Head
    {
        get { return head; }
        set { head = value; }
    }

    public IEnumerable<SingleLinkedListNode<T>> Nodes
    {
        get
        {
            SingleLinkedListNode<T> current = head;
            while (current != null)
            {
                yield return current;
                current = current.Next;
            }
        }
    }

    public SingleLinkedListNode<T> AddToTail(T value)
    {
        if (head == null) return createNewHead(value);

        if (tail == null) tail = findTail();
        SingleLinkedListNode<T> newNode = new SingleLinkedListNode<T>(value, null);
        tail.Next = newNode;
        return newNode;
    }

    public SingleLinkedListNode<T> InsertAtHead(T value)
    {
        if (head == null) return createNewHead(value);

        SingleLinkedListNode<T> oldHead = Head;
        SingleLinkedListNode<T> newNode = new SingleLinkedListNode<T>(value, oldHead);
        head = newNode;
        return newNode;
    }

    public SingleLinkedListNode<T> InsertBefore(T value, SingleLinkedListNode<T> toInsertBefore)
    {
        if (head == null) throw new InvalidOperationException("you cannot insert on an empty list.");
        if (head == toInsertBefore) return InsertAtHead(value);

        SingleLinkedListNode<T> nodeBefore = findNodeBefore(toInsertBefore);
        SingleLinkedListNode<T> toInsert = new SingleLinkedListNode<T>(value, toInsertBefore);
        nodeBefore.Next = toInsert;
        return toInsert;
    }

    public SingleLinkedListNode<T> AppendAfter(T value, SingleLinkedListNode<T> toAppendAfter)
    {
        SingleLinkedListNode<T> newNode = new SingleLinkedListNode<T>(value, toAppendAfter.Next);
        toAppendAfter.Next = newNode;
        return newNode;
    }

    public void TruncateBefore(SingleLinkedListNode<T> toTruncateBefore)
    {
        if (head == toTruncateBefore)
        {
            head = null;
            tail = null;
            return;
        }

        SingleLinkedListNode<T> nodeBefore = findNodeBefore(toTruncateBefore);
        if (nodeBefore != null) nodeBefore.Next = null;
    }

    public void TruncateAfter(SingleLinkedListNode<T> toTruncateAfter)
    {
        toTruncateAfter.Next = null;
    }

    private SingleLinkedListNode<T> createNewHead(T value)
    {
        SingleLinkedListNode<T> newNode = new SingleLinkedListNode<T>(value, null);
        head = newNode;
        tail = newNode;
        return newNode;
    }

    private SingleLinkedListNode<T> findTail()
    {
        if (head == null) return null;
        SingleLinkedListNode<T> current = head;
        while (current.Next != null)
        {
            current = current.Next;
        }
        return current;
    }

    private SingleLinkedListNode<T> findNodeBefore(SingleLinkedListNode<T> nodeToFindNodeBefore)
    {
        SingleLinkedListNode<T> current = head;
        while (current != null)
        {
            if (current.Next != null && current.Next == nodeToFindNodeBefore) return current;
            current = current.Next;
        }
        return null;
    }
}

:

public static void Main(string[] args)
{
    SingleLinkedList<string> list = new SingleLinkedList<string>();
    list.InsertAtHead("state4");
    list.AddToTail("state3");
    list.AddToTail("state2");
    list.AddToTail("state1");

    SingleLinkedListNode<string> current = null;
    foreach (SingleLinkedListNode<string> node in list.Nodes)
    {
        if (node.Value != "state2") continue;

        current = node;
        break;
    }

    if (current != null) list.TruncateAfter(current);
}

, , :

public static void Main(string[] args)
{
    SingleLinkedListNode<string> first =
        new SingleLinkedListNode<string>("state4");
    first.Next = new SingleLinkedListNode<string>("state3");
    SingleLinkedListNode<string> current = first.Next;
    current.Next = new SingleLinkedListNode<string>("state2");
    current = current.Next;
    current.Next = new SingleLinkedListNode<string>("state1");

    current = first;
    while (current != null)
    {
        if (current.Value != "state2") continue;
        current.Next = null;
        current = current.Next;
        break;
    }
}

.

+3

:

while (currentNode.Next != null)
    list.Remove(currentNode.Next);

, , (: ).

, (: YAGNI) /:

public class LinkedListNode<T>
{
    public LinkedList<T> Parent { get; set; }
    public T Value { get; set; }
    public LinkedListNode<T> Next { get; set; }
    public LinkedListNode<T> Previous { get; set; }
}

public class LinkedList<T> : IEnumerable<T>
{
    public LinkedListNode<T> Last { get; private set; }

    public LinkedListNode<T> AddLast(T value)
    {
        Last = (Last == null)
            ? new LinkedListNode<T> { Previous = null }
            : Last.Next = new LinkedListNode<T> { Previous = Last };

        Last.Parent = this;
        Last.Value = value;
        Last.Next = null;

        return Last;
    }

    public void SevereAt(LinkedListNode<T> node)
    {
        if (node.Parent != this)
            throw new ArgumentException("Can't severe node that isn't from the same parent list.");

        node.Next.Previous = null;
        node.Next = null;
        Last = node;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable<T>)this).GetEnumerator();
    }

    public IEnumerator<T> GetEnumerator()
    {
        var walk = Last;

        while (walk != null) {
            yield return walk.Value;
            walk = walk.Previous;
        }
    }

}

SevereAt , "" .

+2

, , Node.Next.Previous = null ( ), Node.Next = null.

, LinkedListNode<T>.Next LinkedListNode<T>.Previous Linked List.NET, , , , .

, , . , , Google #.

0
if(this.ptr != null && this.ObjectName != null)
{
    LinkedListNode<ObjectType> it = ObjectName.Last;
                for (; it != this.ptr; it = it.Previous) 
                {
                    this.m_ObjectName.Remove(it);
                }
}

this.ptr LinkedListNode<ObjectType> fyi

this.ptr - , node, , , , .

, -. , . , . .

0

" node" " node". - LinkedListNode, LinkedList, :

public static class Extensions
{
    public static void RemoveAllBefore<T>(this LinkedListNode<T> node)
    {
        while (node.Previous != null) node.List.Remove(node.Previous);
    }

    public static void RemoveAllAfter<T>(this LinkedListNode<T> node)
    {
        while (node.Next != null) node.List.Remove(node.Previous);
    }
}

:

void Main()
{
    //create linked list and fill it up with some values

    LinkedList<int> list = new LinkedList<int>();
    for(int i=0;i<10;i++) list.AddLast(i);

    //pick some node from the list (here it is node with value 3)

    LinkedListNode<int> node = list.First.Next.Next.Next;

    //now for the trick

    node.RemoveAllBefore();

    //or

    node.RemoveAllAfter();
}

Well, this is not the most efficient approach, and if you call this method on large lists or very often, then the other approaches described here are probably more suitable (for example, writing your own class of linked lists, which allows you to split, as described in other answers) but if it is just the โ€œdeleteโ€ node here and there, then it is simple and quite intuitive.

0
source

Source: https://habr.com/ru/post/1703743/


All Articles