各种排序算法总结

排序算法的整理:在这里插入图片描述

排序算法的评价标准主要是从两方面:1.时间复杂度2.空间复杂度
稳定排序算法只有三种:也就是 冒泡排序,归并排序,以及直接插入排序
插入排序:每一趟将一个待排序的记录,按其关键字的大小插入到已经排序好一组记录的适当位置,直到所有待排序记录全部插入为止;

    public static void charusort(int[] arr){
        int temp,j;
        for(int i=1;i<arr.length;i++){
            if(arr[i]<arr[i-1]){
                temp=arr[i];
                arr[i]=arr[i-1];
//                arr[i-1]=temp;
                //从后往前寻找第一个比它小的元素,将其往后移,然后将该元素插入到空闲的位置
                for(j=i-1;j>=0&&arr[j]>temp;j--){
                    arr[j+1]=arr[j];
                }
                arr[j+1]=temp;
                System.out.println("第"+i+"趟排序的结果是:"+ Arrays.toString(arr));
            }
        }
    }

插入排序又可以分为三种:
直接插入排序,折半插入排序以及希尔排序。
下面依次介绍这三种排序:
直接插入排序:其时间复杂度为O(n2),空间复杂度为O(1);
比较适合于链式结构,无需移动位置,只需移动指针即可;(如果使用顺序结构存储数据的话 适用于有序数组)
折半插入排序:其主要是在查找的过程中,不是按照直接插入排序一般,主要耗时在关键字的比较上,因此这种排序适合无序的数组进行排序;
交换排序:又包括冒泡排序和快速排序
冒泡排序:常见的冒泡排序算法以及其优化

package com.study.exer;

public class Maopao {
    public static void main(String[] args){
        int[] arr=new int[]{8,5,7,6,4,3,1,2};
        Bubblesort(arr,0,arr.length-1);
        for(int i=0;i<arr.length;i++){
            if(i!=arr.length-1){
                System.out.print(arr[i]+" ");
            }else{
                System.out.print(arr[i]);
            }
        }
    }
    public static void Bubblesort(int[] arr,int left,int right){
    //设置一个变量用来标记是否已经交换过
    //是因为当数据基本有序的时候  如果没有交换过的话就不需要对其进行排序,直接跳出得到排序后的结果;
        boolean flag=false;
        int temp;
        for(int i=0;i<arr.length-1;i++){
            for(int j=0;j<arr.length-1-i;j++){
                if(arr[j]>arr[j+1]){
                    flag=true;
                    temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
            if(!flag){
                break;
            }else{
                flag=false;
            }
        }
     }
}

快速排序:基本思想:就是选定pivot中心轴,将大于pivot的关键字放在pivot的右边,将小于pivot的关键字放在其左边,分别再对左右子序列重复前面的步骤;最坏时间复杂度是O(n2),也就是排序列表基本有序的时候,所以最坏情况下的空间复杂度也为O(n)

public class Partitionsort {
    public static void main(String[] args){
        int[] arr=new int[]{8,5,7,6,4,3,1,2};
        Quicksort(arr,0,arr.length-1);
        for(int i=0;i<arr.length;i++){
            if(i!=arr.length-1){
                System.out.print(arr[i]+" ");
            }else{
                System.out.print(arr[i]);
            }
        }
    }
    public static void Quicksort(int[] arr,int left,int right){
        if(left<right){
            int pivot=partition(arr,left,right);
            Quicksort(arr,left,pivot-1);
            Quicksort(arr,pivot+1,right);
        }
    }
    public static int partition(int[] arr,int left,int right){
        //一般都选择第一个数字为枢轴数字
        int pivot_1=arr[left];
        while(left<right){
            while(left<right&&arr[right]>=pivot_1) right--;
            arr[left]=arr[right];
            while(left<right&&arr[left]<pivot_1)left++;
            arr[right]=arr[left];
        }
        arr[left]=pivot_1;
        return left;
    }
}

基于上述的最坏时间复杂度下,所以考虑对快排进行优化:也就是根据三数取中法,主要思想是取合适的枢轴元素,取left,mid,right中关键字居中的数作为枢轴元素并将其放置到元素末尾,然后依次进行比较从左开始找到第一个比枢轴大的数,从右开始找到第一个比枢轴小的元素,然后将其进行交换,并将枢轴数放置到合适的位置上;代码如下:

package com.study.exer;

public class QuickSort_youhua {
    public static void main(String[] args){
        //s三数取中法
        int[] arr=new int[]{8,4,5,7,1,3,6,2};
//        Runtime cur= getRuntime();
        Quicksort(arr,0,arr.length-1);
        for(int i=0;i<arr.length;i++){
            if(i!=arr.length-1){
                System.out.print(arr[i]+" ");
            }else{
                System.out.print(arr[i]);
            }
        }
    }
    public static void Quicksort(int[] arr,int left,int right){
        if(left<right){
            dealPivot(arr,left,right);
            //获取枢轴元素
            int pivot=right-1;
            int i=left,j=right-1;
            while(true){
                while(arr[++i]<arr[pivot]){

                }
                while(j>left&&arr[--j]>arr[pivot]){}
                if(i<j){
                    swap(arr,i,j);
                }else{
                    break;
                }
            }
            if(i<right){
                swap(arr,i,right-1);
            }
            Quicksort(arr,left,i-1);
            Quicksort(arr,i+1,right);
        }

    }
    public static void dealPivot(int[] arr,int left,int right){
        int mid=(left+right)/2;
        //选取三者中的最大值;也就是通过相应的数组的交换
        if(arr[left]>arr[mid]){
            swap(arr,left,mid);
        }
        if(arr[left]>arr[right]){
            swap(arr,left,right);
        }
        if(arr[mid]>arr[right]){
            swap(arr,mid,right);
        }
        //也就是将枢轴元素放在最后一位;
        swap(arr,mid,right-1);
    }
    public static void swap(int[] arr,int a,int b){
        int temp=arr[a];
        arr[a]=arr[b];
        arr[b]=temp;
    }
}

选择排序又分为简单选择排序和堆排序两种:
**简单选择排序:**其基本思想是每一趟从待排序的数组中选出关键字最小的记录,按顺序放在已经排好序的记录序列的最后,直到全部排完为止;

public static void selectsort(int[] arr){
    int temp,index;
    for(int i=0;i<arr.length;i++){
        temp=arr[i];
        index=i;
        for(int j=i+1;j<arr.length;j++){
            if(temp>arr[j]){
                temp=arr[j];
                index=j;
            }
        }
        if(index!=i){
            arr[index]=arr[i];
            arr[i]=temp;
        }
    }
}

简单选择排序的优化,其主要思想是每次可以找到最小值也可以找到最大值;这样的话其整体的找的时间会减少到一半

public static void selectsort(int[] arr){
        int left=0,right=arr.length-1;
        int min,max,minindex,maxindex,temp;
//        int min=arr[left],max=arr[right];
        for(int i=0;i<arr.length/2;i++){
            min=arr[left];
            max=arr[right];
            minindex=left;
            maxindex=right;
            if(min>max){
                temp=arr[left];
                arr[left]=arr[right];
                arr[right]=temp;
                min=arr[left];
                max=arr[right];
            }
            for(int j=left+1;j<right;j++) {
                if (arr[j] < min) {
                    min = arr[j];
                    minindex = j;
                }
                if (arr[j] > max) {
                    max = arr[j];
                    maxindex = j;
                }
            }
                if(minindex!=left){
                    arr[minindex]=arr[left];
                    arr[left]=min;
                }
                if(maxindex!=right){
                    arr[maxindex]=arr[right];
                    arr[right]=max;
                }
            left++;
            right--;
            System.out.println("第"+i+"趟排序的结果为:"+ Arrays.toString(arr));
            }
        }

堆排序:

package com.study.exer;

import java.util.Arrays;

public class Heapsort {
    public static void main(String[] args) {
        int[] arr=new int[]{8,5,7,6,4,3,1,2};
        //首先建立大根堆或者小根堆,这里我选择建立大根堆,大根堆的定义就是  其每一颗左子树及其右子树的值都小于根节点的值
        //从最后一个非叶子节点开始;
        for(int i=arr.length/2-1;i>=0;i--){
            heapadjust(arr,i,arr.length);
        }
        for(int i=arr.length-1;i>0;i--){
            int temp=arr[i];
            arr[i]=arr[0];
            arr[0]=temp;
            heapadjust(arr,0,i);
            System.out.println("第"+i+"趟排序的结果是:"+ Arrays.toString(arr));
        }
        for(int i=0;i<arr.length;i++){
            if(i!=arr.length-1){
                System.out.print(arr[i]+" ");
            }else{
                System.out.print(arr[i]);
            }
        }
    }
    public static void heapadjust(int[] arr,int parent,int len){
        int temp=arr[parent];
        for(int j=2*parent+1;j<len;j=2*j+1){
            if(j+1<len&&arr[j+1]>arr[j]) ++j;
            //如果得到的数序需要对其左右脚进行交换,
            if(temp>=arr[j]) break;
            arr[parent]=arr[j];
            parent=j;
        }
        arr[parent]=temp;
    }
}

归并排序: 将两个或者两个以上的有序表合并成一个有序表的过程,它的思想是假设初始序列含有n个记录,每个子序列的长度为1,然后两两归并,得到[n/2]个长度为2或者1的有序子序列,再两两归并,如此重复直到得到一个长度为n的有序序列为止;
采用经典的分治法,
1.将序列中的待排序数组分为若干组,每个数字分为一组,将若干个数组两两合并,保证合并后的数组是有序的 3重复第二步操作直到只剩下一组,排序完成;
该算法的时间复杂度是O(nlogn) 其最好和最坏的时间复杂度都是O(nlogn);空间复杂度是O(n);
将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列;
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并

public class Guibingsort {
    public static void main(String[] args){
        int[] arr=new int[]{8,4,5,7,1,3,2,6};
        int[] temp=new int[arr.length];
        mergesort(arr,temp,0,arr.length-1);
        for(int i=0;i<arr.length;i++){
            if(i!=arr.length-1){
                System.out.print(arr[i]+" ");
            }else{
                System.out.print(arr[i]);
            }
        }
    }
    public static void mergesort(int[]arr,int[]temp,int left,int right){
        if(left<right){
            int mid=(left+right)/2;
            mergesort(arr,temp,left,mid);
            mergesort(arr,temp,mid+1,right);
            merge(arr,temp,left,mid,right);
        }
    }
    public static void merge(int[] arr,int[] temp,int left,int mid,int right){
        int i=left,j=mid+1,t=0;
        while(i<=mid&&j<=right){
            if(arr[i]<=arr[j]){
                temp[t++]=arr[i++];
            }else{
                temp[t++]=arr[j++];
            }
        }
        while(i<=mid) temp[t++]=arr[i++];
        while(j<=right) temp[t++]=arr[j++];
        //将新数组拷贝到原数组中
        t=0;
        while(left<=right){
            arr[left++]=temp[t++];
        }
    }
}

归并排序与快速排序的区别是:归并排序的递归是在函数一开始的时候,将数组分为两部分,这两部分数据有序之后再进行合并,此时整个数列是有序的,而对于快速排序来说是函数在结束的时候才进行递归,也就是先将一个元素放置到正确的位置,随后再以此位置为枢轴,排序其左右两部分;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值