八大常见排序算法

这几天把数据结构中的八大排序算法复习了一下,今天在这里做个小总结:
1.常见的排序算法
在这里插入图片描述
2,下面分别介绍以下几种排序算法以及他们的性能比较

冒泡排序

  /**  1,冒泡排序   */
    public static void BubbleSort(int[] arr){
       for(int i=1;i<arr.length;i++) {
           int flag=0;
           for(int j=0;j<arr.length-i;j++){
               int tmp=0;
               if(arr[j]>arr[j+1]){
                   tmp=arr[j];
                   arr[j]=arr[j+1];
                   arr[j+1]=tmp;
                   flag=1;
               }
           }
           if(flag==0)break;
       }
    }

插入排序

基本思想:将待排序的元素依次插入到已排好序的队列中,直到所有元素插入完毕,则整个数列有序(刚开始的时候第一个元素有序)。
在这里插入图片描述
代码实现:

 /**  2,插入排序   */
    public static void InsertSort(int[] arr){
        //外层循环:遍历待插入的所有数组元素
        //内层循环:将外层循环本轮选择的元素与排好序的元素相比较
        for(int i=1;i<arr.length;i++){
            int tmp=arr[i];  //先将本次要插入的元素存起来
            int j=0;
            for(j=i-1;j>=0;j--) {
                if (tmp < arr[j]) {
                    arr[j+1]=arr[j];
                    continue;
                }
                if(tmp>=arr[j]){
                   break;
                }
            }
            arr[j+1]=tmp;
        }
    }

快速排序
在这里插入图片描述

 /**  3,快速排序
     * 思想:递归,分治
     * */

    public static void FastSort(int[] arr, int start,int end){
        if(start>=end){
            return;
        }
        //基准元素位置
         int baseIndex=partition(arr,start,end);
         FastSort(arr,start,baseIndex-1);
        FastSort(arr,baseIndex+1,end);
    }
    private static int partition(int[] arr,int start,int end) {
        int left = start;
        int right = end;
        int base = arr[start];  //将基准元素存起来
        int pit = start;  //坑的位置
        while (left <= right) {
            while (left <= right) {
                if (arr[right] <= base) {
                    arr[left] = arr[right];
                    pit = right;
                    left++;  //注意,填坑之后,指针要向前走
                    break;
                }
                right--;
            }

            while (left <= right) {
                if (arr[left] >= base) {
                    arr[right] = arr[left];
                    pit = left;
                    right--;
                    break;
                }
                left++;
            }
        }
        arr[pit]=base;
        return pit;
    }

选择排序

思想:每次从待排序的数据元素中选出最小(或最大)的一个元素,存放在数列的起始位置,直到全部待排序的数据元素排完。
在这里插入图片描述

 /**  4,选择排序   */
    public static void ChooseSort(int[] arr){

        for(int i=0;i<arr.length;i++){
            int min=i;//注意:min不能一直取一个值,因为每层内循环结束后前面的已经是最小值了,若min不变,则无法再找出较小值
            int tmp=arr[i];
            for(int j=i+1;j<arr.length;j++){
                if(arr[j]<arr[min]){
                    min=j;
                }
            }
            arr[i]=arr[min];
            arr[min]=tmp;
        }

    }

希尔排序
在这里插入图片描述

    /**  5,希尔排序
     * 思想:取一个整数gap(刚开始一般取arr.length/3+1)将待排序数组从第一个元素开始每隔gap个数分成一组,
     *       共分n组,然后将每一组进行插排 ,一趟排序结束后,gap值减小(一般取gap=gap/3+1),继续上述步骤
     * */
    public static void ShellSort(int[] arr,int size){
        int gap=size;
       while(true) {
           gap=gap/3+1;
           shellInsert(arr,size,gap);
           if(gap==1){
              break;
           }
       }
    }
   //一次排序
    private static void shellInsert(int[] arr,int size,int gap){
        for(int x=0;x<gap;x++) {
            for (int i = gap+x; i < arr.length; i += gap) {
                int tmp = arr[i];  //先将本次要插入的元素存起来
                int j = 0;
                for (j = i - gap; j >= 0; j -= gap) {
                    if (tmp < arr[j]) {
                        arr[j + gap] = arr[j];
                        continue;
                    }
                    if (tmp >= arr[j]) {
                        break;
                    }
                }
                arr[j + gap] = tmp;
            }
        }
    }

堆排序
堆排序的流程图如下:假设数组元素为arr[]={4,2,6,3,8,5,7,10,9},先将数组构建成一个大顶堆,再将根节点与最后一个叶子节点交换,完了之后将此叶子节点删除(用黑色表示),接着将堆向下调整为大顶堆,重复上述操作,直到所有节点删除完毕(注意:此处的删除不是真正的删除,只是将堆的节点个数减1,方便下次交换时交换到倒数第n个节点)。再将前其层序遍历即可。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最后再将其层序遍历得到
在这里插入图片描述
至此堆排序就完成了。
代码实现如下:

  /**  6,堆排序
     * 思想:将数组构建成大顶堆,取出最大元素与最后一个叶子节点交换之后删除,调整堆为大顶堆循环操作,最后层序遍历
     *   */
    //堆排序
    public static void HeapSort(int[] arr,int length){
         BuildHeap(arr);
         for(int i=length-1;i>0;i--){
             int tmp=arr[0];
             arr[0]=arr[i];
             arr[i]=tmp;
             DownAdjust(arr,0,i);
         }
    }
    //构建堆
    private static void BuildHeap(int[] arr){
         for(int i=(arr.length-2)/2;i>=0;i--){
             DownAdjust(arr,i,arr.length);
         }
    }
    //向下调整
    private static void DownAdjust(int[] arr,int index,int length){
        int childIndex=index*2+1;
        int tmp=arr[index];
        while(childIndex<length){
            if(childIndex+1<length && arr[childIndex]<arr[childIndex+1]){
                    childIndex=childIndex+1;
            }
            if(arr[childIndex]<=tmp) {
                break;
            }
            arr[index]=arr[childIndex];
            index=childIndex;
            childIndex=index*2+1;
        }
        arr[index]=tmp;  //注意,走到这一步时,若循环是正常结束, arr[index]已经是叶子节点了
    }

归并排序
思想:将序列不断划分更小的子序列,当子序列长度为1时,再将相邻两个子序列排序合并,层层往上,最终使整个序列有序。
原理如图:
在这里插入图片描述
代码如下:

    /**  7,归并排序
     * 思想:分治法(先使每个子序列有序,再使子序列段间有序)
     * */
    //先分解
    private static void resolve(int[] arr,int left,int right){
        int mid=left+(right-left)/2;
        if(left<right){
            resolve(arr,left,mid);
            resolve(arr,mid+1,right);
            MergerSort(arr,mid,left,right);
        }
    }
    //再合并
    public static void MergerSort(int[] arr,int mid,int left,int right){
        int[] brr=new int[right-left+1];
        int i=left;
        int j=mid+1;
        int n=0;
        //两个有序数组合成一个有序数组
        while(i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                brr[n]=arr[i];
                i++;
                n++;
            }
            if(arr[i]>arr[j]){
                brr[n]=arr[j];
                j++;
                n++;
            }
        }
        while(i<=mid){  //注意:等号不可没有
            brr[n++]=arr[i++];
        }
        while(j<=right){
            brr[n++]=arr[j++];
        }
        //新合成的有序数组覆盖掉原来的数组(如果不覆盖原数组将没变化)
        for(int k=0;k<brr.length;k++){
            arr[k+left]=brr[k];
        }
    }

计数排序

思想:假设数列为 a[]={9,3,5,4,9,1,2,7,8,1,3,6,5,3,4,0,10,9};
由于数列取值范围在0~10之间,因此可以开辟一个大小为11的数组B,B的下标对应a的数组元素,而a中某一元素的个数对应B数组对应下标的元素值,比如数组a中元素为9的共3个,则B[9]=3;最终遍历B数组打印B[i]个i即可;

代码如下:

  /**  8,计数排序
     * 思想:根据A数组元素的范围创建一个B数组,其下标值对应A数组的元素值 ,
     *      遍历A数组将其对应的元素个数统计出来赋值给B数组下表对应的元素,
     *     最后遍历B数组打印输出B[i]个i(可根据最大元素与最小元素的差进行改进)
     * 适用:数组元素分布范围较小
     * */
    public static void BaseSort(int[] arr){
        int max=0,min=arr[0];
         for(int i=0;i<arr.length;i++){
             if(arr[i]>max){
                 max=arr[i];
             }
             if(arr[i]<min){
                 min=arr[i];
             }
         }
         int L=max-min;
         int[] brr=new int[max-min+1];
         for(int i=0;i<arr.length;i++){
           brr[arr[i]-min]++;
         }
         for(int i=0;i<brr.length;i++){
             for(int j=0;j<brr[i];j++){
              System.out.print((i+min)+" ");
             }
         }
    }

总结:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值