• 排序归纳 Java版


    根据 左神课程 整理补充的排序知识!
    😊😊😊如果有帮助,记得三连哦!

    Created: November 17, 2022 10:53 AM

    简单排序

    选择排序

    • 时间O(N^2) 、空间O(1)、不稳

       public void selectSort(int[] arr) {
            if (arr == null || arr.length < 2) return;
            for (int i = 0; i < arr.length; i++) { // i - N-1
                int minValue = i;
                for (int j = i + 1; j < arr.length; j++) { // i - N-1 找到最小值的下标
                    minValue = arr[minValue] > arr[j] ? j : minValue;
                }
                swap(arr, minValue, i); //最小值放最左边
            }
        }
    
        private void swap(int[] arr, int minValue, int i) {
            int temp = arr[minValue];
            arr[minValue] = arr[i];
            arr[i] = temp;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    冒泡排序

    • 时间O(N^2) 、空间O(1)、稳

    		private void swap(int[] arr, int i, int j) {
            arr[i] = arr[i] ^ arr[j];
            arr[j] = arr[i] ^ arr[j];
            arr[i] = arr[i] ^ arr[j];
        }
    
        public void bubbleSort(int[] arr) {
            if (arr == null || arr.length < 2) return;
            for (int i = arr.length - 1; i > 0; i--) { // 玩N轮
                for (int j = 0; j < i; j++) { //每轮将当前和下一个比大小,谁大谁往右
                    if (arr[j] > arr[j + 1]) {
                        swap(arr, j, j + 1);
                    }
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    插入排序

    • 时间O(N^2) 、空间O(1)、稳
    public void insertionSort(int[] arr) {
        if (arr == null || arr.length < 2) return;
    		// 0~0上有序,0~i想有序
        for (int i = 0; i < arr.length; i++) { // 0 - i做到有序
            for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
                swap(arr, j, j + 1);
            }
        }
    }
    private void swap(int[] arr, int i, int j) {
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    特殊排序

    归并排序

    • 时间O(NlogN)、空间O(N)、稳

    		public void mergeSort(int arr[]) {
    		        process(arr, 0, arr.length - 1);
    		    }
    		
        public void process(int[] arr, int L, int R) {
            if (L == R) return; //只有一个数字就不处理
            int mid = L + ((R - L) >> 1);//中点
            process(arr, L, mid); //左边排好序
            process(arr, mid + 1, R); //右边排好序
            merge(arr, L, mid, R);//利用外排序将左右两边排好序
        }
    
        private void merge(int[] arr, int L, int M, int R) {
            int[] help = new int[R- L + 1]; //外排序的辅助空间
            int i = 0; //外排序的索引
            int p1 = L; //左边排好序的索引
            int p2 = M + 1; //右边排好序的索引
            //左右比较,谁小放进去,总有一个会越界
            while (p1 <= M && p2 <= R) {
    						//相等的情况下先左后右
                help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
            }
            //肯定有越界的情况,但是help肯定不满,下面情况只会中一个
            while (p1 <= M) {
                help[i++] = arr[p1++];
            }
            while (p2 <= R) {
                help[i++] = arr[p2++];
            }
            //将外排序的东西返回原数组
            for (int j = 0; j < help.length; j++) {
                arr[L + j] = help[j];
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    快速排序(实际使用比堆排序快)

    • 时间O(NlogN) 、空间O(logN)、不稳

    		public void quicksort(int arr[], int l, int r) {
            if (l < r) {
                //随机抽取一个放到最后面作为比较值
                swap(arr, l + (int) (Math.random() * (r - l + 1)), r);
                //荷兰国旗问题,最后一个值作为v,p代表左右边界
                int[] p = partition(arr, l, r);
                //对<区域
                quicksort(arr, l, p[0] - 1);
                //对>区域
                quicksort(arr, p[1] + 1, r);
            }
        }
    
        public int[] partition(int arr[], int l, int r) {
            // input: 3,6,2,5,7,5
            int less = l - 1;//< 区域
            //这里r是因为,最后一个r表示荷兰问题中value
            //l ~ r-1 之前表示荷兰问题
            int more = r;//> 区域
            //结束条件是 指针和>区域相遇
            while (l < more) {
                if (arr[l] < arr[r]) {
                    swap(arr, l++, ++less);
                } else if (arr[l] > arr[r]) {
                    swap(arr, l, --more);
                }else {
                    l++;
                }
            }
            // 荷兰问题之后:3, 2, 5, 7, 6, 5
            //将最后一个值和>区域的第一个值交换,因为最后一个是=区域的
            swap(arr,r,more);
            // 交换完之后: 3, 2, 5, 5, 6, 7
            return new int[]{less+1,more};
        }
    
        public void swap(int[] arr, int i, int j) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    堆排序

    • 时间O(NlogN)、空间O(1)、不稳

    public void heapSort(int[] arr) {
            if (arr == null || arr.length < 2) return;
            //将数组变为堆
            for (int i = 0; i < arr.length; i++) {
                heapInsert(arr, i);
            }
    
            int heapsize = arr.length;
            //最大的在堆顶,放到后面,heapsize--,继续堆化调整
            swap(arr, 0, --heapsize);
            while (heapsize > 0) {
                heapify(arr, 0, heapsize);
                swap(arr, 0, --heapsize);
            }
    }
    
    public void heapInsert(int[] arr, int i) {
        while (arr[i] > arr[(i - 1) / 2]) {
            swap(arr, i, (i - 1) / 2);
            i = (i - 1) / 2;
        }
    }
    
    public void heapify(int[] arr, int i, int heapsize) {
        int left = i * 2 + 1;
        while (left < heapsize) {
            //孩子比较
            int largest = left + 1 < heapsize && arr[left + 1] > arr[left] ? left + 1 : left;
            //父子比较
            largest = arr[largest] > arr[i] ? largest : i;
            //父已经是最大,不用再调整了
            if (i == largest) break;
            //交换调整
            swap(arr, largest, i);
            //下一个调整位置
            i = largest;
            left = i * 2 + 1;
        }
    }
    
    public void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    桶排序

    计数排序

    • 时间O(N+K)、空间O(N+K)、稳
    public void countingSort(int[] arr) {
        int min = arr[0];
        int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            min = Math.min(arr[i], min);
            max = Math.max(arr[i], max);
        }
        //生成对应的词频表
        int[] words = new int[max - min + 1];
        for (int i = 0; i < arr.length; i++) {
            words[arr[i] - min]++;
        }
        //生成前缀和
        for (int i = 1; i < words.length; i++) {
            words[i] += words[i - 1];
        }
        int[] sorted = new int[arr.length];
        //逆序输出
        for (int i = arr.length - 1; i >= 0; i--) {
            //查询词汇表中,arr[i]的下标为词频数量--
            int index = --words[arr[i] - min];
            sorted[index] = arr[i];
        }
        for (int i = 0; i < arr.length; i++) {
            arr[i] = sorted[i];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    基数排序

    • 时间O(N*K)、空间O(N)、稳定
    public void radixSort(int[] arr) {
            int max = Integer.MAX_VALUE;
            for (int i = 0; i < arr.length; i++) {
                max = Math.max(arr[i], max);
            }
            //求得最大值的位数
            int digit = 0;
            while (max != 0) {
                digit++;
                max /= 10;
            }
            //对每一个位进行操作
            for (int i = 0; i < digit; i++) {
                //辅助空间,入桶出桶操作
                int[] bucket = new int[arr.length];
                //每个数字的词频
                int[] words = new int[10];
                //该位上的进制
                int dev = (int) Math.pow(10, i);
                //统计所有数字的该位的词频
                for (int j = 0; j < arr.length; j++) {
                    words[arr[j] / dev % 10]++;
                }
                //前缀和
                for (int j = 1; j < 10; j++) {
                    words[j] += words[j - 1];
                }
                //逆序输出,查询词频表的数量--就是下标位置
                for (int j = arr.length - 1; j >= 0; j--) {
                    bucket[--words[arr[j] / dev % 10]] = arr[j];
                }
                for (int j = 0; j < arr.length; j++) {
                    arr[j] = bucket[j];
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 相关阅读:
    将Django项目部署到服务器
    基于Hadoop的电商用户分析系统
    HSDC和独立生成树相关
    流程图在线制作:5款专业流程图制作网站,无需下载,高效立现!
    如何使用MybatisPlus进行数据分页显示
    Item 36: Specify std::launch::async if asynchronicity is essential.
    Java数据结构——第十二节 - Map和Set
    若依3.6.0使用Mybatis-plus分页失效以及完美替换Pagehelper【已解决】
    必看:阿里云99元服务器老用户续费到2027年的方法!
    数据库-多表设计
  • 原文地址:https://blog.csdn.net/qq_41080854/article/details/128008858