【问题标题】:Reverse a singly-linked list with and without using recursion使用和不使用递归来反转单链表
【发布时间】:2011-01-05 10:45:51
【问题描述】:

我是数据结构的新手,我知道这是一个非常常见的问题。但是我知道 .NET 中的 LinkedList 是双向链接的,所以我将如何在 C# 中为单向链接列表编写代码。

有人可以写示例代码吗?

【问题讨论】:

    标签: c# algorithm data-structures singly-linked-list


    【解决方案1】:

    您需要定义一个节点数据结构,其中包含一些数据和对链表中下一个节点的引用。比如:

    class Node {
      private Node _next;
      private string _data;
    
      public Node(string data) {
        _next = null;
        _data = data;
      }
    
      // TODO: Property accessors and functions to link up the list
    }
    

    然后你可以编写一个算法以逆序遍历列表,构造一个新的逆序列表。

    【讨论】:

    • 或者你可以使用内置的链接列表,但只能使用一个方向的链接,如果可以接受,你应该咨询你的导师
    • 所以基本上你是在告诉我 C# 实际上有指针并且它们是用“_”声明的?
    • 没有。 C# 使用与指针相似(但不相同)的引用。引用足以实现链表,不需要指针。顺便说一句,C# 确实有指针,但它们几乎不需要,也不建议正常使用
    【解决方案2】:
    reversed_list = new
    for all node in the original list
       insert the node to the head of reversed_list
    

    【讨论】:

    • 如果我不想使用任何新的链表,那么算法将是什么。
    • @Pritam,实际上,我没有使用任何新列表。 reversed_list 只是一个指向新列表头部的指针。换句话说,不需要内存。
    • 在内存方面这是一个不错的主意,但在性能效率方面,它是效率最低的方法,性能n^2!
    【解决方案3】:

    使用循环(当前元素:currentNode,在循环外初始化的变量:previousNode,nextNode)

    Set nextNode = currentNode.NextNode
    Set currentNode.NextNode = previousNode
    Set previousNode = currentNode
    Set currentNode = nextNode
    continue with loop
    

    【讨论】:

      【解决方案4】:

      由于这很可能是家庭作业,因此我将以一种可能会令人困惑的方式来说明这一点,以免完成所有工作。希望我的尝试不会让事情变得更加混乱(这很有可能)。

      当你引用了列表中的一个节点(比如第一个节点)时,你也引用了它后面的节点。您只需让以下节点引用您的当前节点,同时保留有关以下节点(及其先前状态)的足够信息,以便为它执行类似的工作。现在唯一棘手的部分是处理边界条件(列表的开头和结尾)。

      【讨论】:

        【解决方案5】:

        这里使用递归。

        private void Reverse(Item item)
            {
                if (item == null || item.Next == null) //if head is null or we are at the tail
                {
                    this.Head = item; //we are at the tail or empty list, set the new head to the tail
                    return;
                }
        
                Reverse(item.Next);
        
                var nextItem = item.Next; //get the next item out, dealing with references don't want to override it
                item.Next = null;         //once you get the next item out, you can delete the *reference* i.e. link to it
                nextItem.Next = item;     //set the item you got out link to next item to the current item i.e. reverse it
            }
        

        【讨论】:

          【解决方案6】:
          //Have tried the Iterative approach as below, feel free to comment / optimize 
          
          package com.test;
          
          
          public class ReverseSinglyLinkedList {
          
          
          public ReverseSinglyLinkedList() {
              // TODO Auto-generated constructor stub
          }
          public Node ReverseList(Node n)
          {
          
              Node head =  n; 
              Node current = n; 
              Node firstNodeBeforeReverse = n;  // keep track of origional FirstNode
          
              while(true) 
              {
          
                  Node temp = current; 
                   // keep track of currentHead in LinkedList "n", for continued access to unprocessed List
                  current = current.next; 
                  temp.next = head;
                    // keep track of head of Reversed List that we will return post the processing is over 
                  head = temp;   
          
                  if(current.next == null)
                  {
          
                      temp = current;
                      current.next = head;
                      head = temp;        
                                      // Set the original FirstNode to NULL
                      firstNodeBeforeReverse.next = null; 
          
                      break;
                  }
              } 
          
              return head;
          
          }
          
          public void printLinkList(Node n)
          {
          
              while(true)
              {
                  System.out.print(n.data + " ");
                  n = n.next;
                  if(n.next ==null)
                  {
                      System.out.print(n.data + " ");
                      break;
                  }
          
              }
          }
          
          public static void main(String[] args) {
              // TODO Auto-generated method stub
          
              // TEST THE PROGRAM: crate a node List first to reverse it
              Node n = new Node(1);
              n.next = new Node(2);
              n.next.next = new Node(3);
              n.next.next.next = new Node(4);
              n.next.next.next.next = new Node(5);
              n.next.next.next.next.next = new Node(6);
          
              ReverseSinglyLinkedList r = new ReverseSinglyLinkedList();
              System.out.println("Input Linked List : ");  
              r.printLinkList(n);
          
              Node rsList = r.ReverseList(n);
          
              System.out.println("\n Reversed Linked List : ");
              r.printLinkList(rsList);
          
          
          
          }
          
          }
          

          【讨论】:

            【解决方案7】:

            这里是 .net (C#) 中的链接反向迭代和递归 (请注意,链表同时维护第一个和最后一个指针,以便我可以在 O(1) 的末尾追加或插入头部 - 不必这样做。我刚刚定义了我的链表行为,如上)

            public void ReverseIterative()
                    {
                        if(null == first)
                        {
                            return;
                        }
                        if(null == first.Next)
                        {
                            return;
                        }
                        LinkedListNode<T> p = null, f = first, n = null;
                        while(f != null)
                        {
                            n = f.Next;
                            f.Next = p;
                            p = f;
                            f = n;
                        }
                        last = first;
                        first = p;
                    }
            

            递归:

                    public void ReverseRecursive()
                    {
                        if (null == first)
                        {
                            return;
                        }
                        if (null == first.Next)
                        {
                            return;
                        }
                        last = first;
                        first = this.ReverseRecursive(first);
                    }
                    private LinkedListNode<T> ReverseRecursive(LinkedListNode<T> node)
                    {
                        Debug.Assert(node != null);
                        var adjNode = node.Next;
                        if (adjNode == null)
                        {
                            return node;
                        }
                        var rf = this.ReverseRecursive(adjNode);
                        adjNode.Next = node;
                        node.Next = null;
                        return rf;
                    }
            

            【讨论】:

              猜你喜欢
              • 2018-11-16
              • 1970-01-01
              • 2020-07-22
              • 2018-12-03
              • 2021-09-25
              • 1970-01-01
              • 2020-12-04
              • 1970-01-01
              相关资源
              最近更新 更多