链表的选择排序

Selection sort for linked list

我们已经在 class 中了解了选择排序算法如何处理数组数据结构。在本实验中,我们将练习如何对链表 ADT 执行选择排序。 1.将下面的选择排序伪代码转换为升序排序。 (selectionSort_asc 函数) 一种。在长度为n的链表中找到最小值的节点 b.将最小节点追加到新的结果链表中 C。从原始链表中删除 min d.重复步骤a-c,直到原链表为空 e. Return结果链表 2. 将下面的选择排序伪代码转换为降序排序。 (selectionSort_desc 函数) 一种。在长度为n的链表中找到最大值的节点 b.在新的结果链表中追加最大节点 C。从原始链表中删除 max d.重复步骤a-c,直到原链表为空 e. Return结果链表

我试过下面这段代码,但它没有给我正确的输出。

public class Sort {
    public static void main(String[] args){
        Node head = initializeList("ilovedata"); 
        System.out.println("\n List Before selectionSort_asc");
        printList(head);
        head = selectionSort_asc(head);
        System.out.println("\n List After selectionSort_asc");
        printList(head);
        // Expected answer: -> a -> a -> d -> e -> i -> l -> o -> t -> v
        head = initializeList("ilovedata"); 
        System.out.println("\n List Before selectionSort_desc");
        printList(head);
        head = selectionSort_desc(head);
        System.out.println("\n List After selectionSort_desc");
        printList(head);
        // Expected answer: -> v -> t -> o -> l -> i -> e -> d -> a -> a
        }
        public static Node selectionSort_asc(Node head){ 
            Node result = null;

            Node curr, prev, min;
            while(head!=null) {
                curr = head;
                prev = null;
                min = head;
                while(curr.next!=null) {
                    curr = curr.next;
                    if(curr.item<min.item) {
                        prev = min;
                        min = curr;
                    }
                }
                //append the min at the end of result list
                Node add_min = new Node(min.item);
                if(result==null)
                    result = add_min;
                else {
                    Node last = result;
                    while(last.next!=null) {
                        last = last.next;
                    }
                    last.next = add_min;
                }
                //delete the min node form original list    
                if(min==head) {
                    head = head.next;
                }
                else if(min.next==null){
                    prev.next = null;
                }else {
                    prev.next = prev.next.next;
                    min.next = null;
                }
            }
            return result;
        }
        public static Node selectionSort_desc(Node head){ 
            Node result = null;

            Node curr, prev, max;           
            while(head!=null) {
                curr = head;
                prev = null;
                max = head;
                //find out the max node
                while(curr.next!=null) {
                    curr = curr.next;
                    if(curr.item>max.item) {
                        prev = max;
                        max = curr;
                    }
                }
                //add max to the end of result list             
                Node add_max = new Node(max.item);
                if(result==null) {
                    result = add_max;
                }
                else {
                    Node last = result;
                    while(last.next!=null) {
                        last = last.next;
                    }
                    last.next = add_max;
                }
                //delete min from original list
                if(max == head) {
                    head = head.next;
                }
                else if(max.next==null){
                    prev.next = null;
                }
                else {
                    prev.next = max.next;
                    max.next = null;
                }

            }           
            return result;
        }
        // Method that takes a string and insert its characters into a linked list
        public static Node initializeList(String str){ 
            Node head= new Node(str.charAt(0)),cur; 
            int i;
            for(cur= head,i=1;i<str.length();i++,cur=cur.next){ 
                cur.next = new Node(str.charAt(i));
            }       
            return head;
        }
        // Method for printing linked list 
        public static void printList(Node head){
               Node cur = head;
               if(head==null) 
                   System.out.print("<EMPTY>"); 
               for(;cur!=null;cur=cur.next){
                   System.out.print("-> "+cur.item+" ");
               }
        }
}

问题与这些代码片段中 prev 变量的分配有关

public static Node selectionSort_asc(Node head){ 
...
    if(curr.item><min.item) {
        prev = min;
        min = curr;
    }
...
}

public static Node selectionSort_desc(Node head){ 
...
    if(curr.item>max.item) {
        prev = max;
        max = curr;
    }
...
}

您目前正在将 prev 分配给旧的 min 和旧的 max,但根据您的代码设计,您希望 prev 成为指向新 min 和新 max 之前的节点,以及从原始链表中删除 min 节点的方式。我的建议是保留另一组名为 beforeMinbeforeMax 的变量,并在找到新的最小值或最大值时将它们设置为等于 prev 的当前值。除此之外,您还应该在 while 循环的每次迭代中更新 prev 变量,就像您对 curr 所做的那样。这是 selectionSort_asc 的样子,您可以弄清楚如何调整降序方法以反映它:

public static Node selectionSort_asc(Node head){ 
    Node result = null;

    Node curr, prev, min, beforeMin;
    while(head!=null) {
        curr = head;
        prev = null;
        min = head;
        beforeMin = prev; // new variable
        while(curr.next!=null) {
            prev = curr; // update prev with each iteration
            curr = curr.next;
            if(curr.item<min.item) {
                beforeMin = prev; // variable points to the node before the min node
                min = curr;
            }
        }
        //append the min at the end of result list
        Node add_min = new Node(min.item);
        if(result==null)
            result = add_min;
        else {
            Node last = result;
            while(last.next!=null) {
                last = last.next;
            }
            last.next = add_min;
        }
        //delete the min node form original list    
        if(min==head) {
            head = head.next;
        }
        else if(min.next==null){
            beforeMin.next = null; // no more prev here
        }else {
            beforeMin.next = beforeMin.next.next; // notice how beforeMin is used now
            min.next = null;
        }
    }
    return result;
}