vlambda博客
学习文章列表

算法 | 复杂度与计数排序

时间复杂度

设定算法操作执行次数为函数T(n),若存在函数f(n),使得n趋向于无穷大时,T(n)/f(n)的极限值为不等于0的常数,建成后f(n)是T(n)的通数量级函数,记作T(n)=O(f(n)),O为算法的渐进时间复杂度,简称时间复杂度。

计算原则:

  • 如果运行时间是常数量级,则用常数1表示。

  • 只保留时间函数的最高阶项

  • 如果最高阶项存在,则省去前面的系数

空间复杂度

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。S(n)=O(f(n))。

我们对之前文章七种排序列出的复杂度:

排序算法 平均时间复杂度 最坏时间复杂度 空间复杂度 是否稳定
冒泡排序 O(n2) O(n2) O(1) 是
插入排序 O(n2) O(n2) O(1) 是
选择排序 O(n2) O(n2) O(1) 不是
希尔排序 O(nlogn) O(ns) O(1) 不是
堆排序 O(nlogn) O(nlogn) O(1) 不是
归并排序 O(nlogn) O(nlogn) O(n) 是
快速排序 O(nlogn) O(n2)O(n2) O(logn) 不是

更多细节推荐文末第一篇文章。https://blog.csdn.net/yushiyi6453/article/details/76407640


另外再来介绍一种排序算法--计数排序。

假如有一系列数字90-100,现在排序。

 
   
   
 
  1. function sort()

  2. {

  3. $arr = [98, 96, 99, 90, 99, 92, 91, 94, 98, 96, 95];

  4. $min = $max = $arr[0];

  5. $count = count($arr);

  6. // 计算长度

  7. for ($i=1; $i < $count; $i++) {

  8. if ($arr[$i] > $max) {

  9. $max = $arr[$i];

  10. continue;

  11. }


  12. if ($arr[$i] < $min) {

  13. $min = $arr[$i];

  14. }

  15. }

  16. $length = $max - $min;


  17. for ($i=0; $i<=$length; $i++) {

  18. $countArr[$i] = 0;

  19. }


  20. //计数

  21. for ($i=0; $i<$count; $i++) {

  22. $countArr[$arr[$i] - $min]++;

  23. }


  24. //遍历回来

  25. foreach ($countArr as $k=>$v) {

  26. for ($j=0; $j<$v; $j++) {

  27. $result[] = $k+$min;

  28. }

  29. }


  30. return $result;

  31. }

可以看看gif图片:

算法 | 复杂度与计数排序

那么问题来了,假如这些数字是学生成绩,同分的我们也需要记下对应的人排名,那么怎么办呢?

我们可以在计数之后在进行依次遍历,在对应的下标增加进入前面下标的数量。

假定现在有:

 
   
   
 
  1. [92, 91, 90, 95, 94, 99, 97, 99, 91, 92]

红色是普通的计数,黄色的是进阶计数。

 
   
   
 
  1. function sort()

  2. {

  3. $arr = ['a' => 92, 'b' => 91, 'c' => 90, 'd' => 95, 'e' => 94, 'f' => 99,

  4. 'h' => 97, 'i' => 99, 'j' => 91, 'k'=>92];

  5. $min = $max = $arr['a'];

  6. $count = count($arr);

  7. // 计算长度

  8. foreach ($arr as $val) {

  9. if ($val > $max) {

  10. $max = $val;

  11. continue;

  12. }


  13. if ($val < $min) {

  14. $min = $val;

  15. }

  16. }

  17. $length = $max - $min;


  18. for ($i=0; $i<=$length; $i++) {

  19. $countArr[$i] = 0;

  20. }


  21. //计数

  22. foreach ($arr as $val) {

  23. $countArr[$val - $min]++;

  24. }

  25. // var_dump($countArr);

  26. for ($i=1; $i<=$length; $i++) {

  27. $countArr[$i] += $countArr[$i-1];

  28. }

  29. //遍历回来

  30. foreach ($arr as $k=>$val) {

  31. $result[$count + 1 - $countArr[$val - $min] - 1] = [$k, $val];

  32. $countArr[$val - $min]--;

  33. }


  34. return $result;

  35. }

计数排序适合排序有效区间内的整数,局限性比较多。




参考文章:

文中图片来自以下文章,如有版权问题,请告知删除。有兴趣也可以看下以下文章。

  • 排序算法时间复杂度、空间复杂度、稳定性比https://blog.csdn.net/yushiyi6453/article/details/76407640

  • 《漫画算法》@程序员小灰

  • 时间复杂度和空间复杂度-https://www.cnblogs.com/chenjinxinlove/p/10038919.html

  • 计数排序-https://www.jianshu.com/p/e9db78d3c93c

  • 计数排序--《程序员小灰》- https://www.cnblogs.com/easilyai/p/9769773.html