程序员必须掌握!Java常用的8大排序算法

接着写。。。。。。

冒泡排序(最常见的也是都用的)
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比
较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序
要求相反时,就将它们互换。

程序员必须掌握!Java常用的8大排序算法

/*
 * 冒泡排序
 */
public class BubbleSort {
  public static void main(String[] args) {
    int[] arr={57,68,59,52};
    System.out.println("排序前数组为:");
    for(int num:arr){
      System.out.print(num+" ");
    }
    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]){
          int temp=arr[j];
          arr[j]=arr[j+1];
          arr[j+1]=temp;
        }
      }
    } 
    System.out.println();
    System.out.println("排序后的数组为:");
     for(int num:arr){
       System.out.print(num+" ");
     } 
  }
 }

快速排序
选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一
部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的
方法递归地排序划分的两部分。

程序员必须掌握!Java常用的8大排序算法

public class QuickSort {
    public static void sort(int a[], int low, int hight) {
        int i, j, index;
        if (low > hight) {
            return;
        }
        i = low;
        j = hight;
        index = a[i]; // 用子表的第一个记录做基准
        while (i < j) { // 从表的两端交替向中间扫描
            while (i < j && a[j] >= index)
                j--;
            if (i < j)
                a[i++] = a[j];// 用比基准小的记录替换低位记录
            while (i < j && a[i] < index)
                i++;
            if (i < j) // 用比基准大的记录替换高位记录
                a[j--] = a[i];
        }
        a[i] = index;// 将基准数值替换回 a[i]
        sort(a, low, i - 1); // 对低子表进行递归排序
        sort(a, i + 1, hight); // 对高子表进行递归排序
    }

   public static void quickSort(int a[]) {
        sort(a, 0, a.length - 1);
    }
    public static void main(String[] args) {
       int a[] = { 57, 68, 59, 62, 72, 28, 27, 96,33,24,19 };
        quickSort(a);
        System.out.println(Arrays.toString(a));
    }
}

归并排序
归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分
为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

程序员必须掌握!Java常用的8大排序算法

public static int[] sort(int[] a,int low,int high){
        int mid = (low+high)/2;
        if(low<high){
            sort(a,low,mid);
            sort(a,mid+1,high);
            //左右归并
            merge(a,low,mid,high);
        }
        return a;
    }
     
    public static void merge(int[] a, int low, int mid, int high) {
        int[] temp = new int[high-low+1];
        int i= low;
        int j = mid+1;
        int k=0;
        // 把较小的数先移到新数组中
        while(i<=mid && j<=high){
            if(a[i]<a[j]){
                temp[k++] = a[i++];
            }else{
                temp[k++] = a[j++];
            }
        }
        // 把左边剩余的数移入数组 
        while(i<=mid){
            temp[k++] = a[i++];
        }
        // 把右边边剩余的数移入数组
        while(j<=high){
            temp[k++] = a[j++];
        }
        // 把新数组中的数覆盖nums数组
        for(int x=0;x<temp.length;x++){
            a[x+low] = temp[x];
        }
    }

基数排序
将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开
始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。

程序员必须掌握!Java常用的8大排序算法

import java.util.LinkedList;
import java.util.Queue;
public class RadixSort {
    public int digit(int data,int m,int r){
        /*获取data的第m位数字,该数字为r进制*/
        int i,d;
        if(m==0) return data%r;
        d=r;
        for(i=1;i<m;i++){
            d=d*r;
        }
        return (data/d)%r;
    }
    public void radixSort(int array[],int n,int m,int r){
        /*数组array中存放关键字为m位的r进制数,数组大小为n*/
        int i,j,k;
        Queue[] que=new Queue[r];  //定义一个队列数组
        for( i=0;i<r;i++){    //初始化队列数组
            que[i]=new LinkedList<Integer>();
        }
        for(i=0;i<m;i++){ //进行m趟排序
            for(j=0;j<n;j++){
                k=digit(array[j], i, r);   //取出数组中第j个数的第i位的值
                que[k].add(array[j]);      //把数组中第j个数放入k对应的队列中
            }
            j=0;
            for(k=0;k<r;k++){    //把所有队列中的值取出,重新存入数组array中
                while(!que[k].isEmpty()){
                    array[j++]=(int) que[k].remove();
                }               
            }
            for(j=0;j<n;j++){   //输出每趟排序的结果
                System.out.print(array[j]+", ");
            }
            System.out.println();
        }
    }
    public static void main(String[] args) {
        /*使用基数排序法进行排序*/
        int array[]=new int[]{983,259,23,173,285,274,11,546,744,372};  //把待排序的数存放在数组中
        int n=array.length;
        RadixSort rs=new RadixSort();
        rs.radixSort(array, n, 3, 10);
    }
}

关于算法的复杂度详解

程序员必须掌握!Java常用的8大排序算法

算法的时间复杂度和空间复杂度合称为算法的复杂度。

时间复杂度
时间频度:一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。
但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费
的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句
执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。
时间复杂度:在刚才提到的时间频度中,n称为问题的规模,当n不断变化时,时间频度T(n)也会不
断变化。但有时我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。一般情况
下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),
使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。
记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。
时间频度不同,但时间复杂度可能相同。如:T(n)=n2+3n+4与T(n)=4n2+2n+1它们的频度不同,
但时间复杂度相同,都为O(n2)。按数量级递增排列,常见的时间复杂度有:常数阶O(1),对数阶
O(log2n),线性阶O(n), 线性对数阶O(nlog2n),平方阶O(n2),立方阶O(n3),..., k次方阶O(nk),指数
阶O(2n)。随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。
最坏时间复杂度和平均时间复杂度:最坏情况下的时间复杂度称最坏时间复杂度。一般不特别说
明,讨论的时间复杂度均是最坏情况下的时间复杂度。这样做的原因是:最坏情况下的时间复杂度
是算法在任何输入实例上运行时间的上界,这就保证了算法的运行时间不会比任何更长。
在最坏情况下的时间复杂度为T(n)=0(n),它表示对于任何输入实例,该算法的运行时间不可能大于
0(n)。平均时间复杂度是指所有可能的输入实例均以等概率出现的情况下,算法的期望运行时间。
空间复杂度
一个程序的空间复杂度是指运行完一个程序所需内存的大小。利用程序的空间复杂度,可以对程序
的运行所需要的内存多少有个预先估计。一个程序执行时除了需要存储空间和存储本身所使用的指
令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为现实计算所需
信息的辅助空间。程序执行时所需存储空间包括以下两部分。
固定部分:这部分空间的大小与输入/输出的数据的个数多少、数值无关。主要包括指令空间(即代
码空间)、数据空间(常量、简单变量)等所占的空间。这部分属于静态空间。
可变空间:这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。这部分的空间大小
与算法有关。
一个算法所需的存储空间用f(n)表示。S(n)=O(f(n))其中n为问题的规模,S(n)表示空间复杂度。