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);
            }
    
        }
    }
    
  • 相关阅读:
    Android Logcat使用技巧
    SqlClient使用存储过程并获取输出参数的指
    内存调试的东西D/dalvikvm( 809 ): GC_CONCURRENT freed
    android 读写sd卡的权限设置
    Android中EditText的使用方法持續更新
    RSL编译方式的FLEX站点出现#2046错误
    从网络读取数据并动态的显示在ListView中
    LEFT JOIN INNER JOIN 效率比较
    使用Installshield2009 在IIS6部署Asp.net mvc 应用程序
    Installshield2009中使用osql.exe执行数据库脚本
  • 原文地址:https://www.cnblogs.com/peng8098/p/java_30.html
Copyright © 2011-2022 走看看