排序算法和java实现

一、冒泡排序

1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2、 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3、针对所有的元素重复以上的步骤,除了最后一个。
4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

public static void bubblesort(int[] array){
        for(int j=0;j<array.length-1;j++){
        for(int i = 0;i<array.length-1;i++){
            if(array[i+1]<array[i]){
                int tmp=array[i];
                array[i]=array[i+1];
                array[i+1]=tmp;
                }
            }
        }
    }   

二、选择排序

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

public static void selection_sort(int[] unsort) {
        for (int i = 0; i < unsort.length - 1; i++) {
            int min = unsort[i];
            int min_index = i;
            for (int j = i + 1; j < unsort.length; j++) {
                if (unsort[j] < min) {
                    min = unsort[j];
                    min_index = j;
                }
            }
            if (min_index != i) {
                int tmp = unsort[i];
                unsort[i] = unsort[min_index];
                unsort[min_index] = tmp;
            }
        }
    }

三、插入排序

1、从第一个元素开始,该元素可以认为已经被排序
2、取出下一个元素,在已经排序的元素序列中从后向前扫描
3、如果该元素(已排序)大于新元素,将该元素移到下一位置
4、重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5、将新元素插入到该位置后
6、重复步骤2~5

public static void insertionsort(int[] array){
        for(int i=1;i<array.length;i++){
            int j=i-1;
            int currentNumber=array[i];
            while(j>=0&&array[j]>array[i]){
                array[j+1]=array[j];
                j--;
            }
            array[j + 1] = currentNumber;
        }
    }

四、快速排序

1、从数列中挑出一个元素,称为”基准”(pivot),
2、重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
3、递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

public static int partition(int[] array, int low, int high) {
        if (low < high) {
            return -1;
        }
        int tmp = array[low];// 枢轴记录
        while (low < high) {
            while (low < high && array[high] >= tmp) {
                high--;
            }
            array[low] = array[high];// 交换比枢轴小的记录到左端
            while (low < high && array[low] <= tmp) {
                low++;
            }
            array[high] = array[low];// 交换比枢轴小的记录到右端
        }
        // 扫描完成,枢轴到位
        array[low] = tmp;
        // 返回的是枢轴的位置
        return low;
    }

    public static void quicksort(int[] array, int low, int high) {
        if (low < high) {
            int dp = partition(array, low, high);// 将数组分为两部分
            quicksort(array, low, dp - 1);// 递归排序左子数组
            quicksort(array, dp + 1, high);// 递归排序右子数组
        }
    }

五、归并排序

1、将序列每相邻两个数字进行归并操作,形成 floor(n/2)个序列,排序后每个序列包含两个元素
2、将上述序列再次归并,形成 floor(n/4)个序列,每个序列包含四个元素
3、重复步骤2,直到所有元素排序完毕

归并排序其实就做两件事:
1、“分解”——将序列每次折半划分。
2、“合并”——将划分后的序列段两两合并后排序。

核心思想就是将两个已经各自排好顺序的数组合并成一个。这样我们递归的将一个大的数组,不断分成2段,直到每个数组只有一个元素。同时也不断合并已经排好顺序的数组,直到全都合并完成。过程如下图;

这里写图片描述

public class merge_sort {
    public static void main(String[] args){
        int arr[]  = new int[]{10,9,12,4,11,7,8,3};
        Sort(arr);
        System.out.println(Arrays.toString(arr));  //将整型数组转换为String,打印出来 
    }
    public static void Sort(int  arr[]){
        int tmpArray[] = new int[arr.length]; //创建一个临时的数组来存放临时排序的数组 
        mergeSort(arr,tmpArray, 0 ,arr.length-1);    //开始对数组归并排序 

    }
     //用递归的方法,对数组进行归并排序

    private static void mergeSort(int arr[],int tmpArray[],int first ,int last){
        if(first<last){ //   确定数组不是空的 
            int mid =(first+last)/2;   //将数组分成两段  
             //下面是用递归的方法,不断分割数组。即1分2,2分4,以此类推。直到每个数组都只剩下2个元素。
            mergeSort(arr,tmpArray,first,mid);
            mergeSort(arr,tmpArray,mid+1,last);
            // 下面是利用临时数组tmpArray[] 对分割后的数组排序和归并
            merge(arr,tmpArray,first,mid,last);
            System.out.println(Arrays.toString(arr)); 
        }
    }
    // 合并两个有序子序列 a[first, ..., mid] 和 a[mid+1, ..., last]。tmpArray是辅助数组
    private static  void merge(int a[],int tmpArray[],int first,int mid,int last){
        int beginHalf1  = first; //   第一段数组的起始元素下标  
        int endHalf1    = mid; //   第一段数组的末尾元素下表 
        int beginHalf2 = mid+1; //   第二段数组的起始元素下标 
        int endHalf2    = last; //   第二段数组的末尾元素下标 
        int index   = beginHalf1;  //   临时数组的索引 
        int num = last - first+1;    //   将临时数组tmpArray中已经排好顺序的元素拷贝到数组arr[]需要的次数, (其中没有排好顺序的元素自然就不用复制过去,所以arr那些没有排序的元素还是原样。

        while((beginHalf1 <= endHalf1) && (beginHalf2 <= endHalf2)){ // 确认分割后的两段数组是否都取到了最后一个元素
            if(a[beginHalf1] <= a[beginHalf2]){      //   分别到两段数组中抽取两个元素的值进行比较 
            //哪那个元素值小,就复制到临时数组tmpArray对应的位置中,然后index++,同时将那段数组再去下一个元素

                tmpArray[index++] = a[beginHalf1++];
            }
            else{
                tmpArray[index++] = a[beginHalf2++];

            }

        }
         //经过上面的while循环,必定有段数组的元素都取光了,即肯定还有一段数组是没有取光的,不但没取光,而且剩下的元素还已经排完序了。所以下面两个while只有一个会执行,就是将剩下的那段数组的已经排好顺序的元素都拷贝到临时数组tmpArray[]中对应的位置。 

        while(beginHalf1 <= endHalf1){
            tmpArray[index++] = a[beginHalf1++];
        }
        while(beginHalf2 <= endHalf2){
            tmpArray[index++] = a[beginHalf2++];
        }
         //   将临时数组tmpArray[]中的已经排好顺序的元素全都拷贝到原来的数组arr[]中
        for(int i = 0 ; i < num ;i++,endHalf2--){
            a[endHalf2] = tmpArray[endHalf2];
        }


    }

}

各种排序算法的时间复杂度和空间复杂度比较:

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值