五种常用排序算法 java 实现

 时间复复杂度空间复杂度是否稳定存储方式备注
冒泡On2O1

稳定

(相邻交换)

可链式存储

移动次数较多,时间性能差于插入算法。

初始值无序,n 较大时不宜采用。

选择On2O1

不稳定

(跳跃交换)

可链式存储移动次数较少,当每个数据占空间较大时,比插入排序快。
插入On2O1

稳定

(单方向交换)

可链式存储

适合初始值基本有序。

若无序,n 较大,此算法时间复杂度较高,不宜采用。

快排Onlog2nOlog2n~On

不稳定

(跳跃交换)

不可链式存储。

排序过程需要定位表的上下界

n 较大,初始值无序时,是所有内部排序中最快的。

很小的数组(N<=20)快排不如插入排序。

归并Onlog2nOn

稳定

(相邻交换)

可链式存储,不需要附加存储空间Java类库泛型排序所使用的算法

 

测试代码

import java.util.Arrays;
import java.util.Random;

//多种排序测试
public class SortTest {
    public static void main(String[] args) {
        Random rd = new Random();
        int[] array = new int[21];
        int index=0;
        for(int i=21; i>0;i--){
            array[index++] = i;
        }
        System.out.println("排序前:");
        System.out.println(Arrays.toString(array));
        //BubbleSort(array);
        //QSort(array);
        //SelectSort(array);
        //InsertSort(array);
        //MergeSort(array);
        System.out.println("排序后:");
        System.out.println(Arrays.toString(array));
    }

    //冒泡排序--网上
    private static void BubbleSort(int[] array){
        if(null==array || array.length<2) return ;
        //每一轮规则:前后两两比较,前者比后者大,调换,否则不换。 一直保持后者更大,前者更小。
        //一轮下来,最大值换到最后面。
        //第二轮的时候就不需要比较最后一位了
        //第三轮就不需要比较最后2位
        //最后一轮只需要第一跟第二比就可以
        //所以外循环控制轮数,一共需要比 n-1轮
        //内存换控制每一轮比较次数,是变化的,n-1-i 次
        for(int i=0; i<array.length-1; i++){
            for(int j=0; j<array.length-1-i; j++){
                if(array[j]>array[j+1]){
                    int t=array[j];
                    array[j] = array[j+1];
                    array[j+1] = t;
                }
            }
        }
    }
    //选择排序--严蔚敏
    public static void SelectSort(int[] array){
        if(null==array||array.length<2) return;
        //第一轮 i0 轮流和 i1,i2,i3...ileng比较,如果遇到比自己小的就交换,一轮下来保证 i0最小
        //第二轮 i1 轮流和 i2,i3...ileng 比较,遇到比自己小的就交换,一轮下来保证 i1最小
        //。。。
        //最后一轮 ileng-2和 ileng-1 比较,遇到比自己小的就交换,结果排序完成
        //i一共比较 leng-1次;j 从 i+1开始,最多是 leng-1
        for(int i=0; i<array.length-1; i++){
            int pMin=i;
            for(int j=i+1; j<array.length; j++)
                if(array[pMin]>array[j]) pMin=j;      //pMin 指向此趟排序中最小值
            if(i!=pMin){                              //如果最小值发生变动,则交换
                int t = array[i];
                array[i] = array[pMin];
                array[pMin] = t;
            }
        }
    }
    //插入排序--数据结构与算法分析
    //时间复杂度On2      空间复杂度 O1
    //稳定排序(因为是一位一位移动(交换)的,所以不会像选择排序那样跳跃交换导致不稳定)
    //适合初始值基本有序情况,当初始值无序且 n 较大时,时间复杂度校稿,不适合。
    public static void InsertSort(int[] array){
        if(null==array||array.length<2) return;
        //数组  12  22  3   4   1   40
        //下标  0   1   2   3   4   5
        //第一轮   i0(12)作为排序后数组,其它都是未排序数据。前面的数如果比待插入数大,则把前面元素往后移动一位。前面没了,就把待插入数插入当前位置。
        //第n轮   i0,i1(12 22)作为排序后数据,其它都是未排序数据。前面数如果比待插入数大,就把前面元素往后移动一位,直到前面元素不大于位置,把待插入数插入到当前位置。
        //外循环一共需要比较 n-1轮
        int j,i;
        int t;
        for(i=1; i< array.length; i++){
            t=array[i];
            for(j=i; j>0 && array[j-1]>t; j--){ //如果是引用数据类型,则需要用 compareTo 比较大小
                array[j] = array[j-1];
            }
            array[j] = t;
        }
    }
    
    //快速排序--严蔚敏
    //对循序表 array 做快速排序
    public static void QSort(int[] array){
        if(null==array || array.length<2) return;
        quickSort(array,0,array.length-1);
    }
    //对顺序表 array 中的序列 array[low,high]做快速排序
    public static void quickSort(int[] array, int low, int high){

        if(low<high){                           //隐含判断长度大于1
            int pivotLoc= partition(array,low,high);  //将子序列一分为二,pivotLoc 是枢轴位置
            quickSort(array,low,pivotLoc-1);    //对左子表递归排序
            quickSort(array,pivotLoc+1,high);   //对右子表递归排序
        }
    }
    //对顺序表 array 中的子表array[low,high]进行一趟排序,返回枢轴位置
    public  static int partition(int[] array, int low, int high){
        int pivotKey=array[low];                //用子表第一个记录做枢轴值
        while(low<high){                        //从表的两端交替向中间扫描
            while(low<high && array[high]>=pivotKey)
                high--;
            array[low] = array[high];           //将比枢轴值小的值移动到低端

            while(low<high && array[low]<=pivotKey)
                low++;
            array[high] = array[low];           //将比枢轴值大的值移动到高端
        }                                       //while 结束时 low==high,已到达枢轴在排序中的位置
        array[low] = pivotKey;                  //枢轴值到位
        return low;                             //返回枢轴位置
    }

    //归并排序--数据结构与算法分析
    //需要一份与待排序数据相等的额外存储空间
    public static void MergeSort(int[] array){
        if(null==array||array.length<2)return;
        int[] tmpArray = new int[array.length];
        mSort(array,tmpArray,0,array.length-1);
    }

    //归并算法递归部分
    //分治思想,一组分两半,其中一半再分两半,再分,再分,直到剩1个值分不开了,开始回溯
    //回溯就是往上 merge,先归左边最小的,左边归并完,归并右边最小的,右边归并完,归并总体,完成
    public static void mSort(int[] array, int[] tmpArray, int low, int high){
        if(low < high) {
            int mid = (low+high)/2;
            mSort(array,tmpArray,low,mid);
            mSort(array,tmpArray,mid+1,high);
            merge(array,tmpArray,low,mid,high);
        }
    }

    //归并算法核心
    //将一组数据分成两半,两半的数据从左到右一对一对比较大小,小的先放到临时数组,大的后放,剩余的直接放
    //最后将临时数组的值再倒回原始数组
    public static void merge(int[] a,int[] t,int low,int mid,int high){
        int p1=low;
        int p2=mid+1;
        int k=low;
        while(p1<=mid&&p2<=high){           //将 a[low,mid] a[mid+1,high] 中的值比较大小并入 t[] 中,从小到大
            if(a[p1]<=a[p2])t[k++]=a[p1++];
            else t[k++]=a[p2++];
        }
        while(p1<=mid)t[k++]=a[p1++];       //将a[low,mid]中剩余的值直接放入 t[]中
        while(p2<=high)t[k++]=a[p2++];      //将a[mid+1,high]中剩余的值直接放入 t[]中
        for(int i=low;i<=high;i++){         //将 t 中的值倒回 a 中
            a[i]=t[i];
        }
    }

}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值