排序方法

  1. 快排
    快排原理:
    在要排的数(比如数组A)中选择一个中心值key(比如A[0]),通过一趟排序将数组A分成两部分,其中以key为中心,key右边都比key大,key左边的都key小,然后对这两部分分别重复这个过程,直到整个有序。
    最优的情况下,快速排序算法的时间复杂度为O(nlogn);最坏情况时间复杂度为O(n²),快速排序的平均时间复杂度为O(n×log(n))。
public static int partition(int []array,int lo,int hi){
        int key=array[lo];//设置key
        while(lo<hi){
            while(array[hi]>=key&&hi>lo){//从后半部分向前扫描
                hi--;
            }
            array[lo]=array[hi];
            while(array[lo]<=key&&hi>lo){从前半部分向后扫描
                lo++;
            }
            array[hi]=array[lo];
        }
        array[hi]=key;
        return hi;
    }  
    public static void sort(int[] array,int lo ,int hi){
        if(lo>=hi){
            return ;
        }
        int index=partition(array,lo,hi);
        sort(array,lo,index-1);
        sort(array,index+1,hi); 
    } 
  1. 冒泡排序
    分析冒泡算法最好情况是一趟排好,所以冒泡排序最好的时间复杂度为O(n);最坏情况为排到最后才排完,时间复杂度为O(n²)。所以冒泡排序的平均复杂度为O(n²) 。
for(int i=0;i<arr.length-1;i++){//外层循环控制排序趟数
      for(int j=0;j<arr.length-1-i;j++){//内层循环控制每一趟排序多少次
        if(arr[j]>arr[j+1]){
          swap(arr[j],arr[j+1]);
        }
      }
    } 
  1. 归并排序
    两路归并排序三个步骤:
    第一, 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素.
    第二, 治理: 对每个子序列分别调用归并排序MergeSort, 进行递归操作
    第三, 合并: 合并两个排好序的子序列,生成排序结果.
    对长度为n的文件,需进行趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。
public static int[] sort(int[] arr,int low,int high){
        int mid = (low+high)/2;
        if(low<high){
            sort(arr,low,mid);
            sort(arr,mid+1,high);
            //左右归并
            merge(arr,low,mid,high);
        }
        return arr;
    }
    public static void merge(int[] arr, int low, int mid, int high) {
        int[] temp = new int[high-low+1];
        int i= low;
        int j = mid+1;
        int k=0;
        // 把较小的数先移到新数组中
        while(i<=mid && j<=high){
            if(arr[i]<arr[j]){
                temp[k++] = arr[i++];
            }else{
                temp[k++] = arr[j++];
            }
        }
        // 把左边剩余的数移入数组 
        while(i<=mid){
            temp[k++] = arr[i++];
        }
        // 把右边边剩余的数移入数组
        while(j<=high){
            temp[k++] =arr[j++];
        }
        // 把新数组中的数覆盖nums数组
        for(int x=0;x<temp.length;x++){
            arr[x+low] = temp[x];
        }
    }
  1. 桶排序
    桶排序中:无序数组有个要求,就是成员隶属于固定(有限的)的区间,即知道数组中的元素大致在哪个范围,如范围为0-9,0-99。
    例如待排数字[6 2 4 1 5 9],准备10个空桶,最大数个空桶,数字几就放入几号空桶,对应后依次取值,跳过空桶即排序完成。
    对于N个待排数据,M个桶,平均每个桶[N/M]个数据的桶排序平均时间复杂度为: O(N)+O(M*(N/M)log(N/M))=O(N+N(logN-logM))=O(N+NlogN-NlogM),当N=M时,即极限情况下每个桶只有一个数据时。桶排序的最好效率能够达到O(N)。
public static int[] bucketSort(int[] nums, int maxNum){
    int[] sorted = new int[maxNum+1];

    for(int i=0; i<nums.length; i++){
        sorted[nums[i]] = nums[i];//把数据放到对应索引的位置
    }
    return sorted;
}
  1. 插入排序
    直接插入排序的基本思想:在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。
public void insertSort(int [] a){
        int len=a.length;//单独把数组长度拿出来,提高效率
        int insertNum;//要插入的数
        for(int i=1;i<len;i++){//因为第一次不用,所以从1开始
            insertNum=a[i];
            int j=i-1;//序列元素个数
            while(j>=0&&a[j]>insertNum){//从后往前循环,将大于insertNum的数向后移动
                a[j+1]=a[j];//元素向后移动
                j--;
            }
            a[j+1]=insertNum;//找到位置,插入当前元素
        }
    }
  1. 选择排序
    选择排序的步骤:1.遍历整个序列,将最小的数放在最前面;2.遍历剩下的序列,将最小的数放在最前面;3.重复第二步,直到只剩下一个数。
    时间复杂度为O(n²)
public void selectSort(int[]a){
        int len=a.length;
        for(int i=0;i<len;i++){//循环次数
            int value=a[i];
            int position=i;
            for(int j=i+1;j<len;j++){//找到最小的值和位置
                if(a[j]<value){
                    value=a[j];
                    position=j;
                }
            }
            a[position]=a[i];//进行交换
            a[i]=value;
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值