обратносвязный список между заданными узлами в двусвязном списке - алгоритм

Я пишу код для обращения двусвязного списка между заданными узлами.

учитывая этот связанный список 1->2->3->4->5,

функция reverse(2,4) должна привести к 1->4->3->2->5.

функция принимает два узла, но не индексы.

Вот что у меня есть. Я попробовал отладчик Eclipse, чтобы понять, почему это работает бесконечно. по некоторым причинам я вижу, что узлы повреждены (Eclipse не показывает данных, когда я перехожу через строку, отмеченную ниже)

public static void reverse(Node head, Node tail){
        Node prev=head.prev;
        Node current=head,next;
        while(current!=tail.next){
            next = current.next;
            current.next=prev;
            current.prev=next; //No data stepping after this point
            prev=current;
            current=next;
        }
    }

public static void main(String... args){
        Node one = new Node(1);
        Node two = new Node(2);
        Node three = new Node(3);
        Node four = new Node(4);
        Node five = new Node(5);

        five.setNodes(four, null);
        four.setNodes(three, five);
        three.setNodes(two,four);
        two.setNodes(one,three);
        one.setNodes(null, two);

        System.out.println("before reversing...");
        System.out.println(one);

        System.out.println("After reversing...");
        reverse(two,four);
        System.out.println(one);

}

Вот мой класс узла

class Node {
     Node prev;
     Node next;
     int data;

     public Node(Node prev, Node next, int val){
         this.prev=prev;
         this.next=next;
         this.data=val;
     }

     public Node(int val){
         this(null,null,val);
     }

     public void setNodes(Node prev, Node next){
         this.next=next;
         this.prev=prev;
         }

     public String toString(){
         String toReturn = "[ " + this.data;

         Node current=this.next;
         while (current!=null){
             toReturn+=" -> " + current.data;
             current=current.next;
         }
         toReturn+=" ]";
         return toReturn;
     }

}

person brain storm    schedule 22.01.2016    source источник
comment
Является ли Node current=head,next; опечаткой (запятой)? Это должно было быть Node current=head.next;   -  person user1952500    schedule 23.01.2016
comment
@brainstorm позаботьтесь о методе toString.   -  person David Pérez Cabrera    schedule 23.01.2016


Ответы (1)


Попробуйте с этим:

public static void reverse(Node head, Node tail) {
    Node first = head;
    Node last = tail;
    while (first != last && first.prev != last) {
        Node preFirst = first.prev;
        Node postFirst = first.next;
        Node preLast = last.prev;
        Node postLast = last.next;
        if (preFirst != null) {
            preFirst.next = last;
        }
        if (postLast != null) {
            postLast.prev = first;
        }
        last.prev = preFirst;
        first.next = postLast;
        if (last != postFirst){
            last.next = postFirst;
            postFirst.prev = last;
            first.prev = preLast;
            preLast.next = first;
            first = postFirst;
            last = preLast;
        } else {
            last.next = first;
            first.prev = last;
        }
    }
}

Будьте осторожны с методом toString, он очень важен даже для отладки!

public String toString(){
     String toReturn = "[ " + this.data;

     Node current=this.next;
     while (current!=null && current != this){ // <- cycle protection
         toReturn+=" -> " + current.data;
         current=current.next;
     }
     toReturn+=" ]";
     return toReturn;
 }

ИЗМЕНИТЬ

Он всегда возвращает головной узел:

public static Node reverse(Node head, Node tail) {
    Node first = head;
    Node last = tail;
    while (first != last && first.prev != last) {
        Node preFirst = first.prev;
        Node postFirst = first.next;
        Node preLast = last.prev;
        Node postLast = last.next;
        if (preFirst != null) {
            preFirst.next = last;
        }
        if (postLast != null) {
            postLast.prev = first;
        }
        last.prev = preFirst;
        first.next = postLast;
        if (last != postFirst){
            last.next = postFirst;
            postFirst.prev = last;
            first.prev = preLast;
            preLast.next = first;
            first = postFirst;
            last = preLast;
        } else {
            last.next = first;
            first.prev = last;
        }
    }
    Node result = tail;
    while (result.prev != null){
        result = result.prev;
    }
    return result;
}

Пример:

public static void main(String... args) {
    Node one = new Node(1);
    Node two = new Node(2);
    Node three = new Node(3);
    Node four = new Node(4);
    Node five = new Node(5);

    five.setNodes(four, null);
    four.setNodes(three, five);
    three.setNodes(two, four);
    two.setNodes(one, three);
    one.setNodes(null, two);

    System.out.println("before reversing...");
    System.out.println(one);

    System.out.println("After reversing...");
    one = reverse(one, three);
    System.out.println(one);
}

печатает:

before reversing...
[ 1 -> 2 -> 3 -> 4 -> 5 ]
After reversing...
[ 3 -> 2 -> 1 -> 4 -> 5 ]
person David Pérez Cabrera    schedule 22.01.2016
comment
когда я просматриваю свой код выше на бумаге, я вижу, что он должен работать. но это не так!. спасибо за указание на ошибку в методе toString - person brain storm; 23.01.2016
comment
@brainstorm Вы должны поменять местами пару узлов! Подумайте, что пре-голова и пост-хвост должны быть правильно связаны, вы должны иметь возможность поменять местами нечетное/парное количество узлов (2,4) и (3,4) - person David Pérez Cabrera; 23.01.2016
comment
почему вы делаете обмен? вы должны измениться между заданными узлами. - person brain storm; 23.01.2016
comment
Кстати, вы пробовали реверс (два, пять) с вашим кодом? это не работает - person brain storm; 23.01.2016
comment
поскольку это двусвязный список, вам необходимо сохранить предыдущие и следующие ссылки. Если вы перевернете этот список 1->2->3->4->5->6->7->8 между 2 и 7, первым шагом может быть замена (2,7) 1->7->3->4->5->6->2->8 и повторение с (3,6), (4,5). - person David Pérez Cabrera; 23.01.2016
comment
Я понимаю вашу точку зрения. но ваш код не работал с реверсом (два, пять). Я думаю, это из-за подмены мышления - person brain storm; 23.01.2016
comment
@brainstorm извините, отредактировано! нулевая защита была превышена! - person David Pérez Cabrera; 23.01.2016
comment
Давайте продолжим обсуждение в чате. - person brain storm; 23.01.2016
comment
Вы пробовали реверс (один, три)? - person brain storm; 23.01.2016
comment
@brainstorm да, и это работает! попробуйте System.out.println(три); после реверса (раз, три) - person David Pérez Cabrera; 23.01.2016
comment
Попробуйте System.out.println(one); в основном реверсирование первых трех узлов из пяти узлов - person brain storm; 23.01.2016
comment
@brainstorm после реверса, один не голова! три голова! - person David Pérez Cabrera; 23.01.2016
comment
да, я понял это. поэтому метод должен возвращать голову? - person brain storm; 23.01.2016
comment
@brainstorm Я пытался сохранить исходный интерфейс, но здесь я отредактировал по вашему предложению - person David Pérez Cabrera; 23.01.2016
comment
почему у вас есть эта проверка во время цикла? first.prev != last? - person brain storm; 23.01.2016
comment
@brainstorm для реверсирования пары узлов. Пример: 1->2->3->4->5->6 reverse(2,5) -> (1-й) 1-5-3-4-2-6 (2-й) -> 1-5-4-3-2-6 и теперь первый:3, последний:4 и выполняется обратное. - person David Pérez Cabrera; 24.01.2016