排序算法总结——java语言实现

一、冒泡排序

(1)、基本思想
第一趟,从第0个记录到第n-1个记录,i和i+1关键码进行比较,与要求逆序则交换位置。一趟后最大的关键码就放到了n位置
第二趟,从第0个记录到第n-2进行第二趟冒泡。
如此重复n-1趟,如果在一趟中没有发生交换,说明数组已经是有序的了。

(2)、代码实现

    //冒泡排序实现
    public static void buble_sort(int[] arr){
        //不合法检验
        if(arr==null||arr.length<2){
            return;
        }
        for(int i=0;i<arr.length-1;i++){
            int flag=0;
            for(int j=0;j<arr.length-i-1;j++){
                if(arr[j]>arr[j+1]){
                    int tmp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=tmp;
                    flag=1;
                }
            }
            if(flag==0) break;//一趟中如果没有交换说明已经排好序了
        }


    }

(3)、性能分析
冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1),它是一种稳定的排序算法。

二、选择排序

(1)、基本思想
第i趟,从i+1到n-1 ,用一个变量保存最小值小标,最后变量位置和i位置进行交换

进行n-1趟
(2)、代码实现

    //选择排序实现
    public static void select_sort(int[] arr){
        //不合法检验
        if(arr==null||arr.length==0){
            return;
        }
        for(int i=0;i<arr.length-1;i++){
            int minIndex=i;
           for(int j=i+1;j<arr.length;j++){
                if(arr[minIndex]>arr[j]) minIndex=j;
           }
            if(minIndex!=i){
                int tmp=arr[minIndex];
                arr[minIndex]=arr[i];
                arr[i]=tmp;
            }
        }


    }

(3)、性能分析
选择排序交换次数较少,时间复杂度为O(n^2)。
举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序是一个不稳定的排序算法

三、归并排序

(1)、基本思想
归并排序是基于一种被称为“分治”(divide and conquer)的策略。其基本思路是这样的:
1.对于两个有序的数组,要将其合并为一个有序数组,我们可以很容易地写出如下代码:

public void merge(int[] a, int[] b, int[] c){
    int i=0,j=0,k=0;
    while (i<=a.length && j<=b.length){
        if (a[i]<=b[i]){
            c[k++]=a[i++];
        }
        else{
            c[k++]=b[j++];
        }
    }
    while (i<=a.length){
        c[k++]=a[i++]; 
    }
    while (j<=b.length){
        c[k++]=b[j++];
    }
}

容易看出,这样的合并算法是高效的,其时间复杂度可达到O(n)。

2.假如有一个无序数组需要排序,但它的两个完全划分的子数组A和B分别有序,借助上述代码,我们也可以很容易实现;

3.那么,如果A,B无序,怎么办呢?可以把它们再分成更小的数组。

4.如此一直划分到最小,每个子数组都只有一个元素,则可以视为有序数组。

5.从这些最小的数组开始,逆着上面的步骤合并回去,整个数组就排好了。

总而言之,归并排序就是使用递归,先分解数组为子数组,再合并数组。
(2)、代码实现

    //归并排序实现
    public static void MergeSort(int[] a, int[] b, int left, int right){
        //当left==right的时,已经不需要再划分了
        if (left<right){
            int middle = (left+right)/2;
            MergeSort(a, b, left, middle);          //左子数组
            MergeSort(a, b, middle+1, right);       //右子数组
            mergeSortedArray(a, b, left, middle, right);    //合并两个子数组
        }
    }
    // 合并两个有序子序列 arr[left, ..., middle] 和 arr[middle+1, ..., right]。temp是辅助数组。
    public static void mergeSortedArray(int arr[], int temp[], int left, int middle, int right){
        int i=left;
        int j=middle+1;
        int k=0;
        while ( i<=middle && j<=right){
            if (arr[i] <=arr[j]){
                temp[k++] = arr[i++];
            }
            else{
                temp[k++] = arr[j++];
            }
        }
        while (i <=middle){
            temp[k++] = arr[i++];
        }
        while ( j<=right){
            temp[k++] = arr[j++];
        }
        //把数据复制回原数组
        for (i=0; i<k; ++i){
            arr[left+i] = temp[i];
        }
    }

(3)、性能分析
归并排序是稳定排序,它也是一种十分高效的排序。每次合并操作的平均时间复杂度为O(n),而完全二叉树的深度为|log2n|。总的平均时间复杂度为O(nlogn)。而且,归并排序的最好,最坏,平均时间复杂度均为O(nlogn)。
空间复杂度:需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n)
java中Arrays.sort()采用了一种名为TimSort的排序算法,就是归并排序的优化版本。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值