sorting a doubly linked list with merge sort

前端 未结 5 1522
悲&欢浪女
悲&欢浪女 2020-12-02 01:33

I have found this code in the internet and it was for arrays ,I want to change it for doubly linked list(instead of index we should use pointer) would you please help me tha

5条回答
  •  旧巷少年郎
    2020-12-02 02:21

    Merge sort requires splitting the list quite often. Isn't iterating to the middle of a LinkedList pretty much the most expensive operation you can perform on it (well, short of sorting it)? I could see the merge step working pretty well (you're iterating forwards over two linked lists), but I'm not sure that this implementation is worth the trouble without an O(1) split operation.

    Followup

    As pointed out to me, the O(n) split operation doesn't really add much to complexity when you're already doing O(n) things during the merge phase. Nevertheless, you're still going to run into trouble doing iteration like you're doing (not using an Iterator but instead using get on a List with poor random-access characteristics).

    I was bored while debugging some other issue so wrote you what I consider to be a decent Java implementation of this algorithm. I followed Wikipedia's pseudocode verbatim and sprinkled in some generics and print statements. If you have any questions or concerns, just ask.

    import java.util.List;
    import java.util.LinkedList;
    
    /**
     * This class implements the mergesort operation, trying to stay
     * as close as possible to the implementation described on the
     * Wikipedia page for the algorithm. It is meant to work well
     * even on lists with non-constant random-access performance (i.e.
     * LinkedList), but assumes that {@code size()} and {@code get(0)}
     * are both constant-time.
     *
     * @author jasonmp85
     * @see Merge sort
     */
    public class MergeSort {
        /**
         * Keeps track of the call depth for printing purposes
         */
        private static int depth = 0;
    
        /**
         * Creates a list of 10 random Longs and sorts it
         * using {@link #sort(List)}.
         *
         * Prints out the original list and the result.
         *
         */
        public static void main(String[] args) {
            LinkedList list = new LinkedList();
    
            for(int i = 0; i < 10; i++) {
                list.add((long)(Math.random() * 100));
            }
    
            System.out.println("ORIGINAL LIST\n" + 
                               "=================\n" +
                               list + "\n");
    
            List sorted = sort(list);
    
            System.out.println("\nFINAL LIST\n" +
                               "=================\n" +
                               sorted + "\n");
        }
    
        /**
         * Performs a merge sort of the items in {@code list} and returns a
         * new List.
         *
         * Does not make any calls to {@code List.get()} or {@code List.set()}.
         * 
         * Prints out the steps, indented based on call depth.
         *
         * @param list the list to sort
         */
        public static > List sort(List list) {
            depth++;
            String tabs = getTabs();
    
            System.out.println(tabs + "Sorting: " + list);
    
            if(list.size() <= 1) {
                depth--;
                return list;
            }
    
            List left   = new LinkedList();
            List right  = new LinkedList();
            List result = new LinkedList();
    
            int middle = list.size() / 2;
    
            int added = 0;
            for(T item: list) {
                if(added++ < middle)
                    left.add(item);
                else
                    right.add(item);
            }
    
            left = sort(left);
            right = sort(right);
    
            result = merge(left, right);
    
            System.out.println(tabs + "Sorted to: " + result);
    
            depth--;
            return result;
        }
    
        /**
         * Performs the oh-so-important merge step. Merges {@code left}
         * and {@code right} into a new list, which is returned.
         *
         * @param left the left list
         * @param right the right list
         * @return a sorted version of the two lists' items
         */
        private static > List merge(List left,
                                                               List right) {
            String tabs = getTabs();
            System.out.println(tabs + "Merging: " + left + " & " + right);
    
            List result = new LinkedList();
            while(left.size() > 0 && right.size() > 0) {
                if(left.get(0).compareTo(right.get(0)) < 0)
                    result.add(left.remove(0));
                else
                    result.add(right.remove(0));
            }
    
            if(left.size() > 0)
                result.addAll(left);
            else
                result.addAll(right);
    
            return result;
        }
    
        /**
         * Returns a number of tabs based on the current call depth.
         *
         */
        private static String getTabs() {
            StringBuffer sb = new StringBuffer("");
            for(int i = 0; i < depth; i++)
                sb.append('\t');
            return sb.toString();
        }
    }
    

    To Run

    1. Save the code to a file named MergeSort.java
    2. Run javac MergeSort.java
    3. Run java MergeSort
    4. Marvel
    5. Optionally, run javadoc -private MergeSort.java to create the documentation. Open the index.html file it creates.

提交回复
热议问题