zoukankan      html  css  js  c++  java
  • 基本排序算法(冒泡排序 选择排序 插入排序 快速排序 归并排序 基数排序 希尔排序)

    项目地址:https://github.com/windwant/windwant-service/tree/master/algorithm

    冒泡排序:两两比较,大数冒泡

    升序:

    public static void bubbleSort(int[] arr){
            int lgn = arr.length;
            for (int i = 0; i < lgn - 1; i++) {
                for (int j = 0; j < lgn - 1 - i; j++) {
                    if(arr[j] > arr[j + 1]){
                        int temp = arr[j + 1];
                        arr[j + 1] = arr[j];
                        arr[j] = temp;
                    }
                }
            }
        }

    降序:

    ...

    选择排序:选择剩余元素中最小(最大)的元素放置到初始选择集合中(空)

    public static void SelectionSortAsc(int[] arr){
    int min = 0;
    for (int i = 0; i < arr.length - 1; i++) {
    min = i;
    for (int j = i + 1; j < arr.length ; j++) {
    if(arr[j] < arr[min]){
    min = j;
    }
    }
    if(min != i){
    int tmp = arr[i];
    arr[i] = arr[min];
    arr[min] = tmp;
    }
    }
    }

    public static void SelectionSortDesc(int[] arr){
    int max = 0;
    for (int i = 0; i < arr.length - 1; i++) {
    max = i;
    for (int j = i + 1; j < arr.length ; j++) {
    if(arr[j] > arr[max]){
    max = j;
    }
    }
    if(max != i){
    int tmp = arr[i];
    arr[i] = arr[max];
    arr[max] = tmp;
    }
    }
    }

    插入排序:设定一个初始已排序的集合(一般选择一个元素),从剩余的集合中将各个元素以此插入到初始集合中的正确位置

    public static void insertionSort(int [] array){
            for(int i = 1; i < array.length; i++){
                int temp = array[i];//被标记的值或者说是当前需要插入的值
                int j = i;
                //如果轮循值大于被标记值则往后移
                while( j > 0 && temp < array[j - 1]){
                    array[j] = array[j - 1];
                    j-- ;
                }
                //将被标记值插入最终移出的空位置
                array[j] = temp;
            }
        }

    快速排序:选取锚点,划分小于,大于两个集合,递归处理子集合

    public static void quikeSort(int[] arr, int low, int high) {
            int start = low;
            int end = high;
            int anchor = arr[low];
    
            while (end > start) {
                //比较 anchor---end
                while (end > start && arr[end] >= anchor) {  //从末尾向前寻找小于等于anchor的值
                    end--;
                }
    
                //交换位置
                if (arr[end] <= anchor) {
                    int temp = arr[end];
                    arr[end] = arr[start];
                    arr[start] = temp;
                }
    
                //比较start---anchor
                while (end > start && arr[start] <= anchor) {//从起始位置向后寻找大于等于anchor的值
                    start++;
                }
    
                //交换位置
                if (arr[start] >= anchor) {
                    int temp = arr[start];
                    arr[start] = arr[end];
                    arr[end] = temp;
                }
            }
            //anchor位置确定。左边的元素值都小于anchor值,右边的值都大于anchor值,递归排序左右两侧排序
            //左边元素。low---anchor值索引-1
            if (start > low) {
                quikeSort(arr, low, start - 1);
            }
    
            //右边元素。从anchor值索引+1---high
            if (end < high) {
                quikeSort(arr, end + 1, high);
            }
        }

    归并排序:中分两个结合,分别归并排序,然后合并两个有序结合;递归进行

    public static void mergeSort(int[] data) {
            sort(data, 0, data.length - 1);
        }
    
        public static void sort(int[] data, int left, int right) {
            if (left >= right)
                return;
            // 找出中间索引
            int center = (left + right) / 2;
            // 对左边数组进行递归
            sort(data, left, center);
            // 对右边数组进行递归
            sort(data, center + 1, right);
            // 合并
            merge(data, left, center, right);
        }
    
        /**
         * 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序
         *
         * @param data
         *            数组对象
         * @param left
         *            左数组的第一个元素的索引
         * @param center
         *            左数组的最后一个元素的索引,center+1是右数组第一个元素的索引
         * @param right
         *            右数组最后一个元素的索引
         */
        public static void merge(int[] data, int left, int center, int right) {
            // 临时数组
            int[] tmpArr = new int[data.length];
            // 右数组第一个元素索引
            int mid = center + 1;
            // third 记录临时数组的索引
            int third = left;
            // 缓存左数组第一个元素的索引
            int tmp = left;
            while (left <= center && mid <= right) {
                // 从两个数组中取出最小的放入临时数组
                if (data[left] <= data[mid]) {
                    tmpArr[third++] = data[left++];
                } else {
                    tmpArr[third++] = data[mid++];
                }
            }
            // 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)
            while (mid <= right) {
                tmpArr[third++] = data[mid++];
            }
            while (left <= center) {
                tmpArr[third++] = data[left++];
            }
            // 将临时数组中的内容拷贝回原数组中
            // (原left-right范围的内容被复制回原数组)
            while (tmp <= right) {
                data[tmp] = tmpArr[tmp++];
            }
        }

    基数排序:逐位排序

    //LSD
        public static void radixLSDSort(int[] arr){
            //最高位数
            int maxBit = getMaxBit(arr);
            //十个bulk 分别存放 每个位数 数字 相应的元素 如个位为3 则放入bulk[3]
            Queue<Integer>[] bulk = new Queue[10];
            for (int i = 0; i < bulk.length; i++) {
                bulk[i] = new ArrayDeque();
            }
            //分别处理不同位数 存放 处理
            for (int i = 0; i < maxBit; i++) {
                for (int j = 0; j < arr.length; j++) {
                    int ivalue = (int) (arr[j] % Math.pow(10, i + 1) / Math.pow(10, i)); //去相应位数上的数字作为 存入bulk index
                    bulk[ivalue].offer(arr[j]);
                }
    
                //取出bulk中的元素 重新放入数组 并清除bulk中的元素。
                int arrIndex = 0;
                for (int j = 0; j < bulk.length; j++) {
                    while (bulk[j].size()>0){
                        arr[arrIndex++] = bulk[j].poll();
                    }
                }
            }
        }
    
        public static int getMaxBit(int[] arr){
            int max = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if(arr[i] > max){
                    max = arr[i];
                }
            }
    
            int b = 0;
            while (max > 0){
                max /= 10;
                b++;
            }
            return b;
        }
    
        public static void radixMSDSort(int[] arr){
            msdSort(arr, 0, arr.length, getMaxBit(arr));
        }
    
        //MSD
        public static void msdSort(int[] arr, int left, int right, int maxBit){
            //十个bulk 分别存放 每个位数 数字 相应的元素 如个位为3 则放入bulk[3]
            Queue<Integer>[] bulk = new Queue[10];
            for (int i = 0; i < bulk.length; i++) {
                bulk[i] = new ArrayDeque();
            }
            //依据最高位分别放入不同的bulk
            for (int j = left; j < right; j++) {
                int ivalue = (int) (arr[j] % Math.pow(10, maxBit) / Math.pow(10, maxBit - 1)); //去相应位数上的数字作为 存入bulk index
                bulk[ivalue].offer(arr[j]);
            }
    
            //取出bulk中的元素 重新放入数组 并清除bulk中的元素。记录bulk中queue大小大于1的数组索引 递归使用
            List<Integer> count = new ArrayList<Integer>();
            int arrIndex = left;
            for (int j = 0; j < bulk.length; j++) {
                int start = arrIndex;
                while (bulk[j].size()>0){
                    arr[arrIndex++] = bulk[j].poll();
                }
                if(arrIndex - start > 1){
                    count.add(start);
                    count.add(arrIndex);
                }
            }
            //递归最小位判断
            int nextBit = maxBit - 1;
            if(nextBit > 0) {
                for (int i = 1; i < count.size(); i += 2) {
                    msdSort(arr, count.get(i - 1), count.get(i), nextBit);
                }
            }
        }

    shell排序:插入排序+步长改进

    public static void shellSort(int[] arr){
            int step = arr.length/2;
            while (step >= 1) { //步长为1时 包含所有数组序列
                for (int i = 0; i < step; i++) { //步长为n则数组将分为n组分别排序
                    for (int j = step + i; j < arr.length; j += step) { //对跨步长每组元素进行插入排序
                        int temp = arr[j];
                        int preIndex = j - step;
                        while (preIndex > -1 && temp < arr[preIndex]) {
                            arr[preIndex + step] = arr[preIndex];
                            preIndex -= step;
                        }
                        arr[preIndex + step] = temp;
                        System.out.println(" middle: " + Arrays.toString(arr));
                    }
                }
                step /= 2; //每次步长处理
            }
        }
     
    /**
    * 改进形式
    * @param arr
    */
    public static void shellSort1(int[] arr){
    int step = arr.length/2;
    while (step >= 1) { //步长为1时 包含所有数组序列
    for (int i = step; i < arr.length; i += step) { //对跨步长每组元素进行插入排序
    int temp = arr[i];
    int j = i;
    while (j > 0 && temp < arr[j - step]) {
    arr[j] = arr[j - step];
    j -= step;
    }
    arr[j] = temp;
    }
    System.out.println("step: " + step + " middle: " + Arrays.toString(arr));
    step /= 2; //每次步长处理
    }
    }
  • 相关阅读:
    关于web前端网站优化
    C/S与B/S架构的区别和优缺点
    什么是闭包?闭包的优缺点?
    JavaScript中基本数据类型和引用数据类型的区别
    jQuery对象与DOM对象之间的转换方法
    (转)第05节:Fabric.js的动画设置
    (转)第04节:Fabric.js用路径画不规则图形
    layui表单与原生js表单的一些小问题(三)
    layui表单与原生js表单的一些小问题(二)
    layui表单与原生js表单的一些小问题(一)
  • 原文地址:https://www.cnblogs.com/niejunlei/p/6138807.html
Copyright © 2011-2022 走看看