O(n^2)的算法

都是做的升序。

简单选择排序

思路:每次选择还未排序的区间的最小值和未排序区间的第一个值交换。

 1 function selectSort(arr){
 2     for(let i = 0; i < arr.length; i++){
 3         let minIdx = i;
 4         for(let j = i; j < arr.length; j++){
 5             if(arr[j] < arr[minIdx]){
 6                 minIdx = j;
 7             }
 8         }
 9         let tmp = arr[i];
10         arr[i] = arr[minIdx];
11         arr[minIdx] = tmp;
12     }
13     return arr;
14 }

插入排序(insertion sort)

思路:当前位置的值与前面排好序的区间从后往前对比,找到适合的插入位置并插入。

适用于:近乎有序的排序,在几乎有序的情况下,它的速度会比n(logn)的算法还要快,可以接近O(n),插入排序要优于选择排序

 1 function insertSort(arr){
 2     let tmp;
 3     for(let i = 0; i < arr.length; i++){
 4         for(let j = i - 1; j >= 0; j--){
 5         if(j === 0){
 6             if(arr[i] < arr[j]){
 7                 // 在顺序表中,应该使用副本复制当前的值,采用赋值去修改数组,而不是删除和插入,因为在顺序表中删除和插入的时间复杂度是n
 8                 tmp = arr.splice(i,1)[0];
 9                 arr.splice(j,0,tmp);
10             }
11         }else if(arr[i] < arr[j] && arr[i] >= arr[j - 1]){
12                 tmp = arr.splice(i,1)[0];
13                 arr.splice(j,0,tmp);
14             }
15         }
16         // 做一个当前函数是否有序的判断
17         if(isSort(arr)){
18             return arr;
19         }
20     }
21     return arr;
22 }

冒泡排序

O(nlogn)的算法

归并排序

优化:在待排区间的长度小于100时,可以用插入排序

 1 // 自下而上的归并算法,自上而下需要用到递归
 2 function mergeSort(arr){
 3     let arrSort = [],n = arr.length,count = 0;
 4     for(let size = 1; size <= n; size += size){ // size表示当前有序区间的长度
 5         for(let i = 0; i < n; i += size*2){
 6             // 将[i...i+size-1]和[i+size...i+size*2-1]的两个区间融合成一个有序的并添加到arrSort后面
 7             arrSort = arrSort.concat(orderMerge(arr.slice(i,i+size),arr.slice(i+size,((i+size*2) > n? n : (i+size*2)))));
 8         }
 9         arr = arrSort.slice(0);
10         arrSort.length = 0;
11     }
12     return {arr,count};
13     // orderMerger 函数主要是讲有序的两个表融合成一个有序表
14     function orderMerge(arr1,arr2){
15         let arr = [];
16         let idx1 = 0, idx2 = 0;
17         while(idx1 < arr1.length && idx2 < arr2.length){
18             if(arr1[idx1] <= arr2[idx2]){
19                 arr.push(arr1[idx1++]);
20             }else{
21                // 当arr1[index1] > arr2[idx2]的时候就是一个逆序对
22                 arr.push(arr2[idx2++]);
23                 count++;
24             }
25         }
26         if(idx1 === arr1.length){
27             arr = arr.concat(arr2.slice(idx2));
28         }else{
29             arr = arr.concat(arr1.slice(idx1));
30         }
31         return arr;
32     }
33 }

快速排序

思想:选择待排序的区间中第一个p数作为参照,大于p的放在p的后面,小于p的放前面。最后将p放在两个区间的中间,递归下去。

缺点:: 1 在排近乎有序的数组的时候,时间复杂度趋近于O(n^2)

2 再相同数值很多的数组中,时间复杂度趋近于O(n^2)

解决方案: 优化缺点1:随机选择参照数p或者待排数组中间的数作为参照数

优化缺点2-1 :从待排数组两边进行遍历,从左向右遇到>=p的值停顿,在从右向左遇到<=p的值停顿,将两个数交换并i++,j--,知道i == j为止

优化缺点2-2:三路快速排序,有三个数组,一个数组存放小于p的值,一个存放大于p的值,一个存放等于p的值。

 1 function quickSort(arr){
 2     // 终止条件:当数组长度小于等于1是返回该数组
 3     if(arr.length <= 1){
 4         return arr;
 5     }
 6     // 定义leftSort、rightSort存放小于和大于p的数
 7     let leftSort = [], rightSort =[], midSort = [], odd = 0;
 8     // 遍历arr,将大于p的放在rightSort中,小于p的放在leftSort中
 9     //优化缺点1:选择中间的数做参照并把该数从原数组中删除
10     let idx = Math.floor(arr.length/2);
11     let p = arr.splice(idx,1)[0];
12     for(let i = 0; i < arr.length; i++){
13         if(arr[i] > p){
14             rightSort.push(arr[i]);
15         }else if(arr[i] < p){
16             leftSort.push(arr[i]);
17         }else{
18             // 优化缺点2
19             if(odd){
20                 leftSort.push(arr[i]);
21                   odd = 1;
22             }else{
23                 rightSort.push(arr[i]);
24                 odd = 0;
25             }
26         }
27     }
28     // 递归leftSort、rightSort
29     leftSort = quickSort(leftSort);
30     rightSort = quickSort(rightSort);
31     // 将leftSort、midSort、rightSort合并成一个数组并返回。
32     arr = leftSort.concat(p,rightSort)
33     return arr;
34 }
35
36 //优化缺点2-2
37 function quickSort(arr){
38     if(arr.length <= 1){
39         return arr;
40     }
41     let leftSort = [], rightSort =[], midSort = [];
42     let idx = Math.floor(arr.length/2);
43     let p = arr[idx]; // 可以不用删除了
44     for(let i = 0; i < arr.length; i++){
45         if(arr[i] > p){
46             rightSort.push(arr[i]);
47         }else if(arr[i] < p){
48             leftSort.push(arr[i]);
49         }else{
50             midSort.push(arr[i]);
51         }
52     }
53     arr = quickSort(leftSort).concat(midSort,quickSort(rightSort))
54     return arr;
55 }

扩展

Merge Sort的思路求逆序对的个数

mergeSort第21行

Qiuck Sort求数组中第n大的数
 1 function theNumberN(arr,n){
 2
 3     let p,idx,
 4         leftSort = [],
 5            midSort = [],
 6         rightSort = [];
 7     while(arr.length > 1){
 8         idx = Math.floor(arr.length/2);
 9         p = arr[idx];
10         for(let i = 0; i < arr.length; i++){
11             if(arr[i] < p){
12                 leftSort.push(arr[i]);
13             }else if(arr[i] > p){
14                 rightSort.push(arr[i]);
15             }else{
16                 midSort.push(arr[i]);
17             }
18         }
19         if(leftSort.length >= n){
20             arr = leftSort.slice(0);
21         }
22
23         else if(leftSort.length+midSort.length >= n){
24
25             return midSort[0];
26         }
27
28         else{
29
30             arr = rightSort.slice(0);
31             n = n - leftSort.length - midSort.length;
32         }
33             leftSort.length = midSort.length = rightSort.length = 0;
34
35     }
36     return arr[0];
37
38 }

或者使用递归

 1 function theNumberN(arr,n){
 2     if(arr.length <= 1){
 3         return arr[0];
 4     }
 5     // 选一个基点p
 6     let p,
 7         leftSort = [],
 8         midSort = [],
 9         rightSort = [];
10     // 小于p放leftSort,等于p放midSort,大于放rightSort
11         p = arr[Math.floor(arr.length/2)];
12         for(let i = 0; i < arr.length; i++){
13         if(arr[i] < p){
14             leftSort.push(arr[i]);
15         }else if(arr[i] > p){
16             rightSort.push(arr[i]);
17         }else{
18             midSort.push(arr[i]);
19         }
20     }
21     // 如果leftSort.length>n则抛弃midSort和rightSort再找leftSort中第n大的数
22     if(leftSort.length >= n){
23         return theNumberN(leftSort,n);
24     }
25     // 否则判断leftSort.length+midSort.length>n则抛弃leftSort和rightSort,在midSort中找第n-leftSort.length大的数
26     else if(leftSort.length+midSort.length >= n){
27         // theNumberN(midSort,n - leftSort.length);
28         return midSort[0];
29     }
30     // 否则抛弃leftSort和midSort,在rightSort中找第n-leftSort.length-midSort.length大的数
31     else{
32         return theNumberN(rightSort,n - leftSort.length - midSort.length);
33     }
34 }

转载于:https://www.cnblogs.com/171220-barney/p/8972250.html

O(n^2)以及O(nlogn)时间复杂度的排序算法相关推荐

  1. 堆排序重建堆的时间复杂度_排序算法之 堆排序 及其时间复杂度和空间复杂度-Go语言中文社区...

    堆排序是由1991年的计算机先驱奖获得者.斯坦福大学计算机科学系教授罗伯特.弗洛伊德(Robert W.Floyd)和威廉姆斯(J.Williams)在1964年共同发明了的一种排序算法( Heap ...

  2. 冒泡和快速排序的时间复杂度_排序算法学习分享(二)交换排序---冒泡排序与快速排序...

    排序,也称为排序算法,可以说是我们学习算法的过程中遇到的第一个门槛,也是实际应用中使用得较为频繁的算法,我将自己对所学的排序算法进行一个归纳总结与分享,如有错误,欢迎指正! 排序算法学习分享(一)选择 ...

  3. 常见的时间复杂度和排序算法

    1.常见的时间复杂度 (1)O(1):常量阶,运行时间为常量 (2)O(logn):对数阶,如二分搜索算法 (3)O(n):线性阶,如n个数内找最大值 (4)O(nlogn):对数阶,如快速排序算法 ...

  4. js排序的时间复杂度_JavaScript排序算法及性能比较

    JavaScript排序算法及性能比较 类别: 技术·JS 时间:2017-03-13 19:15:30 字数:7651 版权所有,未经允许,请勿转载,谢谢合作~ #### 前言 对很多同学来说,启蒙 ...

  5. 传说中线性时间复杂度的排序算法

    本文用我自己的理解来介绍3个"超快"的排序算法:计数排序,基数排序,桶排序. 谈到排序该怎么算,直觉上应该都要元素之间进行比较才能排出顺序,比较是不可或缺的,但偏偏有的排序算法可以 ...

  6. 冒泡和快速排序的时间复杂度_排序算法整合(冒泡,快速,希尔,拓扑,归并)

    本文链接:https://blog.csdn.net/onceing/article/details/99838520 冒泡排序介绍 冒泡排序(Bubble Sort),又被称为气泡排序或泡沫排序. ...

  7. 6.排序算法最优的时间复杂度

    排序算法最优的时间复杂度:线性对数阶O(nlogn) 对应的排序算法有:堆排序.归并排序.快速排序(最好平均)

  8. 各种排序算法的时间复杂度对比

    各种排序算法的时间复杂度对比 排序算法 最坏时间复杂度 平均时间复杂度 最优时间复杂度 空间复杂度 稳定性 冒泡排序 O(n^2) O(n^2) O(n) O(1) 稳定 插入排序 O(n^2) O( ...

  9. 常见排序算法的最好、最坏、平均时间复杂度以及空间复杂度

    文章目录 思考 前言 如何分析一个排序算法? 排序算法的执行效率 排序算法的内存消耗 排序算法的稳定性 如何选择合适的排序算法? 如何优化快速排序? 解答思考题 参考链接 思考 为什么插入排序比冒泡排 ...

  10. 排序算法的时间复杂度_算法的时间复杂度

    一. 算法的时间复杂度 1.如何评估算法的性能 数据结构和算法,本质上是解决现实存在的问题,即如何让解决指定问题的代码运行得更快?一个算法如果能在所要求的资源限制(resource constrain ...

最新文章

  1. 【Android 高性能音频】Oboe 函数库简介 ( Oboe 简介 | Oboe 特点 | Oboe 编译工具 | Oboe 相关文档 | Oboe 测试工具 )
  2. Java Ajax jsonp 跨域请求
  3. BZOJ5358: [Lydsy1805月赛]口算训练
  4. python复制代码会被发现吗,我发现了一个记忆代码片段,我想知道它在复制。复制...
  5. 元宇宙时代,技术长什么样
  6. Atitit 编程范式之道 attilax著 艾龙 著 1. 编程范式与编程语言的关系是什么? 1 2. LOP 面向语言编程(LOP, Language Oriented Programming
  7. GPU硬件加速原理 /转
  8. C++练习 简易翻译器
  9. 计算机cad运行缓慢怎样处理,win7系统提高CAD运行速度的方法
  10. 微信支付和支付宝支付整合(异步回调篇)
  11. html里怎么旋转视频文件,如何旋转视频文件(方法三)
  12. Word文件不能编辑是什么原因?
  13. python怎么输出坐标_使用Python实现图像标记点的坐标输出功能
  14. 如何登陆亚马逊EC2
  15. Ubuntu20.04安装nVidia显卡遇到的各种坑
  16. 7-53 生化危机——dfs
  17. 意能通:一名博士CEO的人工智能创业之旅
  18. 矩阵按键及独立按键工作原理
  19. LocalDate计算两个日期间距离
  20. KMPlayer 3.9 播放器不能播放 AC3 音频 解决方法

热门文章

  1. 转:ElasticSearch 插件安装
  2. 【VS2010学习笔记】【异常处理】一(无法启动此程序,因为计算机中丢失libiconv-2.dll)
  3. 【python简洁之道】-----1. 注释规则
  4. 《剑指offer》面试题4——替换空格 C++编程
  5. linux设置服务开机自启动
  6. 设计自己的ImageLoader图片加载框架
  7. Python基础语法-04-生成器,迭代器
  8. mysql job 存储过程_mysql 记录下工作中自己写的存储过程
  9. 字典生成_数据字典文档自成工具,一键生成,效率倍增
  10. Flink 在 B 站的多元化探索与实践