选择排序、冒泡排序、插入排序、计数排序(Java实现)

     Java中排序的应用很广泛,例如上条博客的二分查找,要求必须是一个有序序列才可以进行查找。所以排序很大程度上方便了我们进行查找操作,接下来一起来认识以下几种排序方式。

  • 选择排序

选择排序是一种简单直观的排序。它的原理是:假设有一个数组arr[n],第一轮比较从arr[0]开始,当前元素arr[0]和后面的所有元素依次比较,如果当前元素arr[0]大于(小于)后面的元素则交换位置。

第几轮 比较次数
第1轮 n-1
第2轮 n-2
... ...
第n-1轮 1

代码实现:

class Sort_01{
    public static void main(String[] args){
       selectSort();
    }
 public static void selectSort(){
        int[] arr={8,5,9,2,7,4,6,1,3};
        for(int i=0;i<arr.length-1;i++){//-1是因为没有必要进行最后一个数字的比较
            for(int j=i+1;j<arr.length;j++){
                if(arr[i]>arr[j]){
                    swap(arr,i,j);//即用-即释放
                }
            }
        }
        show(arr);
    }
public static 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 static void show(int[] arr){
        //输出格式[x,x,x,x,x,x,x];
        String s="[";
        for(int i=0;i<arr.length;i++){
            if(i==arr.length-1){
                s+=arr[i]+"]";
            }else{
                s+=arr[i]+",";
            }
        }
        System.out.println(s);
    }
}
  • 冒泡排序

冒泡排序是一种较简单的排序。它的原理是:比较两个相邻的元素,将值大(小)的元素交换到右边。特点是,每进行一趟排序,就会少比较一次,因为每进行一趟排序都会找出一个较大值沉在末尾。

举一个例子从小到大排序:

56 1 84 32 18
1 56 32 18 84
1 32 18 56 84
1 18 32 56 84
1 18 32 56 54

从上述例子我们可以看到,每轮比较都会产生一个最大值在末尾(如红色数字),而后面的都是已排好的,而且每轮比较都会比上一轮少一次,所以当我们有n个数字时,我们只需要比较n-1轮,而且每一轮的比较次数依次递减,第一轮比较n-1次,第n-1轮比较1次即可。

代码如下:

class Sort_02{
    public static void main(String[] args){
        bubbleSort(); 
    }
  public static void bubbleSort(){
        int[] arr={8,5,9,2,7,4,6,1,3};
        for(int i=0;i<arr.length-1;i++){//-1是少一轮比较
            for(int j=0;j<arr.length-1-i;j++){//-1避免重复比较和角标越界
                if(arr[j]>arr[j+1]){
                    swap(arr,j,j+1);
                }
            }
        }
        show(arr);
    }
public static 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 static void show(int[] arr){
        //输出格式[x,x,x,x,x,x,x];
        String s="[";
        for(int i=0;i<arr.length;i++){
            if(i==arr.length-1){
                s+=arr[i]+"]";
            }else{
                s+=arr[i]+",";
            }
        }
        System.out.println(s);
    }
}
  •  插入排序

插入排序是一种简单直观且稳定的排序算法。它的原理是:简单来说就是当前元素左边有数字且左边数字大于当前数字则进行交换。第一轮从数组第二个元素开始,如果前一个元素大于当前元素则交换位置,并且下一次从前一个元素开始,判断如果再前一个元素仍大于当前元素则再次交换,直到前者小于后者或者没有前一个元素该轮结束,再进行下一轮,从该数组第二个元素开始。

class Sort3{
    public static void main(String[] args){
       insertSort1();
       insertSort2();
    }
//未优化:
    public static void insertSort1(){
        int[] arr={5,9,3,7,1,2,6};
        for(int i=1;i<arr.length;i++){//从第二个元素开始,则进行arr.length-1轮;
            for(int j=i;j>0&&arr[j-1]>arr[j];j--){//判断前面是否有数字且前一个是否大于当前的
                swap(arr,j,j-1);//交换位置
            }
        }
        show(arr);//输出
    }

//优化代码:
    public static void insertSort2(){
        int[] arr={5,9,3,7,1,2,6};
        int e;
        int j;
        for(int i=1;i<arr.length;i++){
            e=arr[i];//先将当前元素存入e
            for(j=i;j>0&&arr[j-1]>e;j--){//判断前面是否有数字且前一个是否大于当前的存储的数字
                arr[j]=arr[j-1];//则将前一个数字拿出来替换当前数字
            }
            arr[j]=e;//全部判断完毕后,条件不成立时,跳出循环,直接把e给arr[j]
        }
        show(arr);
    }
    public static 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 static void show(int[] arr){
        //输出格式[x,x,x,x,x,x,x];
        String s="[";
        for(int i=0;i<arr.length;i++){
            if(i==arr.length-1){
                s+=arr[i]+"]";
            }else{
                s+=arr[i]+",";
            }
        }
        System.out.println(s);
    }
}
  • 计数排序

计数排序是一个非基于比较的排序算法是一种牺牲空间换取时间的做法。简单的说它就是创建一个新的数组来存放所要排序的数组中元素出现的次数,将所求数组的值对应新建数组的角标,将次数存入相应角标,然后再遍历输出新建数组角标对应的原数组的值,输出次数即新建数组对应角标中存放的值。

例如:原数组:

5 1 1 10
角标 0 1 2 3

新建数组:

值(出现次数) 2       1         1
角标 0 1 2 3 4 5 6 7 8 9
对应原数组的值 1       5         10

步骤:

1.先获取原数组中的最大值和最小值max 和 min;

2.根据最大值最小值计算新数组的存储空间大小max-min+1,则新建数组最大角标为max-min。

3.计算偏移量offset=min   角标 = 数据 - offset。

 代码如下:

class Sort_04{
    public static void main(String[] args){
       countSort(); 
    }
    public static void countSort(){
        int[] arr={8,5,9,2,7,4,6,1,3,10,-3,-2,-10};
        int min=arr[0];
        int max=arr[0];
        //1.遍历原数组arr[]计算最大最小值。
        for(int i=0;i<arr.length;i++){//O(n)
            if(arr[i]>max){
                max=arr[i];
            }
            if(arr[i]<min){
                min=arr[i];
            }
        }
        //2.创建新数组nums[]存储大小为max-min+1
        int[] nums=new int[max-min+1];
        //偏移量offset就是最小值。
        int offset=min;
        for(int i=0;i<arr.length;i++){//遍历原数组,如果有重复给新数组对应角标里面的值++。
            nums[arr[i]-offset]++;
        }
        int index=0;//表示原数组的角标
        for(int i=0;i<nums.length;i++){//遍历新数组
            if(nums[i]!=0){//如果里面的值不为0,则
                for(int j=0;j<nums[i];j++){//遍历该数据出现的次数,出现几次打印几次
                    arr[index++]=i+offset;//把值(i+offset)依次存放在原数组的空间中
                }
            }
        }
        show(arr);//调用show()依次打印原数组的值即可。
    }
 public static void show(int[] arr){
        //输出格式[x,x,x,x,x,x,x];
        String s="[";
        for(int i=0;i<arr.length;i++){
            if(i==arr.length-1){
                s+=arr[i]+"]";
            }else{
                s+=arr[i]+",";
            }
        }
        System.out.println(s);
    }
}

以上就是四种排序的思想和实现方法!

猜你喜欢

转载自blog.csdn.net/qq_45111347/article/details/104373578
今日推荐