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));
        }
    }
  • 相关阅读:
    173. Binary Search Tree Iterator
    199. Binary Tree Right Side View
    230. Kth Smallest Element in a BST
    236. Lowest Common Ancestor of a Binary Tree
    337. House Robber III
    449. Serialize and Deserialize BST
    508. Most Frequent Subtree Sum
    513. Find Bottom Left Tree Value
    129. Sum Root to Leaf Numbers
    652. Find Duplicate Subtrees
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/15471223.html
Copyright © 2011-2022 走看看