首页 > 其他分享 >排序 我觉得有点难 要常来看

排序 我觉得有点难 要常来看

时间:2024-09-20 21:47:15浏览次数:7  
标签:有点 right int ++ length 要常 array 排序 left

package Sort;

import java.util.Stack;

public class Sort {
    /** 插入排序
     * 时间复杂度:
     *     最好情况 : 数据完全有序的时候 1 2 3 4 5 : O(N)
     *     最坏情况 : 数据完全逆序的时候 5 4 3 2 1 : O(N^2)
     *     结论: 当给出的数据 越有序 排列越快
     *
     * 空间复杂度:O(1)
     * 稳定性:稳定的排序
     *        一个本身就稳定的排序 是可以变成不稳定排序的
     *        但是相反 一个本身就不稳定的排序 是不可以变成稳定排序的
     */
    //插入排序 稳定的排序
    public static void inserSort(int[] array){
        for (int i = 1; i < array.length; i++) {
            int tmp = array[i];
            int j = i - 1;
            while(j>=0){
                if(array[j]>tmp){
                    array[j+1] = array[j];
                }else{
                    break;
                }
                array[j] = tmp;
                j--;
            }
        }
    }
    /** 希尔排序
     *     时间复杂度:O(N^1.3)
     *
     */
    //希尔排序
    public static void shellSort(int[] array){
        int gap = array.length;;
        while(gap > 1){
            gap /= 2;
            shell(array,gap);
        }
    }
    public static void shell(int[] array,int gap){
        for (int i = gap; i < array.length; i++) {
            int tmp = array[i];
            int j = i - gap;
            while(j>=0){
                if(array[j]>tmp){
                    array[j+gap] = array[j];
                }else{
                    break;
                }
            }
            array[j+gap] = tmp;
            j-=gap;
        }
    }

    /** 选择排序
     *      时间复杂度:O(N^2)
     *      空间复杂度:O(1)
     *      不稳定排序
     */
    public static void choseSort(int[] array){
        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            for (int j = i+1; j < array.length; j++) {
                if(array[j]<array[minIndex]){
                    minIndex = j;
                }
            }
            swap(array,i,minIndex);
        }
    }
    public static void swap(int[] array,int i,int j){
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
    public static void choseSort1(int[] array){
        int left = 0;
        int right = array.length-1;
        while(left<right) {
            int minIndex = left;
            int maxIndex = left;
            for (int i = left + 1; i < right; i++) {
                if (array[i] < array[minIndex]) {
                    minIndex = i;
                }
                if (array[i] > array[maxIndex]) {
                    maxIndex = i;
                }
            }
            swap(array,left,minIndex);
            if(maxIndex == left){
                maxIndex = minIndex;
            }
            swap(array,right,maxIndex);
            left++;
            right--;
        }
    }
    /** 堆排序
     *      时间复杂度:O(N*logN)
     *      空间复杂度:O(1)
     *      不稳定排序
     */


    /** 冒泡排序:
     *      时间复杂度:O(N^2) 优化后最好情况:O(N)
     *      空间复杂度:O(1)
     *      稳定性:稳定排序
     */
    public static void bubbleSort(int[] array){
        for (int i = 0; i < array.length-1; i++) {
            boolean flg = false;
            for (int j = 0; j < array.length-1-i; j++) {
                if(array[j]>array[j+1]){
                    swap(array,j,j+1);
                    flg = true;
                }
            }
            if(!flg){
                return;
            }
        }
    }

    /** 快速排序
     *     时间复杂度:
     *          最好的情况:O(N*logN) 满二叉树 或者是 均匀的二叉树
     *          最坏的情况:O(N^2) 单分支的树
     *     空间复杂度:
     *          最好的情况:O(logN)
     *          最坏的情况:O(N)
     *     稳定性:
     *
     *
     *     当数据 太多而且需求量很大的时候 就 容易出现 栈溢出的报错 这里需要优化 如何解决溢出问题?
     */
    public static void quickSort(int[] array){
        quick(array,0,array.length-1);
    }
    public static void quick(int[] array,int start,int end){
        if(start >= end)return;//剩下一个节点或者一个节点都没有了
        //if(end-start+1<=7){inserSortRand(array,start,end);return;}//减少递归次数
        int index = midOfThree(array,start,end);//三数取中
        swap(array,start,index);//保证start 一定是中间大的数字
        int pivot = partition(array,start,end);

        quick(array,start,pivot-1);
        quick(array,pivot+1,end);
    }
    public static int partition(int[] array,int left,int right){
        int key = array[left];
        int i = left;
        //循环让 key的左右 一定 大于或者小于key
         while(left < right){
             //这里就找到了 小于k 的右边的下标
             while(left<right && key <= array[right]){
                  right--;
             }
             //这里就找到了 大于k 的左边边的下标
             while(left<right && key >= array[left]){
                 left++;
             }
             swap(array,left,right);
         }
         //相遇的位置和 i 位置交换
        swap(array,i,left);
        return left;
    }
    //三数取中 (优化快速排序)  避免单分支树的情况 保证 左右两边都有比他大或者比他小的数字
    public static int midOfThree(int[] array,int left,int right){
        int mid = (left+right)/2;
        if(array[left] > array[right]){
            if(array[mid] > array[left]){
                return left;
            }else if(array[mid] < array[right]){
                return right;
            }else{
                return mid;
            }
        }else{
            if(array[mid] < array[left]){
                return left;
            }else if(array[mid] > array[right]){
                return right;
            }else{
                return mid;
            }
        }
    }

    //快速排序优化 挖坑法
    public static int partition2(int[] array,int left,int right){
        int key = array[left];
        //循环让 key的左右 一定 大于或者小于key
        while(left < right){
            //这里就找到了 小于k 的右边的下标
            while(left<right && key <= array[right]){
                right--;
            }
            array[left] = array[right];
            //这里就找到了 大于k 的左边边的下标
            while(left<right && key >= array[left]){
                left++;
            }
            array[right] = array[left];
        }
        //相遇的位置和 i 位置交换
        array[left] = key;
        return left;
    }

    //前后指针法
    public static int partition3(int[] array,int left,int right){
        int prev = left;
        int cur = left+1;
        while(cur <= right){
            if(array[cur]<left && array[++prev]!=array[cur]){
                swap(array,prev,cur);
            }
            cur++;
        }
        swap(array,prev,left);
        return prev;
    }
    //区间内的插排  优化递归次数 但是时间不一定优化
    public static void inserSortRand(int[] array,int begin,int end){
        for (int i = begin+1; i <= end; i++) {
            int tmp = array[i];
            int j = i - 1;
            while(j>=begin){
                if(array[j]>tmp){
                    array[j+1] = array[j];
                }else{
                    break;
                }
            }
            array[j+1] = tmp;
            j--;
        }
    }
    //快速排序的非递归排序
    public static void quickSortNor(int[] array){
        Stack<Integer> stack = new Stack<>();
        int left = 0;
        int right = array.length-1;
        int pivot = partition(array,left,right);
        if(pivot-1>left){
            stack.push(left);
            stack.push(pivot-1);
        }
        if(pivot+1<right){
            stack.push(pivot+1);
            stack.push(right);
        }
        while(!stack.isEmpty()){
            right = stack.pop();
            left = stack.pop();
            pivot = partition(array,left,right);
            if(pivot-1>left){
                stack.push(left);
                stack.push(pivot-1);
            }
            if(pivot+1<right){
                stack.push(pivot+1);
                stack.push(right);
            }
        }
    }

    /**
     * 时间复杂度:O(N*logN)
     * 空间复杂度:O(N)
     * 稳定性:稳定
     * @param array
     */
    public static void mergeSort(int[] array){
        mergeSortFunc(array,0,array.length-1);
    }
    public static void mergeSortFunc(int[] array,int left,int right){
        if(left >= right)return;
        int mid = (left+right)/2;
        mergeSortFunc(array,left,mid);
        mergeSortFunc(array,mid+1,right);
        merge(array,left,right,mid);
    }
    //感觉这里的递归怪怪的
    private static void merge(int[] array, int left, int right, int mid) {
        int s1 = left;
        int s2 = mid+1;
        int[] temArr = new int[right-left+1];
        int k = 0;

        while(s1<=mid && s2 <=right){
            if(array[s1]>=array[s2]){
                temArr[k++] = array[s2++];
            }else{
                temArr[k++] = array[s1++];
            }
        }

        while(s1 <= mid){temArr[k++] = array[s1++];}
        while(s2 <= right){temArr[k++] = array[s2++];}
        //这里的 temArr数组已经是有序数组了

        for (int i = 0; i < temArr.length; i++) {
            array[i+left] = temArr[i];//考虑 右边的排序
        }
    }
    //归并的无递归写法
    public static void mergeSortNor(int[] array){
        int gap = 1;
        while(gap<array.length){
            for (int i = 0; i < array.length; i+=2*gap) {
                int left = i;
                int mid = left+gap-1;
                int right = mid+gap;
                if(mid >= array.length-1){mid = array.length-1;}//如果mid刚刚好是最后一个数 或者比最后一个数大的话
                if(right >= array.length-1){right = array.length-1;}
                merge(array,left,right,mid);
            }
            gap*=2;
        }
    }

    //计数数组 不比较的排序
    public static void countSort(int[] array){
        int minVal = array[0];
        int maxVal = array[0];
        for (int i = 0; i < array.length; i++) {
            if(array[i]<minVal){
                minVal = array[i];
            }
            if(array[i]>maxVal){
                maxVal = array[i];
            }
        }
        int[] count =new int[maxVal-minVal+1];
        for (int i = 0; i < array.length; i++) {
            count[array[i]-minVal]++;
        }
        int index = 0;
        for (int i = 0; i < count.length; i++) {
            while(count[i]>0){
                array[index] = i+minVal;
                index++;
                count[i]--;
            }
        }
    }


    /**
     * 为什么会溢出?
     */

}

标签:有点,right,int,++,length,要常,array,排序,left
From: https://www.cnblogs.com/ljy2003/p/18423345

相关文章

  • c# 笔记 winform添加右键菜单,获取文件大小 ,多条件排序OrderBy、ThenBy,list<double>截取
    Winform右键菜单‌要在C#Winform应用程序中添加右键菜单,‌你可以按照以下步骤操作:‌1.‌创建菜单项‌在Form的构造函数或加载事件中,‌创建ContextMenuStrip控件的实例,‌并为其添加菜单项。‌2.‌绑定到控件‌将ContextMenuStrip控件绑定到需要显示右键菜单的控件上,‌如Panel......
  • 基于Vue 3组合函数的分页、搜索与排序实践 —— nbsaas-boot项目的实际应用
    随着前端框架的不断发展,Vue3引入的组合式API(CompositionAPI)为开发者提供了一种更灵活、更强大的逻辑复用方式。组合函数(CompositionFunction)可以将通用逻辑抽取成独立模块,便于在不同组件间共享和复用。本文将基于nbsaas-boot项目,详细介绍如何通过Vue3的组合函数实现分页、......
  • Oracle 中,根据状态字段进行自定义排序例(待验证、待维修、重新维修)
    按照指定的顺序(待验证、待维修、重新维修、待派单、待接单、驳回、已完成)进行排序,可以修改ORDERBY子句中的CASE语句。以下是修改后的查询:SELECT a.nid,  CASEa.REPAIR_PROGRESS    WHEN1THEN'待验证'    WHEN2THEN'待维修'    WHEN3TH......
  • Go 入门指南:8.5. map 的排序
     原创 吃个大西瓜 CodingBigTree  2024年09月19日08:00 云南map默认是无序的,不管是按照key还是按照value默认都不排序(详见第8.3节)。如果你想为map排序,需要将key(或者value)拷贝到一个切片,再对切片排序(使用sort包,详见第7.6.6节),然后可以使用切片......
  • 2024Mysql And Redis基础与进阶操作系列(5)作者——LJS[含MySQL DQL基本查询:select;简单
    目录1MySQL数据库基本操作-DQL-基本查询1.2SQL概述1.3SQL类2.SQL语言的规则与规范2.1基本规则2.2SQL大小写规范推荐采用统一的书写规范:2.3注释2.4命名规则(了解即可)举例:两句是一样的,不区分大小写创建表格order使用``飘号,因为order和系统关键字或系统函数名......
  • 34. 在排序数组中查找元素的第一个和最后一个位置
    思路先判断target是否存在列表中,不存在直接输出存在,则找出第一个等于target值的列表位置,即目标值在列表中的开始位置接着在当前位置继续往下查找,找到最后一个目标值等于列表值的位置(也可用二分查找找到等于target值的位置+往前、往后找到开始、结束位置,但会超限,可参考(......
  • 算法设计与分析(合并排序
    目录归并排序(MergeSort)的C++实现源代码解释结果小结:归并排序(MergeSort)的C++实现归并排序是一种分而治之的算法,它将数组分成两半,对每半部分递归地应用归并排序,然后将排序好的两半合并成一个有序的数组。以下是一个归并排序的C++实现。源代码#include<iostream>usingnames......
  • mysql查询字段排序规则、数据库编码、表编码,修改排序规则
    查询字段排序规则、数据库编码、表编码SELECTTABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME,COLLATION_NAMEFROMINFORMATION_SCHEMA.COLUMNS 表字段修复#改变字段数据字符集、排序规则SELECTTABLE_SCHEMA'数据库',TABLE_NAME'表',CO......
  • 15:00面试,15:06就出来了,问的问题有点变态。。。
    从小厂出来,没想到在另一家公司又寄了。到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到9月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%,这下搞的饭都吃不起了。还在有个朋友内推我去了一家互联网公司,兴冲冲见面试官,没想到一道......
  • 【每日一题】LeetCode 2332.坐上公交的最晚时间(数组、双指针、二分查找、排序)
    【每日一题】LeetCode2332.坐上公交的最晚时间(数组、双指针、二分查找、排序)题目描述给你一个下标从0开始长度为n的整数数组buses,其中buses[i]表示第i辆公交车的出发时间。同时给你一个下标从0开始长度为m的整数数组passengers,其中passengers[j]表示第......