几种常见的Java排序算法

几种常见的Java排序算法

  • 一、插入排序
  • 二、希尔排序
  • 三、冒泡排序
  • 四、选择排序
  • 五、堆排序
  • 六、快速排序
  • 七、归并排序


本文介绍了Java中几种常见的排序算法
1.插入排序(插入排序,希尔排序)
2.交换排序(冒泡排序,快速排序)
3.选择排序(选择排序,堆排序)
4.归并排序

一、插入排序

插入排序属于内部排序法,是对内部欲排序的元素以插入的方式移动到合适的位置
即把所有的元素看成两部分,一部分是有序的,另外一部分是无序的,刚开始有序的部分为一个元素,而无序的部分则为n-1个元素,排序的时候将无序序列中第一个元素和有序队列进行比较,将其放到合适的位置,形成新的有序表。

 //插入排序
public static void insertionSort(int []array){
        for(int i=1;i<array.length;i++){
            int tmp=array[i];
            int j=i-1;
            for(;j>=0;j--){
                if(array[j]>tmp){//
                    array[j+1]=array[j];
                }else {
                    break;
                }
            }
            array[j+1]=tmp;
        }
    }

插入排序的平均时间复杂度是O(n^2) 最好情况是O(n)最坏情况也是O(n^2),空间复杂度是O(1),稳定性 :稳定

二、希尔排序

希尔排序就是优化的插入排序,将一组数据分成n组,之后再组内进行交换即可,
给定组的值可以为固定的值,一般都为数组长度除二

 public static void shellSort(int []array){
        int []drr={5,2,1};
        for (int i = 0; i <drr.length ; i++) {
            shell(array,drr[i]);
        }
    }
    public static void shell(int []array,int gap){
        for(int i=gap;i<array.length;i++){
            int tmp=array[i];
            int j=i-gap;
            for(;j>=0;j=j-gap){
                if(array[j]>tmp){
                    array[j+gap]=array[j];
                }else {
                    break;
                }
            }
            array[j+gap]=tmp;
        }
    }

希尔排序的平均时间复杂度为O(n^1.3~1.5),最好情况是O(n),最坏情况是n平方 。空间复杂度是O(1)。
稳定性: 不稳定。

三、冒泡排序

优化冒泡排序就是插入一个boolean变量检查是否交换,如果没有交换说明已经有序即退出。

 public static void bubbleSort(int []array){
        for(int i=0;i<array.length-1;i++){
            boolean flg=false;
            for(int j=0;j<array.length-1-i;j++){
                if(array[j]>array[j+1]){
                    int tmp=array[j];
                    array[j]=array[j+1];
                    array[j+1]=tmp;
                    flg=true;
                }
            }
            if(flg==false){
                break;
            }
        }
    }

冒泡排序时间复杂度为O(n^2) 最好情况是O(n)即数组就是有序的 遍历一边没有交换元素。空间复杂度为O(1)稳定性:稳定

四、选择排序

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

选择排序的时间复杂度最好最坏情况都是O(n^2) 空间复杂度为O(1), 稳定性:不稳定

五、堆排序

堆排序就是先建立一个大堆,大堆的每一个子树的根都是最大的,然后尾巴元素和根交换,之后重新建大堆,再次找到最大的数放到根位置,继续交换即可

//堆排序 从小到大排序 应该是建大堆(能知道最上面是最大的)
    public static void heapSort(int []array){
        createHeap(array);
        int end=array.length-1;
       // while(){//循环 建立大堆 每次都是头最大 交换 尾巴节点
        while (end>0){
            int tmp=array[0];
            array[0]=array[end];
            array[end]=tmp;
            adjust(array,0,end);
            end--;
        }
        }
    public static void adjust(int []array,int parent,int len){
        int child=2*parent+1;
        while(child<len){
            if(child+1<len&&array[child+1]>array[child]){
                child++;
            }
            if(array[child]>array[parent]){
                int tmp=array[parent];
                array[parent]=array[child];
                array[child]=tmp;
                parent=child;
                child=2*parent+1;
            }else {
                break;
            }
        }
    }
    public static void createHeap(int []array){
        for(int p=(array.length-1-1)/2;p>=0;p--){
            adjust(array,p,array.length);
        }
    }

堆排序的时间复杂度为O(nlogn)空间复杂度为O(1) 稳定性:不稳定

六、快速排序

快速排序是一种非常高效的排序算法,它的实现,增大了记录和比较和移动的距离,从而减少总的比较此时和移动次数。采用分而治之的思想,将一个大的问题拆成一个小的问题,小的问题拆成更小的问题。

public static void quickSort(int []array,int low,int high) {
        if(low>=high){
            return;
        }
        int left=low;
        int right=high;
        int base = array[low];
        while (left!=right) {//从后面开始检索 遇到比基准数小的就停下,遇到比基准数大于等于的就继续检索
            while (array[right]>=base&&left<right) {//left小于right 防止越界 比如数组内所有元素都比base小就会一路走下去
                right--;
            }
            while (array[left] <= base&&left<right) {
                left++;
            }
          
            int temp=array[left];
            array[left]=array[right];
            array[right]=temp;
        }
        //交换基准值和相遇位置的值
        array[low]=array[left];//相遇的值一定小于基准值
        array[left]=base;
        quickSort(array,low,left-1);
        quickSort(array,left+1,high);
    }

快速排序
时间复杂度最好情况是都能分割成较完美的两部分 O(nlog(n)),最坏情况是数组是有序的每次分割只有一边 O(n^2)
空间复杂度为O(nlog(n)) 稳定性:不稳定
快速排序再最坏的情况下可以优化,即优化基准值
三数取中法即low mid high 取中间大小的数字为基准值

七、归并排序

归并排序采用分而治之思想,将序列分为子序列,将子序列有序,再将两个有序的子序列合并成新的序列。

public static void mergeSort(int []array){
    mergeSortRec(array,0,array.length-1);
    }
    public static void mergeSortRec(int []array,int low,int high){//递归 分解
        if(low>=high){
            return;
        }
        int mid=(high+low)>>>1;
        mergeSortRec(array,low,mid);
        mergeSortRec(array,mid+1,high);
        merge(array,low,mid,high);//合并

    }
    public static void merge(int []array,int low,int mid,int high){//合并
        int[]tmparr=new int[high-low+1];
        int k=0;
            int s1=low;
            int s2=mid+1;
     while (s1<=mid&&s2<=high){
         if(array[s1]<array[s2]){//合并二个数组
             tmparr[k]=array[s1];
             k++;
             s1++;
         }else {
             tmparr[k]=array[s2];
             k++;
             s2++;
         }
     }
     while (s1<=mid){//如果后面的数组结束了,前面的数组还有元素就放到新数组中
          tmparr[k]=array[s1];
         k++;
         s1++;
     }
     while (s2<=high){
         tmparr[k]=array[s2];
         k++;
         s2++;
     }
        for (int i = 0; i <tmparr.length ; i++) {
            array[i+low]=tmparr[i]; //注意赋值时不能把原来的数组值覆盖
        }
    }

归并排序的时间平均(最好,最坏)复杂度都为O=(nlog(n)) 空间复杂度为O(n),稳定性: 稳定

你可能感兴趣的:(笔记)