反向单链表Java [重复]

Posted

技术标签:

【中文标题】反向单链表Java [重复]【英文标题】:Reverse Singly Linked List Java [duplicate] 【发布时间】:2014-05-01 13:16:03 【问题描述】:

谁能告诉我为什么我的代码不起作用?我想在java中反转单个链表:这是方法(不能正常工作)

public void reverseList()
    Node before = null;
    Node tmp = head;
    Node next = tmp.next;
    while(tmp != null)
      if(next == null)
         return;
      tmp.next = before;
      before = tmp;
      tmp = next;
      next = next.next;
    

这是 Node 类:

public class Node
   public int data;
   public Node next;
   public Node(int data, Node next)
      this.data = data;
      this.next = next;
   

在输入 4->3->2->1 上,我得到了输出 4。我对其进行了调试,它正确设置了指针,但我仍然不明白为什么它只输出 4。

【问题讨论】:

用动画完成逐步解释。单次迭代的最佳解决方案。 youtube.com/watch?v=txqLgAdgyVM&t=83s 【参考方案1】:
Node next = tmp.next;
while(tmp != null)

那么当 tmp == null 时会发生什么?

不过,你几乎明白了。

Node before = null;
Node tmp = head;
while (tmp != null) 
    Node next = tmp.next;
    tmp.next = before;
    before = tmp;
    tmp = next;

head = before;

或者更好的 (?) 命名:

Node reversedPart = null;
Node current = head;
while (current != null) 
    Node next = current.next;
    current.next = reversedPart;
    reversedPart = current;
    current = next;

head = reversedPart;

ASCII艺术:

        <__<__<__ __ : reversedPart    : head
                 (__)__ __ __
head :   current:      >  >  >

【讨论】:

嘿,我们不能把“Node next = current.next”这一行放在while循环之外吗?只需将“next = current.next”放在while循环中?就像对于 reversedPart 和 current 一样,我们只是将 "Node next = null" 放在 while 循环之外? @Satnamxv63 感谢您的想法,但在 java 中,循环内部的声明与外部的声明不同。只为next 保留一个变量槽。 @dharam 不错;只能以动画 gif 等作为顶部。 @JoopEggen 谢谢。关于动图,下次注意。 用动画完成逐步解释。单次迭代的最佳解决方案。 youtube.com/watch?v=txqLgAdgyVM&t=83s【参考方案2】:

使用这个。

if (current== null || current.next==null) return current;
 Node nextItem = current.next;
 current.next = null;
 Node reverseRest = reverse(nextItem);
 nextItem.next = current;
 return reverseRest

或Java Program to reverse a Singly Linked List

【讨论】:

【参考方案3】:

我认为你的问题是你最初的最后一个元素 next 属性没有因为你的条件而改变

if(next == null)
     return;

在循环的开头。

我会在 tmp.next 被分配后立即移动它:

while(tmp != null)

  tmp.next = before;
  if(next == null)
     return;
  before = tmp;
  tmp = next;
  next = next.next;

【讨论】:

【参考方案4】:
public void reverse() 
    Node prev = null; Node current = head; Node next = current.next;
    while(current.next != null) 
        current.next = prev;
        prev = current;
        current = next;
        next = current.next;
    
    current.next = prev;
    head = current;

【讨论】:

【参考方案5】:
public Node<E> reverseList(Node<E> node) 
    if (node == null || node.next == null) 
        return node;
    
    Node<E> currentNode = node;
    Node<E> previousNode = null;
    Node<E> nextNode = null;

    while (currentNode != null) 
        nextNode = currentNode.next;
        currentNode.next = previousNode;
        previousNode = currentNode;
        currentNode = nextNode;
    
    return previousNode;

【讨论】:

用动画完成逐步解释。单次迭代的最佳解决方案。 youtube.com/watch?v=txqLgAdgyVM&t=83s【参考方案6】:

我尝试了下面的代码,它工作正常:

Node head = firstNode;
Node current = head;
while(current != null && current.next != null)
    Node temp = current.next;
    current.next = temp.next;
    temp.next = head;
    head = temp;

基本上,它将一个节点的下一个指针设置为它的下一个节点,因此从下一个开始,所有节点都附加在列表的后面。

【讨论】:

虽然这个代码块可以回答这个问题,但如果你能提供一些解释为什么它会这样做,那将是一个更好的答案。【参考方案7】:
package com.three;

public class Link 

    int a;
    Link Next;

    public Link(int i)
        a=i;
    



public class LinkList 

    Link First = null;

    public void insertFirst(int a)
        Link objLink = new Link(a);

        objLink.Next=First;
        First = objLink;

    

    public void displayLink()

        Link current = First;
        while(current!=null)
            System.out.println(current.a);
            current = current.Next;
        

    

    public void ReverseLink()
        Link current = First;
        Link Previous = null;
        Link temp = null;

        while(current!=null)

            if(current==First)
                temp = current.Next;
            else
                temp=current.Next;

            if(temp==null)
                First = current;
                //return;
            
            current.Next=Previous;
            Previous=current;
            //System.out.println(Previous);
            current = temp;
        

    

    public static void main(String args[])

        LinkList objLinkList = new LinkList();
        objLinkList.insertFirst(1);
        objLinkList.insertFirst(2);
        objLinkList.insertFirst(3);
        objLinkList.insertFirst(4);
        objLinkList.insertFirst(5);
        objLinkList.insertFirst(6);
        objLinkList.insertFirst(7);
        objLinkList.insertFirst(8);
        objLinkList.displayLink();
        System.out.println("-----------------------------");
        objLinkList.ReverseLink();
        objLinkList.displayLink();

    


【讨论】:

您的答案似乎全是代码。最佳答案解释了代码中发生了什么【参考方案8】:

你也可以试试这个

    LinkedListNode pointer = head;
    LinkedListNode prev = null, curr = null;

    /* Pointer variable loops through the LL */
    while(pointer != null)
    
        /* Proceed the pointer variable. Before that, store the current pointer. */
        curr = pointer; //          
        pointer = pointer.next;         

        /* Reverse the link */
        curr.next = prev;

        /* Current becomes previous for the next iteration */
        prev = curr;            
    

    System.out.println(prev.printForward());

【讨论】:

【参考方案9】:

如果这不是家庭作业,并且您是故意“手动”执行此操作,那么我建议您使用

Collections.reverse(list);

Collections.reverse() 返回 void,调用后你的列表反转。

【讨论】:

我可以知道为什么-1吗? Collections.reverse() 反转一个列表,这就是问题所在,不是吗? 问题中提供的 Node 类不是 List 类型,因此不能作为 Collections.reverse(List list) 方法的参数。请注意,这是一个单链表,不使用任何 Java 的链表实现。如果问题试图逆转例如 LinkedList 对象,您的答案将是正确的。【参考方案10】:

我知道递归解决方案不是最佳解决方案,但只想在这里添加一个:

public class LinkedListDemo 

    static class Node 
        int val;
        Node next;

        public Node(int val, Node next) 
            this.val = val;
            this.next = next;
        

        @Override
        public String toString() 
            return "" + val;
        
    

    public static void main(String[] args) 
        Node n = new Node(1, new Node(2, new Node(3, new Node(20, null))));
        display(n);
        n = reverse(n);
        display(n);
    

    static Node reverse(Node n) 
        Node tail = n;
        while (tail.next != null) 
            tail = tail.next;
        
        reverseHelper(n);
        return (tail);
    

    static Node reverseHelper(Node n) 
        if (n.next != null) 
            Node reverse = reverseHelper(n.next);
            reverse.next = n;
            n.next = null;
            return (n);
        
        return (n);
    

    static void display(Node n) 
        for (; n != null; n = n.next) 
            System.out.println(n);
        
    

【讨论】:

【参考方案11】:

我不明白...为什么不这样做:

private LinkedList reverseLinkedList(LinkedList originalList)
    LinkedList reversedList = new LinkedList<>();

    for(int i=0 ; i<originalList.size() ; i++)
        reversedList.add(0, originalList.get(i));
    

    return reversedList;

我觉得这更容易。

【讨论】:

因为问题是关于单链表,而您的解决方案使用 Java 的 LinkedList,它有许多基本单链表没有的功能。例如,如果 Java 没有提供 get(index) 方法,您的代码将无法运行。在这种情况下,Node 类没有这样的方法。 这更容易,而且您浪费了两倍的内存,因此您提供的代码不是内存效率的。此外,您甚至不知道垃圾收集器何时会释放未使用的旧列表。【参考方案12】:

更优雅的解决方案是使用递归

void ReverseList(ListNode current, ListNode previous) 
            if(current.Next != null) 
            
                ReverseList(current.Next, current);
                ListNode temp = current.Next;
                temp.Next = current;
                current.Next = previous;
            
        

【讨论】:

在一个非常大的列表中,此代码会发生堆栈溢出。使用递归而不是使用迭代解决方案是一个糟糕的选择。【参考方案13】:

链表反转的方法如下;

逆向法

public void reverseList() 
    Node<E> curr = head;
    Node<E> pre = null;
    Node<E> incoming = null;

    while(curr != null) 
        incoming = curr.next;   // store incoming item

        curr.next = pre;        // swap nodes
        pre = curr;             // increment also pre

        curr = incoming;        // increment current
    

    head = pre; // pre is the latest item where
                // curr is null

反转列表需要三个引用:precurrincoming

...      pre     curr    incoming
... --> (n-1) --> (n) --> (n+1) --> ...

要反转一个节点,你必须存储 previous 元素,这样你就可以使用简单的语句;

curr.next = pre;

反转当前元素的方向。但是,要遍历列表,您必须在执行上述语句之前存储传入的元素,因为在反转当前元素的下一个引用时,您不再知道传入的元素,这就是需要第三个引用的原因。

演示代码如下;

LinkedList 示例类

public class LinkedList<E> 

    protected Node<E> head;

    public LinkedList() 
        head = null;
    

    public LinkedList(E[] list) 
        this();
        addAll(list);
    

    public void addAll(E[] list) 
        for(int i = 0; i < list.length; i++)
            add(list[i]);
    

    public void add(E e) 
        if(head == null)
            head = new Node<E>(e);
        else 
            Node<E> temp = head;

            while(temp.next != null)
                temp = temp.next;

            temp.next = new Node<E>(e);
        
    

    public void reverseList() 
        Node<E> curr = head;
        Node<E> pre = null;
        Node<E> incoming = null;

        while(curr != null) 
            incoming = curr.next;   // store incoming item

            curr.next = pre;        // swap nodes
            pre = curr;             // increment also pre

            curr = incoming;        // increment current
        

        head = pre; // pre is the latest item where
                    // curr is null
    

    public void printList() 
        Node<E> temp = head;

        System.out.print("List: ");
        while(temp != null) 
            System.out.print(temp + " ");
            temp = temp.next;
        

        System.out.println();
    

    public static class Node<E> 

        protected E e;
        protected Node<E> next;

        public Node(E e) 
            this.e = e;
            this.next = null;
        

        @Override
        public String toString() 
            return e.toString();
        

    


测试代码

public class ReverseLinkedList 

    public static void main(String[] args) 
        Integer[] list =  4, 3, 2, 1 ;

        LinkedList<Integer> linkedList = new LinkedList<Integer>(list);

        linkedList.printList();
        linkedList.reverseList();
        linkedList.printList();
    


输出

List: 4 3 2 1 
List: 1 2 3 4 

【讨论】:

一个非常好的和明确的答案!应该得到更多的选票。 用动画完成逐步解释。单次迭代的最佳解决方案。 youtube.com/watch?v=txqLgAdgyVM&t=83s【参考方案14】:
Node reverse_rec(Node start) 
    if (start == null || start -> next == null) 
       return start;
    

    Node new_start = reverse(start->next);
    start->next->next = start;
    start->next = null;
    return new_start;



Node reverse(Node start) 
    Node cur = start;
    Node bef = null;

    while (cur != null) 
       Node nex = cur.next;
       cur.next = bef;
       bef = cur;
       cur = nex;
    
    return bef;

【讨论】:

【参考方案15】:
public class SinglyLinkedListImpl<T> 

    private Node<T> head;

    public void add(T element) 
        Node<T> item = new Node<T>(element);
        if (head == null) 
            head = item;
         else 
            Node<T> temp = head;
            while (temp.next != null) 
                temp = temp.next;
            
            temp.next = item;
        
    

    private void reverse() 

        Node<T> temp = null;
        Node<T> next = null;
        while (head != null) 
            next = head.next;
            head.next = temp;
            temp = head;
            head = next;
        
        head = temp;
    

    void printList(Node<T> node) 
        while (node != null) 
            System.out.print(node.data + " ");
            node = node.next;
        
        System.out.println();
    

    public static void main(String a[]) 
        SinglyLinkedListImpl<Integer> sl = new SinglyLinkedListImpl<Integer>();
        sl.add(1);
        sl.add(2);
        sl.add(3);
        sl.add(4);

        sl.printList(sl.head);
        sl.reverse();
        sl.printList(sl.head);

    

    static class Node<T> 

        private T data;
        private Node<T> next;

        public Node(T data) 
            super();
            this.data = data;
        

    

【讨论】:

【参考方案16】:

我们可以有三个节点previous、current和next。

public void reverseLinkedlist()

    /*
     * Have three nodes i.e previousNode,currentNode and nextNode
 When currentNode is starting node, then previousNode will be null
 Assign currentNode.next to previousNode to reverse the link.
 In each iteration move currentNode and previousNode by  1 node.
     */

    Node previousNode = null;
    Node currentNode = head;
    while (currentNode != null) 
    
        Node nextNode = currentNode.next;
        currentNode.next = previousNode;
        previousNode = currentNode;
        currentNode = nextNode;
    
    head = previousNode;

【讨论】:

【参考方案17】:
package LinkedList;

import java.util.LinkedList;

public class LinkedListNode 

    private int value;
    private LinkedListNode next = null;

    public LinkedListNode(int i) 
        this.value = i;
    

    public LinkedListNode addNode(int i) 
        this.next = new LinkedListNode(i);
        return next;
    

    public LinkedListNode getNext() 
        return next;
    

    @Override
    public String toString() 
        String restElement = value+"->";
        LinkedListNode newNext = getNext();
        while(newNext != null)
            restElement = restElement + newNext.value + "->";
            newNext = newNext.getNext();
        restElement = restElement +newNext;
        return restElement;
    

    public static void main(String[] args) 
        LinkedListNode headnode = new LinkedListNode(1);
        headnode.addNode(2).addNode(3).addNode(4).addNode(5).addNode(6);

        System.out.println(headnode);
        headnode = reverse(null,headnode,headnode.getNext());

        System.out.println(headnode);
    

    private static LinkedListNode reverse(LinkedListNode prev, LinkedListNode current, LinkedListNode next) 
        current.setNext(prev);
        if(next == null)
            return current;
         return reverse(current,next,next.getNext());   
    

    private void setNext(LinkedListNode prev) 
        this.next = prev;
    

【讨论】:

【参考方案18】:
public class Linkedtest 
    public static void reverse(List<Object> list) 

        int lenght = list.size();
        for (int i = 0; i < lenght / 2; i++) 
            Object as = list.get(i);
            list.set(i, list.get(lenght - 1 - i));
            list.set(lenght - 1 - i, as);
        
    
    public static void main(String[] args) 
        LinkedList<Object> st = new LinkedList<Object>();
        st.add(1);
        st.add(2);
        st.add(3);
        st.add(4);
        st.add(5);
        Linkedtest.reverse(st);
        System.out.println("Reverse Value will be:"+st);
    

这对于任何类型的集合对象都很有用。

【讨论】:

检查其测试代码【参考方案19】:
public class ReverseLinkedList 

    public static void main(String args[])
        LinkedList<String> linkedList = new LinkedList<String>();
        linkedList.add("a");
        linkedList.add("b");
        linkedList.add("c");
        linkedList.add("d");
        linkedList.add("e");
        linkedList.add("f");
        System.out.println("Original linkedList:");
        for(int i = 0; i <=linkedList.size()-1; i++)

            System.out.println(" - "+ linkedList.get(i));

        
        LinkedList<String> reversedlinkedList = reverse(linkedList);
        System.out.println("Reversed linkedList:");
        for(int i = 0; i <=reversedlinkedList.size()-1; i++)
            System.out.println(" - "+ reversedlinkedList.get(i));

        
    

    public static LinkedList<String> reverse(LinkedList<String> linkedList)

        for(int i = 0; i < linkedList.size()/2; i++)
            String temp = linkedList.get(i);
            linkedList.set(i, linkedList.get(linkedList.size()-1-i));
            linkedList.set((linkedList.size()-1-i), temp);
        
        return linkedList;
    

【讨论】:

通过get()和set()访问链表无效;每次访问都可以从头或尾进行迭代【参考方案20】:

要反转单链表,您应该有三个节点,topbeforeTopAfterTop。 Top 是单链表的标题,因此 beforeTop 将为 null 而 afterTop 将是 top 的下一个元素,并且每次迭代都向前推进 beforeTop 被分配 top 并且 top 被分配 afterTop(即 top.下一个)。

private static Node inverse(Node top) 
        Node beforeTop=null, afterTop;
        while(top!=null)
            afterTop=top.next;
            top.next=beforeTop;
            beforeTop=top;
            top=afterTop;
        
        return beforeTop;
    

【讨论】:

【参考方案21】:

使用递归太简单了:

package com.config;

import java.util.Scanner;

public class Help 

    public static void main(String args[])

        Scanner sc = new Scanner(System.in);
        Node head = null;
        Node temp = null;
        int choice = 0;
        boolean flage = true;
        do
            Node node = new Node();
            System.out.println("Enter Node");
            node.data = sc.nextInt();
            if(flage)
                head = node;
                flage = false;
            
            if(temp!=null)
                temp.next = node;
            temp = node;

            System.out.println("Enter 0 to exit.");
            choice = sc.nextInt();
        while(choice!=0);

        Help.getAll(head);

        Node reverse = Help.reverse(head,null);
        //reverse = Help.reverse(head, null);

        Help.getAll(reverse);

    

    public static void getAll(Node head)
        if(head==null)
            return ;
        System.out.println(head.data+"Memory Add "+head.hashCode());
        getAll(head.next);
    

    public static Node reverse(Node head,Node tail)
        Node next = head.next;
        head.next = tail;
        return (next!=null? reverse(next,head) : head);
    


class Node
    int data = 0;
    Node next = null;

【讨论】:

【参考方案22】:
    // Java program for reversing the linked list
    class LinkedList 

        static Node head;

        static class Node 

            int data;
            Node next;

            Node(int d) 
                data = d;
                next = null;
            
        

      //  Function to reverse the linked list 
        Node reverse(Node node) 
            Node prev = null;
            Node current = node;
            Node next = null;
            while (current != null) 
                next = current.next;
                current.next = prev;
                prev = current;
                current = next;
            
            node = prev;
            return node;
        




        // prints content of double linked list
        void printList(Node node) 
            while (node != null) 
                System.out.print(node.data + " ");
                node = node.next;
            
        


        public static void main(String[] args) 
            LinkedList list = new LinkedList();
            list.head = new Node(85);
            list.head.next = new Node(15);
            list.head.next.next = new Node(4);
            list.head.next.next.next = new Node(20);

            System.out.println("Given Linked list");
            list.printList(head);
            head = list.reverse(head);
            System.out.println("");
            System.out.println("Reversed linked list ");
            list.printList(head);
        
    


OUTPUT: -

Given Linked list
85 15 4 20 
Reversed linked list 
20 4 15 85 

【讨论】:

请解释您的答案在做什么以及它是如何做到的【参考方案23】:
Node Reverse(Node head) 
        Node n,rev;
        rev = new Node();
        rev.data = head.data;
        rev.next = null;


        while(head.next != null)
            n = new Node();
            head = head.next;
            n.data = head.data;
            n.next = rev;
            rev = n;
            n=null;


        
    return rev;

使用上述函数反转单链表。

【讨论】:

【参考方案24】:
 public ListNode reverseList(ListNode head) 
    ListNode prev = null;
    ListNode curr = head;
    while (curr != null) 
        ListNode nextTemp = curr.next;
        curr.next = prev;
        prev = curr;
        curr = nextTemp;
    
    return prev;

查看有关复杂性分析的更多详细信息 http://javamicro.com/ref-card/DS-Algo/How-to-Reverse-Singly-Linked-List?

【讨论】:

如果您更好地评论您的方法以仅包含一个链接会很好。【参考方案25】:
public static LinkedList reverseLinkedList(LinkedList node) 
    if (node == null || node.getNext() == null) 
        return node;
    

    LinkedList remaining = reverseLinkedList(node.getNext());
    node.getNext().setNext(node);
    node.setNext(null);
    return remaining;

【讨论】:

【参考方案26】:
/**
 * Reverse LinkedList
 * @author asharda
 *
 */

class Node

  int data;
  Node next;
  Node(int data)
  
    this.data=data;
  

public class ReverseLinkedList 

  static Node root;
  Node temp=null;
  public void insert(int data)
  
    if(root==null)
    
      root=new Node(data);

    
    else
    
      temp=root;
      while(temp.next!=null)
      
        temp=temp.next;
      

      Node newNode=new Node(data);
      temp.next=newNode;
    
  //end of insert

  public void display(Node head)
  
    while(head!=null)
    
      System.out.println(head.data);
      head=head.next;
    

  

  public Node reverseLinkedList(Node head)
  
    Node newNode;
    Node tempr=null;
    while(head!=null)
    
      newNode=new Node(head.data);
      newNode.next=tempr;
      tempr=newNode;
      head=head.next;
    
    return tempr;
  
  public static void main(String[] args) 

    ReverseLinkedList r=new ReverseLinkedList();
    r.insert(10);
    r.insert(20);
    r.insert(30);
    r.display(root);
    Node t=r.reverseLinkedList(root);
    r.display(t);
  


【讨论】:

以上是关于反向单链表Java [重复]的主要内容,如果未能解决你的问题,请参考以下文章

数据结构之单链表反向查找

单链表 C 反向数据读取

java数据结构:单链表常见操作代码实现

c_cpp FP风格的反向单链表

13.删除单链表中重复的元素

线性表练习之Example002-删除递增非空单链表中的重复值域节点