C# 单链表:删除方法

C# 单链表:删除方法,c#,C#,我正在用C#写一个单链表,你能告诉我是否有比我现在的方法更好的删除方法吗 using System; class Node { public int data = int.MinValue; public Node m_NextNode; public Node(int data_in) { data = data_in; } public Node() { } } class LinkedList {

我正在用C#写一个单链表,你能告诉我是否有比我现在的方法更好的删除方法吗

using System;

class Node
{
    public int data = int.MinValue;
    public Node m_NextNode;

    public Node(int data_in)
    {
        data = data_in;
    }

    public Node()
    {
    }
}

class LinkedList
{
    private Node m_HeadNode;

    public void InsertData(int data)
    {
        Node aCurrentNode = m_HeadNode;
        if(m_HeadNode == null)
        {
            m_HeadNode = new Node();
            m_HeadNode.data = data;
        }
        else
        {
            while(aCurrentNode.m_NextNode != null)
                aCurrentNode = aCurrentNode.m_NextNode;

            aCurrentNode.m_NextNode = new Node();
            aCurrentNode.m_NextNode.data = data;
        }
    }

    public void DisplayData()
    {
        Node aCurrentNode = m_HeadNode;

        while (aCurrentNode != null)
        {
            Console.WriteLine("the value is {0}", aCurrentNode.data);
            aCurrentNode = aCurrentNode.m_NextNode;
        }    
    }

    public void RemoveData(int data)
    {
        Node aCurrentNode = m_HeadNode;

        while (aCurrentNode != null)
        {
            //if the data is present in head
            //remove the head and reset the head
            if (m_HeadNode.data == data)
            {
                m_HeadNode = null;
                m_HeadNode = aCurrentNode.m_NextNode;
            }
            else
            {
                //else save the previous node
                Node previousNode = aCurrentNode;
                if (aCurrentNode != null)
                {
                    //store the current node
                    Node NextNode = aCurrentNode.m_NextNode;
                    if (NextNode != null)
                    {
                        //store the next node
                        Node tempNode = NextNode.m_NextNode;

                        if (NextNode.data == data)
                        {
                            previousNode.m_NextNode = tempNode;
                            NextNode = null;
                        }
                    }

                    aCurrentNode = aCurrentNode.m_NextNode;
                }
            }            
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        LinkedList aLinkedList = new LinkedList();
        aLinkedList.InsertData(10);
        aLinkedList.InsertData(20);
        aLinkedList.InsertData(30);
        aLinkedList.InsertData(40);
        aLinkedList.DisplayData();

        aLinkedList.RemoveData(10);
        aLinkedList.RemoveData(40);

        aLinkedList.RemoveData(20);
        aLinkedList.RemoveData(30);

        aLinkedList.DisplayData();

        Console.Read();
    }
}

您有一条不需要的线路:

            m_HeadNode = null;
            m_HeadNode = aCurrentNode.m_NextNode;

在将m_HeadNode设置为其他值之前,不需要将其设置为null。

我会将“如果删除head node”从while循环中拉出,使while循环更简单。只需跟踪当前和以前的节点,并在找到要删除的节点时切换引用即可

public void RemoveData(int data)
{
    if (m_HeadNode == null)
        return;

    if (m_HeadNode.data == data)
    {
        m_HeadNode = m_HeadNode.m_NextNode;
    }
    else
    {
        Node previous = m_HeadNode;
        Node current = m_HeadNode.m_NextNode;

        while (current != null)
        {
            if (current.data == data)
            {
                // If we're removing the last entry in the list, current.Next
                // will be null. That's OK, because setting previous.Next to 
                // null is the proper way to set the end of the list.
                previous.m_NextNode = current.m_NextNode;
                break;
            }

            previous = current;
            current = current.m_NextNode;
        } 
    }
}
RemoveData应该从列表中删除该整数的一个实例,还是所有实例?前面的方法只删除第一个,这里的方法删除了所有的

public void RemoveAllData(int data)
{
    while (m_HeadNode != null && m_HeadNode.data == data)
    {
        m_HeadNode = m_HeadNode.m_NextNode;
    }

    if(m_HeadNode != null)
    {
        Node previous = m_HeadNode;
        Node current = m_HeadNode.m_NextNode;

        while (current != null)
        {
            if (current.data == data)
            {
                // If we're removing the last entry in the list, current.Next
                // will be null. That's OK, because setting previous.Next to 
                // null is the proper way to set the end of the list.
                previous.m_NextNode = current.m_NextNode;
                // If we remove the current node, then we don't need to move
                // forward in the list. The reference to previous.Next, below,
                // will now point one element forward than it did before.
            }
            else
            {
                // Only move forward in the list if we actually need to, 
                // if we didn't remove an item.
                previous = current;
            }

            current = previous.m_NextNode;
        } 
    }
}

只有一个局部变量。
您的代码中有一个bug,假设您有一个包含3个元素的列表,其中data=5,并且您想要删除5个元素,那么您的代码将头部存储在aCurrentNode中并启动循环。在这里,条件为真,因此您可以将头部移动到下一个。但是aCurrentNode没有更新,因此在下一次迭代中,它指向上一个头部,aCurrentNode.m_NextNod将是您当前的头部,因此您陷入了一个永无止境的循环

 public void Remove(int data)
    {
      for(var cur = new Node {Next = Head}; cur.Next != null; cur = cur.Next)
      {
        if (cur.Next.Data != data) continue;
        if (cur.Next == Head)
          Head = Head.Next;
        else
          cur.Next = cur.Next.Next;
      }
    }
使循环更简单的一个技巧是从指向头部的假节点开始。通过这种方式,您不需要以不同的方式放置If来检查头部,但是您需要If来设置头部。另一个技巧是检查下一个节点的数据。这样,您就不需要保留以前的节点。

publicslement-Remove(int-index)
    public bool RemoveNode(int data) {
        Node prev = null;
        for (Node node = head; node != null; node = node.next) {
            if (node.data == data) {
                if (prev == null) head = node.next;
                else prev.next = node.next;
                return true;
            }
            prev = node;
        }
        return false;
    }
{ SLElement prev=_根; if(prev==null)返回null; SLElement curr=\u root.\u next; 对于(int i=1;i

这将删除具有特定索引的元素,而不是具有特定值的元素,从而使操作变得非常简单。请按照下面的说明。下面是从单个链接列表中删除项的代码段

public void DeleteNode(int nodeIndex)
        {
            int indexCounter = 0;
            Node TempNode = StartNode;
            Node PreviousNode = null;
            while (TempNode.AddressHolder != null)
            {
                if (indexCounter == nodeIndex)
                {
                    PreviousNode.AddressHolder = TempNode.AddressHolder;
                    break;
                }
                indexCounter++;
                PreviousNode = TempNode;
                TempNode = TempNode.AddressHolder;
            }
        }

你的代码块真的被破坏了,但这会有帮助吗?你说的“更好”是什么意思?可读性更强、性能更好、代码更少等等?这只是一个编程练习吗?C#一个内置的类型安全双链表。关于其他部分,我使用了三个节点来删除数据;首先我记得上一个节点,然后从上一个节点我从当前节点中获取当前节点我得到下一个节点,一旦数据匹配,我移除当前节点并在上一个节点和当前节点之间建立链接,有没有更好的方法来实现相同的目标你真的不需要返回,他的实现将删除所有出现的数据。
public SLElement Remove(int index)
    {
      SLElement prev = _root;
      if (prev == null) return null; 
      SLElement curr = _root._next;
      for (int i = 1; i < index; i++)
      {
        if (curr == null) return null; 
        prev = curr;
        curr = curr._next;
      }
      prev._next = curr._next; 
      curr._next = null;
      return curr;
    }
public void DeleteNode(int nodeIndex)
        {
            int indexCounter = 0;
            Node TempNode = StartNode;
            Node PreviousNode = null;
            while (TempNode.AddressHolder != null)
            {
                if (indexCounter == nodeIndex)
                {
                    PreviousNode.AddressHolder = TempNode.AddressHolder;
                    break;
                }
                indexCounter++;
                PreviousNode = TempNode;
                TempNode = TempNode.AddressHolder;
            }
        }