选择、插入排序

main.cpp

 1 #include <iostream>
3 #include "SortTestHelper.h"
4
5 using namespace std;
6
7 template<typename T>
8 void selectionSort(T arr[],int n){
9 for(int i = 0 ; i < n ; i ++){
10 int minIndex = i;
11 for( int j = i + 1 ; j < n ; j ++ )
12 if( arr[j] < arr[minIndex] )
13 minIndex = j;
14 swap( arr[i] , arr[minIndex] );
15 }
16 }
17
18 template<typename T>
19 void insertionSort(T arr[],int n){
20 for(int i = 1 ; i < n ; i++ ){
21 T e = arr[i];
22 int j;
23 for(j = i ; j > 0 && arr[j-1] > e ; j --)
24 arr[j] = arr[j-1];
25 arr[j] = e;
26 }
27 }
28
29 int main(){
30 int n = 100000;
31 int *arr = SortTestHelper::generateNearlyOrderedArray(n,10);
32
33 SortTestHelper::testSort("Insertion Sort",insertionSort,arr,n);
34 SortTestHelper::testSort("Selection Sort",selectionSort,arr,n);
35
36 delete[] arr;
37 return 0;
38 }

SortTestHelper.h

 1 #include <iostream>
2 #include <ctime>
3 #include <cassert>
4 #include <string>
5
6 using namespace std;
7
8 namespace SortTestHelper{
9 int *generateRandomArray(int n,int rangeL,int rangeR){
10 assert(rangeL <= rangeR);
11 int *arr = new int[n];
12 srand(time(NULL));
13 for(int i = 0 ; i < n ; i++)
14 arr[i] = rand()%(rangeR-rangeL+1) + rangeL;
15 return arr;
16 }
17
18 int *generateNearlyOrderedArray(int n, int swapTimes){
19 int *arr = new int[n];
20 for(int i = 0 ; i < n ; i ++ )
21 arr[i] = i;
22 srand(time(NULL));
23 for( int i = 0 ; i < swapTimes ; i ++){
24 int posx = rand()%n;
25 int posy = rand()%n;
26 swap( arr[posx] , arr[posy] );
27 }
28 return arr;
29 }
30
31 template<typename T>
32 void printArray(T arr[],int n){
33 for(int i = 0;i<n;i++)
34 cout << arr[i] <<" ";
35 cout << endl;
36 return;
37 }
38
39 template<typename T>
40 bool isSorted(T arr[],int n){
41 for(int i = 0 ; i<n-1 ; i++)
42 if(arr[i] > arr[i+1])
43 return false;
44 return true;
45 }
46 template<typename T>
47 void testSort(const string &sortName,void (*sort)(T[],int),T arr[],int n){
48
49 clock_t startTime = clock();
50 sort(arr,n);
51 clock_t endTime = clock();
52
53 assert(isSorted(arr,n));
54
55 cout << sortName << " : " << double(endTime-startTime)/CLOCKS_PER_SEC << " s" <<endl;
56
57 return;
58 }
59 }

结果

插入排序快的原因

  • 可提前终止循环
  • 没有交换操作
  • 对近乎有序数组,插入排序会更快,甚至快于O(nlogn)级算法,在实际中有大量应用

冒泡排序

方法1

 1 template<typename T>
2 void bubbleSort( T arr[] , int n){
3
4 bool swapped;
5
6 do{
7 swapped = false;
8 for( int i = 1 ; i < n ; i ++ )
9 if( arr[i-1] > arr[i] ){
10 swap( arr[i-1] , arr[i] );
11 swapped = true;
12
13 }
14
15 // 优化, 每一趟Bubble Sort都将最大的元素放在了最后的位置
16 // 所以下一次排序, 最后的元素可以不再考虑
17 n --;
18
19 }while(swapped);
20 }

方法2

 1 template<typename T>
2 void bubbleSort2( T arr[] , int n){
3
4 int newn; // 使用newn进行优化
5
6 do{
7 newn = 0;
8 for( int i = 1 ; i < n ; i ++ )
9 if( arr[i-1] > arr[i] ){
10 swap( arr[i-1] , arr[i] );
11
12 // 记录最后一次的交换位置,在此之后的元素在下一轮扫描中均不考虑
13 newn = i;
14 }
15 n = newn;
16 }while(newn > 0);
17 }

优化

  • 每轮循环如果没有发生交换,就代表数据已经有序,提前退出
  • 每轮循环中后面的元素如果已经有序,下一轮循环就不再考虑

三种O(n^2)级别算法的思路:

  • 冒泡排序:相邻元素作比较,每次循环后最大的元素放在最后
  • 选择排序:找到后面最小的元素,每次循环后最小的元素放在最前
  • 插入排序:将新元素插入到有序数组中合适的位置

时间复杂度比较

  • 选择排序:比较+交换。对于最好和最坏情况,比较的次数是一样多的,均为n(n-1)/2,最好情况交换0次,最坏情况交换n-1次,故总的时间复杂度为O(n2)
  • 插入排序:比较+赋值。最好情况为顺序,只需比较前面的一个元素即可,不需要赋值,复杂度O(n),最坏情况为逆序,需要和前面所有的数都进行比较和赋值,复杂度O(n2)
  • 单向链表插入排序:比较+插入,链表插入的复杂度是O(1),故主要时间消耗在比较上,即为新元素找到合适的位置插入,对于逆序,每次新元素只要完成插入即可,时间消耗O(n);对于顺序,每个新元素都要从头遍历(单向链表,无法直接比较前一个元素),与每个元素进行比较,时间消耗O(n2)

最新文章

  1. lca入门———树上倍增法(博文内含例题)
  2. 获取枚举类型的描述description
  3. Windbg调试命令详解(3)
  4. HDU 2665(Kth number-区间第k大[内存限制+重数])
  5. Eclipse更改默认工作目录的方法
  6. IT生涯, 我的常用软件清单
  7. 语义化版本控制规范(SemVer)
  8. node.js使用scp2来进行scp操作
  9. hibernate自定义校验Valid
  10. Python常用字符编码(转)
  11. 安装淘宝npm(cnpm)
  12. talk with gao about qssp
  13. BZOJ4974 八月月赛 Problem D 字符串大师 KMP
  14. day5 五、数字类型、字符串,列表类型的基本操作和内置方法
  15. jzoj5906
  16. Django 2.0.3安装-压缩包方式
  17. Linux 调优方案, 修改最大连接数-ulimit
  18. [jOOQ中文]3. 数据库版本管理工具Flyway
  19. WeChat-扫码支付
  20. maven install时自动施行单元测试

热门文章

  1. mybatis-plus的Could not set property &#39;updateDate&#39; of &#39;class com.example.pojo.User&#39; with value &#39;Fri Jul 24 10:29:39 CST 2020&#39; Cause: java.lang.IllegalArgumentException: argument type mismatch解决方案
  2. PAT (Advanced Level) Practice 1015 Reversible Primes (20 分) 凌宸1642
  3. Linux 软链接link/ln -s
  4. 第23 章 : Kubernetes API 编程范式
  5. 关于 Spring 中 getBean 的全流程源码解析
  6. MQ 入门实践
  7. redhat7.6 安装 Python 3
  8. .netcore 写快递100的快递物流信息查询接口
  9. day8.函数基础
  10. 病毒木马查杀实战第025篇:JS下载者脚本木马的分析与防御