简单的排序算法与时间复杂度(一)

常数时间的操作:一个操作如果和数据量没有关系,每次都是固定时间内完成的操作,叫做常数操作。时间复杂度为一个算法流程中,常数操作数量的指标。常用O(读作big O)来表示。具体来说,在常数操作数量的表达式中,只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分如果记为f(N),那么时间复杂度为O(f(N))。评价一个算法流程的好坏,先看时间复杂度的指标,然后再分析不同数据样本下的实际运行时间,也就是常数项时间。一般一个算法的时间复杂度是它的最差时间复杂度。

1.冒泡排序(O(n^2))

public static void bubbleSort(int[] arr)`{
  if(arr=.=null || arr.length<2){
    return
  }
  for(int e=arr.length-1;e>0;e--){
    for(int i=0;i<e;i++){
      if(arr[i]>arr[i+1]){
        swap(arr,i,i+1);
      }
    }
  }
public static void swap(int[] arr,int i,int j){
     arr[i]=arr[i]^arr[j];
     arr[j]=arr[i]^arr[j];
     arr[i]=arr[i]^arr[j];
   }
}

冒泡排序法的核心就是比较 相邻两个数的大小,再进行交换,举个栗子,就拿上面的代码来说,外层for循环控制的是排序的趟数,内层for循环控制的是每一趟排序的次数,即相邻两个数交换的次数。那么它的时间复杂度为多少呢,它的最好的时间复杂度是O(n),因为当数据全部为正序时,只需要走过n-1次就可以成功。反之最差的为(n-1)+(n-2)+…+1,就是(n^2/2)+n+1,即 O(n^2)。
上面说到了一个算法的时间复杂度为它的最差时间复杂度,所以冒泡排序的时间复杂度为O(n^2)。

2.选择排序(O(n^2))

public static void selectionSort(int[] arr){
  if(arr==null || arr.length<2){
    return;
  }
    for(int i=0;i<arr.length-1;i--){
      int minIndex=i;
      for(int j=i+1;j<arr.length;j++){
        minIndex=arr[j]<arr[minIndex] ?j : minIndex;
      }
      swap(arr,i,minIndex);
    }
public static void swap(int[] arr,int i,int j){
     arr[i]=arr[i]^arr[j];
     arr[j]=arr[i]^arr[j];
     arr[i]=arr[i]^arr[j];
   }
}

举例:数组 int[] arr={5,2,8,4,9,1};


第一趟排序: 原始数据:5 2 8 4 9 1

最小数据1,把1放在首位,也就是1和5互换位置,

排序结果:1 2 8 4 9 5


第二趟排序:

第1以外的数据{2 8 4 9 5}进行比较,2最小,

排序结果:1 2 8 4 9 5


第三趟排序:

除1、2以外的数据{8 4 9 5}进行比较,4最小,8和4交换

排序结果:1 2 4 8 9 5


第四趟排序:

除第1、2、4以外的其他数据{8 9 5}进行比较,5最小,8和5交换

排序结果:1 2 4 5 9 8


第五趟排序:

除第1、2、4、5以外的其他数据{9 8}进行比较,8最小,8和9交换

排序结果:1 2 4 5 8 9
同理选择排序的时间复杂度为O(n^2);

3.插入排序(O(n^2))

public static void insertSort(int[] arr){
  if(arr==null&&arr.length<2){
  return;
  }
  for(int i=1;i<arr.length;i++){
    for(int j=i-1;j>=0&&arr[j]>arr[j+1];j--){
       swap(arr,j,j+1);
    }
  }
   public static void swap(int[] arr,int i,int j){
     arr[i]=arr[i]^arr[j];
     arr[j]=arr[i]^arr[j];
     arr[i]=arr[i]^arr[j];
   }
}

直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。 [1]
例如,已知待排序的一组记录是:
60,71,49,11,24,3,66
假设在排序过程中,前3个记录已按关键码值递增的次序重新排列,构成一个有序序列:
49,60,71
将待排序记录中的第4个记录(即11)插入上述有序序列,以得到一个新的含4个记录的有序序列。首先,应找到11的插入位置,再进行插入。可以讲11放入数组的第一个单元r[0]中,这个单元称为监视哨,然后从71起从右到左查找,11小于71,将71右移一个位置,11小于60,又将60右移一个位置,11小于49,又再将49右移一个位置,这时再将11与r[0]的值比较,11≥r[0],它的插入位置就是r[1]。假设11大于第一个值r[1]。它的插入位置应该在r[1]和r[2]之间,由于60已经右移了,留出来的位置正好留给11.后面的记录依照同样的方法逐个插入到该有序序列中。若记录数n,续进行n-1趟排序,才能完成。
直接插入排序的算法思路:
(1) 设置监视哨arr[0],将待插入记录的值赋值给arr[0];
(2) 设置开始查找的位置j;
(3) 在数组中进行搜索,搜索中将第j个记录后移,直至arrr[0].key≥arr[j].key为止;
(4) 将arr[0]插入arrr[j+1]的位置上。

猜你喜欢

转载自blog.csdn.net/qq_40707033/article/details/82777859