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

    参考:

    https://www.cnblogs.com/onepixel/articles/7674659.html

    这个博客写的很好,而且还有每个排序算法的动画,非常值得一看。

    一、概览

    二、java实现

    public class SortUtils {
        /**
         * 1.插入排序
         * 从第二个元素开始和前面的有序序列进行比较,
         * 如果小于有序元素的最后一个,则向前再向前,一直找到合适的位置插入
         * 然后插入位置的元素和它之后的元素统一向后移动一位
         * 插入排序理解起来不难,难点在于边界的确定
         */
    
        public static void insertSort(Integer[] arr) {
            //第一个数据肯定有序,所以从第二个数据开始跟有序序列做比较
            for (int i = 1; i < arr.length; i++) {
                Integer data = arr[i];
                int j = i - 1;
                //从后向前寻找arr[i]的插入位置
                while (data < arr[j] && j > 0) {
                    j--;
                }
                //把j+1~i的所有数据统一向后移动一位,移动是逆序从后向前进行的
                for (int k = i; k > j; k--) {
                    arr[k] = arr[k - 1];
                }
                arr[j + 1] = data;
            }
        }
    
        /**
         * 2.冒泡排序,最好理解
         * 一趟排序就可以把最大元素交换到队尾,然后下一次对前n-1个元素继续冒泡排序
         * @param arr
         */
        public static void bubbleSort(Integer[] arr) {
            int length = arr.length;
            for (int i = 0; i < length; i++) {
                for (int j = 0; j < length - i - 1; j++) {
                    if (arr[j] > arr[j + 1]) {
                        exchange(arr, j, j + 1);
                    }
                }
            }
        }
    
        /**
         * 3.选择排序
         * 始终选择未排序序列中的最小元素,插入到已排序序列的最后
         *
         * @param arr
         */
        public static void selectSort(Integer[] arr) {
            int length = arr.length;
            for (int j = 0; j < length; j++) {
                Integer minD = Integer.MAX_VALUE;
                int index = 0;
                for (int i = j; i < length; i++) {
                    if (arr[i] < minD) {
                        minD = arr[i];
                        index = i;
                    }
                }
                //循环结束,找到了最小元素和最小元素的下标
                Integer old = arr[j];
                arr[j] = minD;
                arr[index] = old;
    
            }
        }
    
        /**
         * 4.希尔排序
         * 可以认为是插入排序的改进版
         * 通过将原数组分解成不同步长的子序列,对子序列进行插入排序
         * 不断缩短步长,直到步长为一
         *
         * @param arr
         */
        public static void shellSort(Integer[] arr) {
            //初始步长为数组长度的一半
            int step = arr.length / 2;
            //while循环内部还是一个插入排序,与基本插入排序相比多了下标越界的校验
            while (step > 0) {
                for (int i = step; i < arr.length; i++) {
                    Integer data = arr[i];
                    int j = i - step;
                    //从后向前寻找arr[i]的插入位置
                    while (j >= 0 && data < arr[j]) {
                        j = j - step;
                    }
                    //把j+1~i的所有数据统一向后移动一位,移动是逆序从后向前进行的
                    for (int k = i; k > j && k - step >= 0; k = k - step) {
                        arr[k] = arr[k - step];
                    }
                    arr[j + step] = data;
                }
                step = step / 2;
            }
        }
    
        /**
         * 5.归并排序
         * 对数组进行递归的拆分,直到每个数组只有一个元素,此时一定是有序的
         * 然后将这两个最小的有序数组进行合并再合并
         *
         * @param arr
         */
        public static void mergeSort(Integer[] arr, int start, int end) {
            if (start < end) {
                int q = (start + end) / 2;
                mergeSort(arr, start, q);
                mergeSort(arr, q + 1, end);
                merge(arr, start, q, end);
            }
        }
    
        private static void merge(Integer[] arr, int start, int q, int end) {
            //新建两个辅助数组,n1,n2是实际存放元素的长度
            int n1 = q - start + 1;
            int n2 = end - q;
            //每个数组多一个哨兵元素空间
            Integer[] left = new Integer[n1 + 1];
            Integer[] right = new Integer[n2 + 1];
            //将原数组的元素复制到辅助数组
            for (int i = 0; i < n1; i++) {
                left[i] = arr[start + i];
            }
            for (int j = 0; j < n2; j++) {
                right[j] = arr[q + 1 + j];
            }
            //哨兵元素
            left[n1] = Integer.MAX_VALUE;
            right[n2] = Integer.MAX_VALUE;
            int m = 0;
            int n = 0;
            for (int k = start; k <= end; k++) {
                if (left[m] < right[n]) {
                    arr[k] = left[m];
                    m++;
                } else {
                    arr[k] = right[n];
                    n++;
                }
            }
        }
    
        /**
         * 6.快速排序
         * 通过一趟排序将待排记录分隔成独立的两部分,
         * 其中一部分记录的关键字均比另一部分的关键字小,
         * 则可分别对这两部分记录继续进行排序,以达到整个序列有序。
         *
         * @param arr
         */
    
        public static void quickSort(Integer[] arr, int start, int end) {
            if (start < end) {
                int q = partition(arr, start, end);
                quickSort(arr, start, q - 1);
                quickSort(arr, q + 1, end);
            }
        }
    
        /**
         * 分区是快速排序的关键
         * 将一个数组根据基准分成小于基准值和大于基准值的两部分
         * 特点:需要两个游标
         *
         * @param arr
         * @param start
         * @param end
         * @return
         */
        private static int partition(Integer[] arr, int start, int end) {
            //默认以最后一个元素为基准
            Integer base = arr[end];
            //i代表较小值的最大索引,j代表未知元素最小索引
            int i = start - 1;
            for (int j = start; j < end; j++) {
                if (arr[j] <= base) {
                    i++;
                    exchange(arr, i, j);
                }
            }
            exchange(arr, i + 1, end);
            return i + 1;
    
        }
    
        public static void exchange(Integer[] arr, int i, int j) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    
        /**
         * 7.堆排序:需要借助堆数据结构
         *
         * @param arr
         */
        public static void heapSort(Integer[] arr) {
            MHeap<Integer> heap = new MHeap<>();
            for (Integer integer : arr) {
                heap.insert(integer);
            }
            for (int i = 0; i < arr.length; i++) {
                arr[i] = heap.pop();
            }
        }
    
        /**
         * 8.计数排序
         * 统计数组中小于一个元素所有元素的个数,这个个数正好就是它在新数组中的下标
         *
         * @param arr
         */
        public static Integer[] countSort(Integer[] arr) {
            Integer[] result = new Integer[arr.length];
            Integer[] c = new Integer[100];
            Arrays.fill(c, 0);
            for (int i = 0; i < arr.length; i++) {
                c[arr[i]] = c[arr[i]] + 1;
            }
    
            for (int i = 1; i < c.length; i++) {
                c[i] = c[i] + c[i - 1];
            }
            for (int i = 0; i < arr.length; i++) {
                Integer index = c[arr[i]];
                result[index - 1] = arr[i];
            }
            return result;
        }
    
        /**
         * 9.基数排序
         * 按照从低位到高位的顺序依次对数组进行排序
         * 基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。
         *
         * @param arr
         */
        public static void radixSort(Integer[] arr, int d) {
            //从个位到十位再到百位
            for (int i = 1; i <= d; i++) {
                doRadixSort(arr, i);
            }
        }
    
        /**
         * 借用临时数组存放每次基数排序的结果
         *
         * @param arr
         * @param degree
         */
        private static void doRadixSort(Integer[] arr, int degree) {
            //临时数组
            Integer[][] tempArray = new Integer[10][10];
            Integer[] indexArray = new Integer[10];
            Arrays.fill(indexArray, 0);
            for (Integer integer : arr) {
                int intByDegree = getIntByDegree(integer, degree);
                Integer idx = indexArray[intByDegree];
                tempArray[intByDegree][idx] = integer;
                indexArray[intByDegree] = indexArray[intByDegree] + 1;
            }
    
            int nd = 0;
            for (int i = 0; i < tempArray.length; i++) {
                Integer len = indexArray[i];
                for (int j = 0; j < len; j++) {
                    arr[nd] = tempArray[i][j];
                    nd++;
                }
            }
    
        }
    
        /**
         * 获取最大数的位
         *
         * @param maxVal
         * @return
         */
        private static int getDegree(Integer maxVal) {
            int i = 0;
            while (maxVal != 0) {
                i++;
                maxVal = maxVal / 10;
            }
            return i;
        }
    
        /**
         * 1-个位,2=10位
         * 获取当前位的值
         *
         * @param data
         * @param degree
         * @return
         */
        private static int getIntByDegree(Integer data, int degree) {
            return (int) ((data / Math.pow(10, degree - 1)) % 10);
        }
    
        /**
         * 10.桶排序
         * 桶是有序的,对桶内数据再排序,然后合并
         * 关键是如何进行分桶,使得每个桶的元素相差不大
         *
         * @param arr
         */
        public static void bucketSort(Integer[] arr) {
            int bucketNum = 0;
            //获取最大数的位数,即为桶数
            for (Integer integer : arr) {
                if (bucketNum < getDegree(integer)) {
                    bucketNum = getDegree(integer);
                }
            }
            Integer[] indexArray = new Integer[bucketNum];
            Arrays.fill(indexArray, 0);
            //构造m*n的二维数组,m是桶数
            Integer[][] buckets = new Integer[bucketNum][arr.length];
            //遍历原数组,根据特征把数放入不同的桶
            for (Integer integer : arr) {
                //不同位的数放入不同桶
                int degree = getDegree(integer);
                int idx = degree - 1;
                //indexArray存放二级索引
                Integer index = indexArray[idx];
                buckets[idx][index] = integer;
                indexArray[idx] = indexArray[idx] + 1;
            }
            //对每个桶分别排序
            for (int i = 0; i < bucketNum; i++) {
                Integer[] bucket1 = buckets[i];
                Integer length = indexArray[i];
                quickSort(bucket1, 0, length - 1);
            }
            int newIndex = 0;
            //将桶的数据重新放回数组
            for (int i = 0; i < bucketNum; i++) {
                Integer len = indexArray[i];
                for (int j = 0; j < len; j++) {
                    arr[newIndex] = buckets[i][j];
                    newIndex++;
                }
            }
        }
    
        public static void main(String[] args) {
            Integer[] array = {76, 1, 43, 22, 5, 34, 547, 17, 18, 9};
    //        insertSort(array);
    //        bubbleSort(array);
    //        selectSort(array);
    //        heapSort(array);
    //        quickSort(array,0,array.length-1);
    //        mergeSort(array, 0, array.length - 1);
    //        shellSort(array);
    //        Integer[] array1 = countSort(array);
    //        bucketSort(array);
            radixSort(array, 3);
            System.out.println(Arrays.toString(array));
        }
    }
  • 相关阅读:
    解决前端从url路径上拿到的中文乱码
    仪表盘双层结构图
    element ui 按钮显示
    vue在手机上运行,打包之后显示
    echarts使用遇到的一些问题总结,比如颜色改变,文字位置调整
    微信小程序地图移动到指定的位置
    微信小程序多边形地图显示
    button取消边框
    代码审计小记 (一)
    [root-me](web-client)write up 一个大坑怎么填啊
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/15471223.html
Copyright © 2011-2022 走看看