单链表:remove方法

本文关键字:remove 方法 链表 单链表 | 更新日期: 2023-09-27 17:48:58

我正在用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();
    }
}

单链表:remove方法

我会将"if removing the 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;
        } 
    }
}

您有一行不需要:

            m_HeadNode = null;
            m_HeadNode = aCurrentNode.m_NextNode;

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

    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;
    }
public void RemoveData(int data)
{
    if(null == m_HeadNode) return;
    if(m_HeadNode.data == data)
    {
       // remove first node
    }
    else
    {
        Node current = m_HeadNode;
        while((null != current.m_NextNode) && (current.m_NextNode.data != data))
            current = current.m_NextNode;
        if(null != current.m_NextNode)
        {
            // do remove node (since this sounds like homework, I'll leave that to you)
        }
    }    
}

只有一个局部变量
你的代码中有一个错误,假设你有一个列表,其中有3个元素,数据=5,你想删除5,你的代码将头部存储在aCurrentNode中并开始循环。在那里,条件是真的,所以你把头移到下一个。但是aCurrentNode没有更新,所以在下一次迭代中,它指向上一个Head,而aCurrentNode.m_NextNod将是您当前的Head,因此您陷入了一个永无止境的循环!

 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;
      }
    }

让循环更简单的一个技巧是从一个指向head的假节点开始。这样,你就不需要放置一个If来以不同的方式检查头部,但你需要一个If来设置头部。另一个技巧是检查下一个节点的数据。这样就不需要保留以前的节点。

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;
            }
        }