Java中的7种排序

冒泡排序

冒泡排序的思想就是就是相邻的两个依次比较,如果是升序:总是先将最大的放在最后,然后是第二大放在倒数第二的位置,依次往下重复.
时间复杂度:O(N^2)
空间复杂度:O(1);
稳定性:稳定

  public static void bubbleSort(int[] arr){
                for(int i = 0 ; i < arr.length-1; i++){
                  //设置一个标志位
                    boolean flag = false;
                     for(int j = 0 ; j < arr.length- i -1 ; j++){
                          if(arr[j] > arr[j+1]){
                              int temp = arr[j];
                              arr[j] = arr[j+1];
                              arr[j+1] = temp;
                              flag = true;
                          }
                     }
                     //如果标志位为false证明没有发生交换(此时数组及时有序的了,直接break;)
     
                     if(flag == false){
                         break;
                     }
                }
  }

选择排序

选择排序的思想是将当前元素和他后面的元素相比较,如果是升序排序可以发现总是将小的往前面放(第一小在数组第一个位置,第二小在数组第二的位置…).
时间复杂度:O(N^2)
空间复杂度:O(1);
稳定性:不稳定

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

直接插入排序

直接插入排序的思想就是就是先将当前元素插入进来,如果是升序排序,判断当前插入元素是否比他前面的小,如果小就让比它大的元素往后面走,直到碰到比插入元素小的元素,将它插入到比它小的前面.
时间复杂度 : 最好情况下:当数据有序的时候,O(n) 当数据越有序越快 , 最坏情况下:当数据逆序的时候,可以达到O(n^2)
空间复杂度 : O(1)
稳定性 : 不稳定

public static void insertSort(int[] arr){
        for(int i = 1 ; i < arr.length ;i++){
            int temp = arr[i];
            int j = i-1;
            for(;j>=0;j--){
                if(temp < arr[j]){
                    arr[j+1] = arr[j];
                }else{
                    break;
                }
            }
            arr[j+1] = temp;
        }
    }

希尔排序

希尔排序又叫做缩小增量排序,其本质还是插入排序,是对直接插入排序的一种优化版本,只是在将待排序序列按照某种规则分成几个子序列,分别对这几个子序列进行直接插入排序,这个规则的体现就是增量的选取,如果选择增量为1那么就是直接插入排序。而希尔排序的每一趟排序都会使整个序列变得有序,等到整个序列有序了,那么再使用增量为1的插入排序的话那么就会使得排序的效率提高
时间复杂度:O(n*logN)
空间复杂度:O(1);
稳定性:不稳定

 	public static void shellSort(int[] arr){
         int gap = arr.length >>>1;
         while(gap>1){
             shell(gap,arr);
             gap = gap>>>1;
         }
         shell(1,arr);
    }
    public static void shell(int gap , int[] arr){
        for(int i = gap ; i < arr.length ; i++){
                int temp = arr[i];
                int  j = i-gap;
                for(;j >= 0 ; j-=gap){
                     if(temp < arr[j]){
                         arr[j+gap] = arr[j];
                     }else{
                         break;
                     }
                }
                arr[j+gap] = temp;
        }
    }

堆排序

如果是升序排序,就建大根堆,如果是降序排序,就建小根堆,建堆完成之后,通过根节点与最后一个节点的交换实现排序过程.
时间复杂度: O(N*logN);
空间复杂度: O(1);
稳定性:不稳定
我们以升序排序为例:

//建立大根堆
    public static void createHeap(int[] arr){
        for(int i = (arr.length-1-1)/2; i>= 0 ; i--){
               adjustDown(i,arr,arr.length);
        }
    }
    //向下调整
    public static void adjustDown(int p , int[] arr,int len){

        int child  = 2*p+1;
        while(child<len){
              if(child+1 < len && arr[child+1] >arr[child]){
                  child++;
              }
              if(arr[child] > arr[p]){
                  int tmp = arr[child];
                  arr[child] = arr[p];
                  arr[p] = tmp;
                  p = child;
                  child = 2*p+1;
              }else{
                  break;
              }
        }
    }
    public static  void heapSort(int[] arr){
            createHeap(arr);
            int len = arr.length;
            while(len-1 > 0){
                     int tmp = arr[0];
                     arr[0] = arr[len-1];
                     arr[len-1] = tmp;
                     len--;
                     adjustDown(0,arr,len);
            }
    }

快速排序

快速排序的思想是先以数组的低位为基准,(以升序排序为例)比它大的后边放,比它小的往前边放,然后将它基准元素放入中间位置,此时就有基准左边的一组数组(都是比基准小的),和基准右边的一组数据(都是比基准数据大的),然后每组数据重复相同的动作,每组又会被分成两个组,直到每组只有一个数据时,这个数组就是有序的了.
时间复杂度:O(N*logN)
空间复杂度:O(1)
稳定性:不稳定
递归写法:

 public static int partion(int[] arr,int low , int end){
        int tmp = arr[low];
        while(low< end){
            while(low < end && tmp <= arr[end]){
                 end--;
            }
            arr[low] = arr[end];
            while(low < end && tmp >=arr[low]){
                low++;
            }
            arr[end] = arr[low];
        }
        arr[low] = tmp;
        return low;
    }
    public static void  quickSort(int[] arr,int low , int end){

        if(low<end){
            int partion = partion(arr, low, end);
            quickSort(arr,low,partion-1);
            quickSort(arr,partion+ 1,end);
        }
    }

非递归写法:

  public static void  noRecQuickSort(int[] arr){
        Stack<Integer> stack =  new Stack<>();
        int low = 0 ;
        int high = arr.length-1;
        int par = partion(arr, low, high);
        //1、分别判断 左右两边是否有两个元素以上,包含两个元素
        //左边有2个元素以上
        if(par > low+1) {
            // 左边有2个元素以上
            stack.push(low);
            stack.push(par-1);
        }
        //右边有2个元素以上
        if(par < high-1) {
            stack.push(par+1);
            stack.push(high);
        }
        while(!stack.empty()){
           high= stack.pop();
            low= stack.pop();
            par = partion(arr, low, high);
            if(par > low+1) {
                //入栈:
                stack.push(low);
                stack.push(par-1);
            }
            //右边有2个元素以上
            if(par < high-1) {
                stack.push(par+1);
                stack.push(high);
            }

        }
    }

归并排序

归并排序使用的是分治的思想基本思想:将待排序元素分成大小大致相同的2个子集合,分别对2个子集合进行排序,最终将排好序的子集合合并成为所要求的排好序的集合。
时间复杂度:O(N*logN)
空间复杂度:O(N)
稳定性:稳定
递归写法:

 public static  void mergeSort(int[] arr,int low , int high){
                if(low >=high){
                    return;
                }
                int mid = (low+high)>>>1;
                 mergeSort(arr,low,mid);
                 mergeSort(arr,mid+1,high);
                 //合并
                 merge(arr,low,mid,high);
    }
    public static void merge(int[] arr,int low , int mid ,int high){
          int[] tmp =   new int[high-low+1];
          int i = 0;
           int s1 = low;
           int s2 = mid+1;
           int e1 = mid ;
           int e2 = high;
           while(s1 <= e1 && s2 <= e2){
                if(arr[s1] <= arr[s2]){
                    tmp[i++] = arr[s1++];

                }else{
                    tmp[i++] = arr[s2++];

                }
           }
           while(s1 <= e1){
               tmp[i++] = arr[s1++];
           }
           while(s2 <= e2){
            tmp[i++] = arr[s2++];
           }
           for(int k = 0 ; k < tmp.length ; k++){
               arr[k+low] = tmp[k];
           }
    }

非递归写法:

 public static void mergeSort2(int[] arr){
        for(int gap = 1 ; gap < arr.length;gap*=2){
            merge2(gap , arr);
        }
    }
    public static void merge2(int gap , int[] arr){
        int[] tmp =   new int[arr.length];
        int i = 0;
         int s1 = 0;
         int e1 = s1+gap-1;
         int s2 = e1+1;
         int e2 = s2+gap-1 >= arr.length ? arr.length-1:s2+gap-1;
         while(s2 < arr.length){
             //保证两个段都有元素
             while(s1 <= e1 && s2 <= e2){
                 if(arr[s1] <= arr[s2]){
                     tmp[i++] = arr[s1++];

                 }else{
                     tmp[i++] = arr[s2++];

                 }
             }
             while(s1 <= e1){
                 tmp[i++] = arr[s1++];
             }
             while(s2 <= e2){
                 tmp[i++] = arr[s2++];
             }
             s1 = e2+1;
             e1 = s1+gap-1;
             s2 = e1+1;
             e2 = s2+gap-1 >= arr.length ? arr.length-1:s2+gap-1;
         }
         while(s1 < arr.length){
            tmp[i++] = arr[s1++];
        }
         for(int k = 0 ; k < tmp.length ; k++){
             arr[k] = tmp[k];
         }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值