Инвертирование связанного списка в Java, рекурсивно

97
задан Peter Mortensen 16 November 2014 в 20:42
поделиться

7 ответов

Существует код в одном ответе, который обстоятельно объясняет его, но Вы могли бы найти легче запуститься с самого начала путем выяснения и ответа на крошечные вопросы (это - подход в Небольшом Lisper):

  1. , Каков реверс пустого указателя (пустой список)? пустой указатель.
  2. , Каков реверс одного списка элемента? элемент.
  3. , Каков реверс n списка элемента? реверс остальной части списка, сопровождаемого первым элементом.
<час>
public ListNode Reverse(ListNode list)
{
    if (list == null) return null; // first question

    if (list.next == null) return list; // second question

    // third question - in Lisp this is easy, but we don't have cons
    // so we grab the second element (which will be the last after we reverse it)

    ListNode secondElem = list.next;

    // bug fix - need to unlink list from the rest or you will get a cycle
    list.next = null;

    // then we reverse everything from the second element on
    ListNode reverseRest = Reverse(secondElem);

    // then we join the two lists
    secondElem.next = list;

    return reverseRest;
}
312
ответ дан piritocle 24 November 2019 в 05:19
поделиться

Алгоритм должен будет работать над следующей моделью,

  • отслеживают голову
  • , Рекурсивно вызывают до конца связи Реверса linklist

Структура:

Head    
|    
1-->2-->3-->4-->N-->null

null-->1-->2-->3-->4-->N<--null

null-->1-->2-->3-->4<--N<--null

null-->1-->2-->3<--4<--N<--null

null-->1-->2<--3<--4<--N<--null

null-->1<--2<--3<--4<--N<--null

null<--1<--2<--3<--4<--N
                       |
                       Head

Код:

public ListNode reverse(ListNode toBeNextNode, ListNode currentNode)
{               
        ListNode currentHead = currentNode; // keep track of the head

        if ((currentNode==null ||currentNode.next==null )&& toBeNextNode ==null)return currentHead; // ignore for size 0 & 1

        if (currentNode.next!=null)currentHead = reverse(currentNode, currentNode.next); // travarse till end recursively

        currentNode.next = toBeNextNode; // reverse link

        return currentHead;
}

Вывод:

head-->12345

head-->54321
8
ответ дан abatishchev 24 November 2019 в 05:19
поделиться

Меня задали этот вопрос на интервью и раздражали, что я возился с ним, так как я был немного возбужден.

Это должно инвертировать отдельно связанный список, названный с реверсом (голова, ПУСТОЙ УКАЗАТЕЛЬ); таким образом, если это было Вашим списком:

1->2->3->4->5->null
it would become:
5->4->3->2->1->null

    //Takes as parameters a node in a linked list, and p, the previous node in that list
    //returns the head of the new list
    Node reverse(Node n,Node p){   
        if(n==null) return null;
        if(n.next==null){ //if this is the end of the list, then this is the new head
            n.next=p;
            return n;
        }
        Node r=reverse(n.next,n);  //call reverse for the next node, 
                                      //using yourself as the previous node
        n.next=p;                     //Set your next node to be the previous node 
        return r;                     //Return the head of the new list
    }
    

редактирование: я сделал как 6 редактирований на этом, показав, что это все еще немного коварно для меня lol

29
ответ дан selpak 24 November 2019 в 05:19
поделиться

Я прошел половину пути (до нуля и одного узла, как указано в плинтусе), но потерял след после выполнения рекурсивного вызова. Однако после прочтения поста у постамента я пришел к следующему:

Node reverse(Node head) {
  // if head is null or only one node, it's reverse of itself.
  if ( (head==null) || (head.next == null) ) return head;

  // reverse the sub-list leaving the head node.
  Node reverse = reverse(head.next);

  // head.next still points to the last element of reversed sub-list.
  // so move the head to end.
  head.next.next = head;

  // point last node to nil, (get rid of cycles)
  head.next = null;
  return reverse;
}
22
ответ дан 24 November 2019 в 05:19
поделиться
void reverse(node1,node2){
if(node1.next!=null)
      reverse(node1.next,node1);
   node1.next=node2;
}
call this method as reverse(start,null);
4
ответ дан 24 November 2019 в 05:19
поделиться

Я думаю, что это более чистое решение, напоминающее LISP

// Example:
// reverse0(1->2->3, null) => 
//      reverse0(2->3, 1) => 
//          reverse0(3, 2->1) => reverse0(null, 3->2->1)
// once the first argument is null, return the second arg
// which is nothing but the reveresed list.

Link reverse0(Link f, Link n) {
    if (f != null) {
        Link t = new Link(f.data1, f.data2); 
        t.nextLink = n;                      
        f = f.nextLink;             // assuming first had n elements before, 
                                    // now it has (n-1) elements
        reverse0(f, t);
    }
    return n;
}
7
ответ дан 24 November 2019 в 05:19
поделиться

Я знаю, что это старое сообщение, но большинство ответов не являются хвостовыми рекурсивными, т.е. они выполняют некоторые операции после возврата из рекурсивного вызова, и поэтому не являются самыми эффективными.

Вот хвостовая рекурсивная версия:

public Node reverse(Node previous, Node current) {
    if(previous == null)
        return null;
    if(previous.equals(head))
        previous.setNext(null);
    if(current == null) {    // end of list
        head = previous;
        return head;
    } else {
                    Node temp = current.getNext();
        current.setNext(previous);
        reverse(current, temp);
    }
    return null;    //should never reach here.
} 

Вызов с:

Node newHead = reverse(head, head.getNext());
7
ответ дан 24 November 2019 в 05:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: