如何交换链表中的相邻节点

How to swap neighbouring nodes in a linked list

我是编程新手,刚开始学习链表,我正在尝试交换列表中的相邻节点。例如:

input 1 2 3 4 5 6 
output 2 1 4 3 6 5

我找到了交换数据​​的解决方案并尝试调整它以交换节点,但我无法使其正常运行。有任何想法吗?一旦我启动 pairWiseSwap,它似乎只是循环,参见第三块。

    // Java program to pairwise swap elements of a linked list
class LinkedList {
    Node head; // head of list

    /* Linked list Node*/
    class Node {
        int data;
        Node next;
        Node(int d)
        {
            data = d;
            next = null;
        }
    }

     public void pairWiseSwap()
    {
        Node temp = head;
        Node swap;


        /* Traverse only till there are atleast 2 nodes left */
        while (temp != null && temp.next != null) {

            /*
            int k = temp.data;
            temp.data = temp.next.data;
            temp.next.data = k;
            temp = temp.next.next;
            */

            // just loops 
            swap = temp;
            temp = temp.next;
            temp.next = swap;
            temp = temp.next.next;

        }
    }

    /* Utility functions */

    /* Inserts a new Node at front of the list. */
    public void push(int new_data)
    {
        /* 1 & 2: Allocate the Node &
                  Put in the data*/
        Node new_node = new Node(new_data);

        /* 3. Make next of new Node as head */
        new_node.next = head;

        /* 4. Move the head to point to new Node */
        head = new_node;
    }

    /* Function to print linked list */
    void printList()
    {
        Node temp = head;
        while (temp != null) {
            System.out.print(temp.data + " ");
            temp = temp.next;
        }
        System.out.println();
    }

    /* Driver program to test above functions */
    public static void main(String args[])
    {
        LinkedList llist = new LinkedList();

        /* Created Linked List 1->2->3->4->5 */
        llist.push(5);
        llist.push(4);
        llist.push(3);
        llist.push(2);
        llist.push(1);

        System.out.println("Linked List before calling pairWiseSwap() ");
        llist.printList();

        llist.pairWiseSwap();

        System.out.println("Linked List after calling pairWiseSwap() ");
        llist.printList();
    }
}

一种方法是操纵对节点的引用。

Node pf; // reference to first node in sequence pointing to Node a
// Node a and Node b are adjacent nodes.

pf -> a -> b -> rest of list

a.next = b.next; // a -> rest of list
b.next = a;      // b -> a
pf.next = b;     // pf -> b
// so now 
pf -> b -> a -> rest of list

当某些 next 引用可能为空时,可能还需要考虑一些边缘情况。因此,请使用边界案例进行测试,以确保无论您是哪两个相邻节点都可以正常工作 "swapping."

如果您在 class 声明中使用泛型,您可以容纳任何类型。

class LinkedList<T> {
    Node head; // head of list

    /* Linked list Node*/
    class Node {
        T data;
        Node next;
        Node(T d)
        {
            data = d;
            next = null;
        }
    }
    // rest of class

将其“写在纸上”会有所帮助。我建议使用三个引用:prevcurrnext,它们在列表中相互跟随:

public void pairWiseSwap()
{
    if (head == null || head.next == null) {
        return;
    }
    Node prev = null;
    Node curr = head;
    Node next;
    head = head.next;
    while (curr != null && curr.next != null) {
        next = curr.next;
        if (prev != null) {
            prev.next = next;  // Link the previously swapped pair to the next pair
        }
        prev = curr;
        curr = next;
        next = curr.next;   // Save curr.next before changing it
        curr.next = prev;
        curr = next;
    }
    if (prev != null) {
        prev.next = curr;
    }
}

你也可以考虑递归解决。

public void pairWiseSwap()
{
    head = swapPair(head);      
}

private Node swapPair(Node curr)
{
    if(curr == null || curr.next == null) return curr;
    
    Node next = curr.next;  
    curr.next = next.next;
    next.next = curr;

    curr.next = swapPair(curr.next);
    
    return next;
}

您可以使用公共代码序列来交换任何一对节点,无论是否相邻。首先交换指向两个节点的内容,然后交换节点中的指针。假设你想交换 b 和 d:

non-adjacent nodes:
a -> b -> c -> d -> e
swap a.next and c.next     a -> d ... c -> b
swap b.next and d.next     b -> e ... d -> c
                           a -> d -> c -> b -> e

adjacent nodes:
a -> b -> d -> e
swap a.next and b.next     a -> d ... b -> b
swap b.next and d.next     b -> e ... d -> b
                           a -> d -> b -> e

如果有一个虚拟头节点不属于实际列表的一部分,那么您不需要特殊代码来处理第一个节点与另一个节点的交换。对于上面的示例,a 可能是虚拟头节点,而实际的初始列表将以 b.

开头