zoukankan      html  css  js  c++  java
  • 八大排序算法 Java实现

    一、插入排序

    稳定排序

    模板

    class Sort {
        public static <AnyTpye extends Comparable<? super AnyTpye>> void insertionSort(AnyTpye[] a){ //Comparable可以比较的数或对象
            int j;
            for (int p =1;p < a.length;p++){ //默认a[0]是有序的,所以从1开始
                AnyTpye tmp = a[p]; //暂存要插入的p号元素
                //把p号元素从本身开始往前比较,直到比前一个数大,终止循环,可以插入
                for (j = p;j>0 && tmp.compareTo(a[j-1])<0;j--) 
                    a[j] = a[j-1];
                a[j] = tmp;
            }
        }
    }
    

    应用

    import java.util.Arrays;
    
    class Sort{
        public static void insertionSort(int[] a){
            int j;
            for (int p = 1; p < a.length; p++) {
                int tmp = a[p];
                for (j = p;j>0 && tmp<a[j-1];j--){
                    a[j] = a[j-1];
                }
                a[j] = tmp;
            }
        }
    
        public static void main(String[] args) {
            int[] nums = {8,34,64,51,32,21};
            insertionSort(nums);
            System.out.println(Arrays.toString(nums));
        }
    }
    

    分析

    时间复杂度O(N^2)

    N个互异数的数组的平均逆序数是N(N-1)/4

    通过交换相邻元素进行排序的任何算法平均都需要Ω(N^2)时间

    二、希尔排序

    非稳定排序

    模板

    class Sort{
        public static <AnyTpye extends Comparable<? super AnyTpye>> void shellSort(AnyTpye[] a){
            int j;
            //在不同的gap上用插入排序
            for (int gap = a.length/2;gap > 0;gap /= 2)
                for (int i = gap;i < a.length;i++){
                    AnyTpye tmp = a[i];
                    for (j = i;j>=gap && tmp.compareTo(a[j-gap])<0;j -= gap)
                        a[j] = a[j-gap];
                    a[j] = tmp;
                }
        }
    }
    

    应用

    import java.util.Arrays;
    
    class Sort{
        public static void shellSort(int[] a){
            int j;
            for (int gap = a.length/2;gap > 0;gap /= 2){
                for (int i = gap;i < a.length;i++){
                    int tmp = a[i];
                    for (j = i;j >= gap && tmp < a[j-gap];j -= gap){
                        a[j] = a[j-gap];
                    }
                    a[j] = tmp;
                }
            }
        }
    
        public static void main(String[] args) {
            int[] nums = {8,34,64,51,32,21};
            shellSort(nums);
            System.out.println(Arrays.toString(nums));
        }
    }
    

    分析

    使用希尔增量({1,4,8...,2^k})的希尔排序,最坏时间复杂度O(N^2)

    使用 Hibbard 增量({1,3,7,...2^k-1})的希尔排序,最坏时间复杂度O(N^1.5),它跟希尔增量的区别在于相邻增量没有公因数

    最优的增量序列:{1,5,19,41,109,...,9*(4^k-2^k)+1,4^i-3*2^i+1,...}

    三、选择排序

    import java.util.Arrays;
    
    class Sort{
        private static void chooseSort(int[] nums){
            for (int i = 0; i < nums.length-1; i++) {
                int k = i;
                for (int j = i+1; j < nums.length; j++) {
                    if (nums[k] > nums[j]) k = j; //选出最小数的角标
                }
                if (k!=i){ //最小的不是自己则需要拿到前面
                    int tmp = nums[i];
                    nums[i] = nums[k];
                    nums[k] = tmp;
                }
            }
        }
    
        public static void main(String[] args) {
            int[] nums = {8,34,64,51,32,21};
            chooseSort(nums);
            System.out.println(Arrays.toString(nums));
        }
    }
    

    四、堆排序

    完全二叉树,第 i 个结点为例,左孩子为 2i+1,右孩子为 2i+2

    public class HeapSort {
        public static void main(String[] args) {
    //        int[] arr = {5, 1, 7, 3, 1, 6, 9, 4};
            int[] arr = {16, 7, 3, 20, 17, 8};
    
            heapSort(arr);
    
            for (int i : arr) {
                System.out.print(i + " ");
            }
        }
    
    
        //创建堆 
        private static void heapSort(int[] arr) {
            //创建堆
            for (int i = (arr.length - 1) / 2; i >= 0; i--) {
                //从第一个非叶子结点从下至上,从右至左调整结构
                adjustHeap(arr, i, arr.length);
            }
    
            //调整堆结构+交换堆顶元素与末尾元素
            for (int i = arr.length - 1; i > 0; i--) {
                //将堆顶元素与末尾元素进行交换
                int temp = arr[i];
                arr[i] = arr[0];
                arr[0] = temp;
    
                //重新对堆进行调整,调前i个就行了
                adjustHeap(arr, 0, i);
            }
        }
    
        //调整堆
        private static void adjustHeap(int[] arr, int parent, int length) {
            //将temp作为父节点
            int temp = arr[parent];
            //左孩子
            int lChild = 2 * parent + 1;
    
            while (lChild < length) {
                //右孩子
                int rChild = lChild + 1;
                // 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
                if (rChild < length && arr[lChild] < arr[rChild]) {
                    lChild++;
                }
    
                // 如果父结点的值已经大于孩子结点的值,则直接结束
                if (temp >= arr[lChild]) {
                    break;
                }
    
                // 把孩子结点的值赋给父结点
                arr[parent] = arr[lChild];
    
                //选取孩子结点的左孩子结点,继续向下筛选
                parent = lChild;
                lChild = 2 * lChild + 1;
            }
            arr[parent] = temp;
        }
    }
    

    五、冒泡排序

    import java.util.Arrays;
    
    class Sort{
        private static void chooseSort(int[] nums){
            for (int i = 0; i < nums.length; i++) {
                for (int j = 0; j < nums.length - i - 1; j++) {
                    if (nums[j] > nums[j+1]){
                        int tmp = nums[j];
                        nums[j] = nums[j+1];
                        nums[j+1] = tmp;
                    }
                }
            }
        }
    
        public static void main(String[] args) {
            int[] nums = {8,34,64,51,32,21};
            chooseSort(nums);
            System.out.println(Arrays.toString(nums));
        }
    }
    

    六、快速排序

    import java.util.Arrays;
    
    class Sort{
        private static void quickSort(int[] nums){
            quickSort(nums, 0, nums.length - 1);
        }
    
        private static void quickSort(int[] nums, int l, int r) {
            if (l >= r) return;
            int index = helper(nums,l,r);
            quickSort(nums,l,index-1);
            quickSort(nums,index+1,r);
        }
    
        private static int helper(int[] nums,int l,int r){
            int i = l;
            int j = r;
            int x = nums[i];
            while (i < j){
                while (i < j && nums[j] >= x){
                    j--;
                }
                if (i < j){
                    nums[i] = nums[j];
                }
                while (i < j && nums[i] <= x){
                    i++;
                }
                if (i < j){
                    nums[j] = nums[i];
                }
            }
            nums[i] = x;
            return i;
        }
    
        public static void main(String[] args) {
            int[] nums = {8,34,64,51,32,21};
            quickSort(nums);
            System.out.println(Arrays.toString(nums));
        }
    }
    

    七、归并排序

    import java.util.Arrays;
    
    class Sort{
        private static void mergeSort(int[] nums){
            mergeSort(nums,0,nums.length-1);
        }
    
        private static void mergeSort(int[] nums, int left, int right) {
            if (left < right){
                int center = (left + right) / 2;
                mergeSort(nums,left,center); //递归调用
                mergeSort(nums,center+1,right);
                merge(nums,left,center,right); //连接两个有序数组
            }
        }
    
        private static void merge(int[] nums, int left, int center, int right) {
            int[] tmpNums = new int[nums.length];
            int mid = center + 1; //后边数组的开始
            int third = left;
            int tmp = left; //留到最后拷贝数组用
            while (left <= center && mid <= right){
                if (nums[left] <= nums[mid]){
                    tmpNums[third++] = nums[left++];
                }else {
                    tmpNums[third++] = nums[mid++];
                }
            }
            while (mid <= right){
                tmpNums[third++] = nums[mid++];
            }
            while (left <= center){
                tmpNums[third++] = nums[left++];
            }
            while (tmp <= right){
                nums[tmp] = tmpNums[tmp++];
            }
        }
        
        public static void main(String[] args) {
            int[] nums = {8,34,64,51,32,21};
            mergeSort(nums);
            System.out.println(Arrays.toString(nums));
        }
    }
    

    八、基排序

    public class RadixSort {
        public static void main(String[] args) {
            int[] arr = {63, 157, 189, 51, 101, 47, 141, 121, 157, 156,
                    194, 117, 98, 139, 67, 133, 181, 12, 28, 0, 109};
    
            radixSort(arr);
    
            System.out.println(Arrays.toString(arr));
        }
    
        private static void radixSort(int[] arr) {
            //待排序列最大值
            int max = arr[0];
            int exp;//指数
    
            //计算最大值,确定最高位数
            for (int anArr : arr) {
                if (anArr > max) {
                    max = anArr;
                }
            }
    
            //从个位开始,对数组进行排序
            for (exp = 1; max / exp > 0; exp *= 10) {
                //存储待排元素的临时数组
                int[] temp = new int[arr.length];
                //分桶个数
                int[] buckets = new int[10];
    
                //将数据出现的次数存储在buckets中
                for (int value : arr) {
                    //(value / exp) % 10 :value的最底位(个位)
                    buckets[(value / exp) % 10]++;
                }
    
                //更改buckets[i],
                for (int i = 1; i < 10; i++) {
                    buckets[i] += buckets[i - 1];
                }
    
                //将数据存储到临时数组temp中
                for (int i = arr.length - 1; i >= 0; i--) {
                    temp[buckets[(arr[i] / exp) % 10] - 1] = arr[i];
                    buckets[(arr[i] / exp) % 10]--;
                }
    
                //将有序元素temp赋给arr
                System.arraycopy(temp, 0, arr, 0, arr.length);
            }
    
        }
    }
    
  • 相关阅读:
    Encryption (hard) CodeForces
    cf 1163D Mysterious Code (字符串, dp)
    AC日记——大整数的因子 openjudge 1.6 13
    AC日记——计算2的N次方 openjudge 1.6 12
    Ac日记——大整数减法 openjudge 1.6 11
    AC日记——大整数加法 openjudge 1.6 10
    AC日记——组合数问题 落谷 P2822 noip2016day2T1
    AC日记——向量点积计算 openjudge 1.6 09
    AC日记——石头剪刀布 openjudge 1.6 08
    AC日记——有趣的跳跃 openjudge 1.6 07
  • 原文地址:https://www.cnblogs.com/peng8098/p/java_30.html
Copyright © 2011-2022 走看看