排序算法总结

作者: Megahorn | 来源:发表于2019-06-20 07:50 被阅读0次
    类别 排序方法 平均情况 最好情况 最坏情况 空间复杂度 稳定性
    插入排序 插入排序 O(n^2) O(n) O(n^2) O(1) 稳定
    插入排序 Shell排序 O(n^{1.3}) O(n) O(n^2) O(1) 不稳定
    选择排序 选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定
    选择排序 堆排序 O(nlog_{2}n) O(nlog_{2}n) O(nlog_{2}n) O(1) 不稳定
    交换排序 冒泡排序 O(n^2) O(n) O(n^2) O(1) 稳定
    交换排序 快速排序 O(nlog_{2}n) O(nlog_{2}n) O(n^2) O(nlog_{2}n) 不稳定
    归并排序 归并排序 O(nlog_{2}n) O(nlog_{2}n) O(nlog_{2}n) O(n) 稳定
    基数排序 基数排序 O(d(r+n)) O(d(n+rd)) O(d(r+n)) O(rd+n) 稳定

    基数排序中r代表关键字的基数,d代表长度,n代表关键字的个数

    package com.sort_algorithm;
    
    import java.util.Arrays;
    
    public class SortSummarize {
    
        public static void main(String[] args) {
            int[] a = { 9, 8, 7, 6, 5, 1, 3, 0, 10, -1, 99, -10 };
            int[] b = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 16 };
            // 将a的地址也就是引用给了b,使b的引用发生了改变。此时打印,其实打印的是同一个地址下的数组,
            // 此时a、b都指向a的值,原来的b数组会因为没有被引用到,被JVM的GC回收
            b = a;
            // 将b的地址也就是引用给了a,使a的引用发生了改变。此时打印,其实打印的是同一个地址下的数组,
            // 此时a、b都指向b的值,原来的a数组会因为没有被引用到,被JVM的GC回收
            // a = b;
            print("选择排序 ", selectSort(a));
            print("冒泡排序 ", bubbleSort(b));
            print("插入排序 ", insertSort(b));
            print("归并排序 ", mergeSort(b));
            print("希尔排序 ", shellSort(b));
            print("堆排序 ", heapSort(b));
            print("快速排序 ", quickSort(b));
        }
    
        /**
         * 冒泡排序算法:每次将最小的一个数”浮“上去 最好情况O(n),即数组本身有序 最坏情况O(n^2)
         */
        public static int[] bubbleSort(int[] a) {
            a = Arrays.copyOf(a, a.length);
    
            int count = 0;
            boolean terminated = false;
    
            for (int i = 0; i < a.length - 1 && !terminated; i++) {
                terminated = true;
                for (int j = a.length - 2; j >= i; j--) {
                    count++;
                    if (a[j] > a[j + 1]) {
                        swap(a, j + 1, j);
                        terminated = false;
                    }
                }
            }
            System.out.println("冒泡排序比较次数: " + count);
            return a;
        }
    
        /**
         * 选择排序:每次选出待排序中最小的一个
         */
        public static int[] selectSort(int[] a) {
            a = Arrays.copyOf(a, a.length);
    
            int count = 0;
            for (int i = 0; i < a.length - 1; i++) {
                int min = a[i];
                int minIndex = i;
                for (int j = i + 1; j < a.length; j++) {
                    count++;
                    if (a[j] < min) {
                        minIndex = j;
                        min = a[j];
                    }
                }
                swap(a, i, minIndex);
            }
            System.out.println("选择排序比较次数: " + count);
            return a;
        }
    
        public static int[] insertSort(int[] a) {
            a = Arrays.copyOf(a, a.length);
    
            int count = 0;
            for (int i = 1; i < a.length; i++) {// i之前有序,i指向待排序的元素
                if (a[i] < a[i - 1]) {
                    int temp = a[i];
                    int j = i - 1;// j指向当前元素的前一个
                    for (; j >= 0 && a[j] > temp; j--) {
                        count++;
                        a[j + 1] = a[j];
                    }
                    a[j + 1] = temp;
                }
            }
    
            System.out.println("插入排序比较次数: " + count);
            return a;
        }
    
        private static void swap(int[] a, int i, int j) {
            if (i == j)
                return;
            int temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    
        /**
         * 希尔排序
         * 
         * @param a
         * @return
         */
        public static int[] shellSort(int[] a) {
            a = Arrays.copyOf(a, a.length);
            int count = 0;
    
            int increment = a.length;
            do {
                increment = increment / 3 + 1;
                for (int i = increment; i < a.length; i = i + increment) {
                    if (a[i] < a[i - increment]) {
                        int temp = a[i];
                        int j = i - increment;
                        for (; j >= 0 && a[j] > temp; j -= increment) {
                            count++;
                            a[j + increment] = a[j];
                        }
                        a[j + increment] = temp;
                    }
                }
            } while (increment > 1);
    
            System.out.println("希尔排序比较次数: " + count);
            return a;
    
        }
    
        /**
         * 堆排序
         * 
         * @param a
         * @return
         */
        public static int[] heapSort(int[] a) {
            a = Arrays.copyOf(a, a.length);
            int length = a.length;
            for (int i = length / 2 - 1; i >= 0; i--)// 2*i+1<=length-1,最后一个有左孩子的节点
                heapAdjust(a, i, length);
    
            for (int i = length - 1; i >= 0; i--) {
                swap(a, 0, i);
                heapAdjust(a, 0, i);//
            }
    
            return a;
        }
    
        // 每次将以i为root的子树满足最大堆特性;i指向待调整的节点
        private static void heapAdjust(int[] a, int i, int length) {
            int temp = a[i];
    
            for (int j = 2 * i + 1; j < length; j = 2 * i + 1) {// 刚开始时指向左孩子
                if (j + 1 < length && a[j + 1] > a[j])// 如果有做右孩子,且右孩子比左孩子大
                    j++;// j指向左右孩子中值较大的一个
    
                if (temp >= a[j])
                    break;
                a[i] = a[j];
    
                i = j;
            }
            a[i] = temp;
        }
    
        public static int[] mergeSort(int[] a) {
            a = Arrays.copyOf(a, a.length);
            int[] aux = new int[a.length];
            mergeSort(a, aux, 0, a.length - 1);
            return a;
        }
    
        private static void mergeSort(int[] a, int[] aux, int lo, int high) {
            if (lo >= high)
                return;
    
            int mid = (lo + high) / 2;
            mergeSort(a, aux, lo, mid);
            mergeSort(a, aux, mid + 1, high);
            merge(a, aux, lo, mid, high);
        }
    
        private static void merge(int[] a, int aux[], int lo, int mid, int high) {
            for (int i = lo; i <= high; i++) {
                aux[i] = a[i];
            }
    
            int lo_h = mid + 1;
            for (int i = lo; i <= high; i++) {
                if (lo > mid)
                    a[i] = aux[lo_h++];
                else if (lo_h > high)
                    a[i] = aux[lo++];
                else {
                    if (aux[lo] <= aux[lo_h])
                        a[i] = aux[lo++];
                    else
                        a[i] = aux[lo_h++];
                }
            }
        }
    
        /**
         * 快速排序
         * 
         * @param a
         * @return
         */
    
        public static int[] quickSort(int[] a) {
            a = Arrays.copyOf(a, a.length);
            quickSort(a, 0, a.length - 1);
            return a;
        }
    
        private static void quickSort(int[] a, int low, int high) {
            if (low >= high)
                return;
    
            int partition = partition(a, low, high);
            quickSort(a, low, partition - 1);
            quickSort(a, partition + 1, high);
        }
    
        private static int partition(int[] a, int low, int high) {
            int tempt = a[low];
    
            while (low < high) {
                while (low < high && a[high] >= tempt)
                    high--;
                // swap(a,low,high);
                a[low] = a[high];
    
                while (low < high && a[low] <= tempt)
                    low++;
                // swap(a,low,high);
                a[high] = a[low];
            }
            a[low] = tempt;
            return low;
        }
    
        private static void print(String str, int[] a) {
            System.out.println(str);
            for (int i = 0; i < a.length; i++)
                System.out.print(a[i] + " ");
            System.out.println("\n");
        }
    
        /**
         * 下面是链表的快速排序
         * 
         * @param str
         * @param a
         */
        public static ListNode quickSort(ListNode begin, ListNode end) {
            // 判断为空,判断是不是只有一个节点
            if (begin == null || end == null || begin == end)
                return begin;
            // 从第一个节点和第一个节点的后面一个几点
            // begin指向的是当前遍历到的最后一个<= nMidValue的节点
            ListNode first = begin;
            ListNode second = begin.next;
    
            int nMidValue = begin.val;
            // 结束条件,second到最后了
            while (second != end.next && second != null) {// 结束条件
                // 一直往后寻找<=nMidValue的节点,然后与fir的后继节点交换
                if (second.val < nMidValue) {
                    first = first.next;
                    // 判断一下,避免后面的数比第一个数小,不用换的局面
                    if (first != second) {
                        int temp = first.val;
                        first.val = second.val;
                        second.val = temp;
                    }
                }
                second = second.next;
            }
            // 判断,有些情况是不用换的,提升性能
            if (begin != first) {
                int temp = begin.val;
                begin.val = first.val;
                first.val = temp;
            }
            // 前部分递归
            quickSort(begin, first);
            // 后部分递归
            quickSort(first.next, end);
            return begin;
        }
    
        /**
         * 链表的归并排序
         */
        public ListNode sortList1(ListNode head) {
            if (head == null || head.next == null)
                return head;
            quickSort(null, null);
            return mergeSort(head);
        }
    
        private ListNode mergeSort(ListNode head) {
            if (head == null || head.next == null)
                return head;
    
            ListNode mid = getMid(head);
            ListNode second = mid.next;
            mid.next = null;
    
            ListNode left = mergeSort(head);
            ListNode right = mergeSort(second);
            return merge(right, left);
        }
    
        private ListNode merge(ListNode l1, ListNode l2) {
            ListNode dummy = new ListNode(0);
            ListNode cur = dummy;
            while (l1 != null && l2 != null) {
                if (l1.val <= l2.val) {
                    cur.next = l1;
                    l1 = l1.next;
                } else {
                    cur.next = l2;
                    l2 = l2.next;
                }
                cur = cur.next;
            }
            if (l1 != null)
                cur.next = l1;
            else
                cur.next = l2;
    
            return dummy.next;
    
        }
    
        private ListNode getMid(ListNode head) {
            if (head == null || head.next == null)
                return head;
            ListNode slow = head;
            ListNode faster = head.next;
            while (faster != null && faster.next != null) {
                slow = slow.next;
                faster = faster.next.next;
            }
            return slow;
        }
    }
    
    package com.sort_algorithm;
    
    public class ListNode {
    
        int val;
        ListNode next;
    
        public ListNode(int x) {
            val = x;
            next = null;
        }
        
    }
    

    相关文章

      网友评论

        本文标题:排序算法总结

        本文链接:https://www.haomeiwen.com/subject/usmrqctx.html