排序算法(java)

在平均情况下,快速排序最快;
在最好情况下,插入排序和冒泡排序最快;
在最坏情况下,堆排序和归并排序最快。

一.选择排序

时间复杂度:O(n²)

从数组中选择最小元素,将它与数组的第一个元素交换位置。再从数组剩下的元素中选择出最小的元素,将它与数组的第二个元素交换位置。不断进行这样的操作,直到将整个数组排序。

   public static int[] SelectionSort(int arr[]){   
        for(int i=0;i<arr.length-1;i++){
            int min=i;
            for (int j=i+1;j<arr.length;j++){
                if(arr[j]<arr[min])
                    min=j;
            }
            arr=Exchange(arr,min,i);
        }
        return arr;
    }

public static int[] Exchange(int arr[],int a,int b){  //交换两个数
        int flag=arr[a];
        arr[a]=arr[b];
        arr[b]=flag;
        return arr;
    }

二.冒泡排序

时间复杂度 :O(n²)

比较相邻的元素。如果第一个比第二个大,就交换他们两个
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

   public static int[] BubbleSort(int arr[]){   
        for(int i=0;i<arr.length-1;i++){
            for(int j=1;j<arr.length-i;j++){
                if(arr[j]<arr[j-1])
                    arr=Exchange(arr,j,j-1);
            }
        }
        return arr;
    }

   public static int[] Exchange(int arr[],int a,int b){  //交换两个数
        int flag=arr[a];
        arr[a]=arr[b];
        arr[b]=flag;
        return arr;
    }

三.插入排序 

时间复杂度:O(n²)

将数组分成两部分, 一部分是已经排好的, 另一部分挨个访问, 插入到前一部分合适的地方

    public static int[] InsertionSort(int arr[]) {    
        for (int i = 1; i < arr.length ; i++) {
            for (int j = i-1; j >= 0 && arr[j] > arr[j+1]; j--) {
                arr=Exchange(arr,j,j+1);
            }
        }
        return arr;
    }

       public static int[] Exchange(int arr[],int a,int b){  //交换两个数
        arr[a]=arr[a]^arr[b];
        arr[b]=arr[a]^arr[b];
        arr[a]=arr[a]^arr[b];   //选择排序不能用,a=b时arr[a]=arr[b],指向同一个,方法错误
        return arr;
    }

四.归并排序  

时间复杂度:O(N*log2N)  

用递归方法,取中点,左右分别排序(详细见注释)
  public static int[] MergeSort(int arr[],int left,int right){ 
        int mid=(left+right)/2;
          if (left==right){  //递归出口
              return arr;
          }
          MergeSort(arr,left,mid);  //左部分使用归并方法
          MergeSort(arr,mid+1,right); //右部分使用归并方法
          Merge(arr,mid,right,left);  //递归调用
          return arr;
    }

    public static int[] Merge(int arr[],int mid,int right,int left){  //  归并方法        
       int tmp[]=new int[right-left+1];  //中介数组
       int i=0;  //中介数组的指针
       int leftStart=left,leftEnd=mid,rightStart=mid+1,rightEnd=right;//左右部分的头末节点
          while(leftStart<=leftEnd&&rightStart<=rightEnd){  //判断左右部分所在指针哪个数小,数小的赋值到中介数组中,直到左右任一部分到达末尾
              if (arr[leftStart]<=arr[rightStart]){
                  tmp[i++]=arr[leftStart++];
              }else
                  tmp[i++]=arr[rightStart++];
          }
          while(leftStart<=leftEnd){  //如果右部分到达了末尾,但左部分还没到的情况
              tmp[i++]=arr[leftStart++];
          }
          while(rightStart<=rightEnd){  //如果左部分到达了末尾,但右部分还没到的情况
              tmp[i++]=arr[rightStart++];
          }
          for(int j=0;j<i;j++){    //将tmp中介数组赋值回原数组中
              arr[left+j]=tmp[j];
          }
          return arr;
    }

 五.快速排序

时间复杂度:O(N*log2N)  

将数组最后一个数与数组中随机一个数互换(为了绝对随机,防止特殊情况),使用左右边界,将比互换后最后一个数小的放在左边,大的放在右边,相等的在中间(并不是完全排好序),再将最后一个数与右边界的数互换,这样中间部分就排好序了,再递归执行,将数组所有部分排好序(详细见注释)
 public static int[] QuickSort(int arr[],int left,int right){
          if (left>=right){   //递归出口
              return arr;
          }
        Exchange(arr,left+(int)(Math.random()*(right-left+1)),right);  //数组最后一个数与left和right之间的随机一个数互换((int)Math.random()*N  代表取【0,N-1】范围的一个随机整数)
          int tmp[]=Partition(arr,left,right);  //tmp[0]代表排好序范围的左节点 tmp[1]代表排好序范围的右节点
          QuickSort(arr,left,tmp[0]-1);  //左部分递归调用
          QuickSort(arr,tmp[1]+1,right);  //右部分递归调用
          return arr;
    }


    public static int[] Partition(int arr[],int left,int right){
        int leftp=left-1;  //左边界
        int num=right;   //最后一位数,都需要跟此数比大小
        int rightp=right; //右边界
        while(left<rightp){  //left为当前要判断的数的指针
            if (arr[left]<arr[num]){  //当前要判断的数小于num的情况
                Exchange(arr,left++,++leftp);  //左边界后移,然后交换左边界的数和判断的数 指针+1
            }else if (arr[left]>arr[num]){//当前要判断的数大于num的情况
                Exchange(arr,left,--rightp); //右边界前移,然后交换右边界的数和判断的数 指针不动
            }else{ //当前要判断的数等于num的情况
                left++;  //左右边界都不动,指针+1
            }
        }
        Exchange(arr,rightp,num); //交换右边界的数和最后一位数
        int tmp[]=new int[2];  //用于返回排好序的左右节点的中介数组
            tmp[0]=leftp+1; //排好序的左节点
            tmp[1]=rightp;  //排好序的右节点
        return tmp;
    }

    public static int[] Exchange(int arr[],int a,int b){  //交换两个数
        int flag=arr[a];
        arr[a]=arr[b];
        arr[b]=flag;
        return arr;
    }

六.堆排序 

未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值