选择、插入排序

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)

[算法] O(n^2)排序算法的效率比较的更多相关文章

  1. 数据结构和算法(Golang实现)(25)排序算法-快速排序

    快速排序 快速排序是一种分治策略的排序算法,是由英国计算机科学家Tony Hoare发明的, 该算法被发布在1961年的Communications of the ACM 国际计算机学会月刊. 注:A ...

  2. 数据结构和算法(Golang实现)(19)排序算法-冒泡排序

    冒泡排序 冒泡排序是大多数人学的第一种排序算法,在面试中,也是问的最多的一种,有时候还要求手写排序代码,因为比较简单. 冒泡排序属于交换类的排序算法. 一.算法介绍 现在有一堆乱序的数,比如:5 9 ...

  3. 数据结构和算法(Golang实现)(20)排序算法-选择排序

    选择排序 选择排序,一般我们指的是简单选择排序,也可以叫直接选择排序,它不像冒泡排序一样相邻地交换元素,而是通过选择最小的元素,每轮迭代只需交换一次.虽然交换次数比冒泡少很多,但效率和冒泡排序一样的糟 ...

  4. 数据结构和算法(Golang实现)(21)排序算法-插入排序

    插入排序 插入排序,一般我们指的是简单插入排序,也可以叫直接插入排序.就是说,每次把一个数插到已经排好序的数列里面形成新的排好序的数列,以此反复. 插入排序属于插入类排序算法. 除了我以外,有些人打扑 ...

  5. 数据结构和算法(Golang实现)(22)排序算法-希尔排序

    希尔排序 1959 年一个叫Donald L. Shell (March 1, 1924 – November 2, 2015)的美国人在Communications of the ACM 国际计算机 ...

  6. 数据结构和算法(Golang实现)(23)排序算法-归并排序

    归并排序 归并排序是一种分治策略的排序算法.它是一种比较特殊的排序算法,通过递归地先使每个子序列有序,再将两个有序的序列进行合并成一个有序的序列. 归并排序首先由著名的现代计算机之父John_von_ ...

  7. 数据结构和算法(Golang实现)(24)排序算法-优先队列及堆排序

    优先队列及堆排序 堆排序(Heap Sort)由威尔士-加拿大计算机科学家J. W. J. Williams在1964年发明,它利用了二叉堆(A binary heap)的性质实现了排序,并证明了二叉 ...

  8. 链表插入和删除,判断链表是否为空,求链表长度算法的,链表排序算法演示——C语言描述

    关于数据结构等的学习,以及学习算法的感想感悟,听了郝斌老师的数据结构课程,其中他也提到了学习数据结构的或者算法的一些个人见解,我觉的很好,对我的帮助也是很大,算法本就是令人头疼的问题,因为自己并没有学 ...

  9. 冒泡排序算法和简单选择排序算法的js实现

    之前已经介绍过冒泡排序算法和简单选择排序算法和原理,现在有Js实现. 冒泡排序算法 let dat=[5, 8, 10, 3, 2, 18, 17, 9]; function bubbleSort(d ...

  10. 数据结构和算法(Golang实现)(18)排序算法-前言

    排序算法 人类的发展中,我们学会了计数,比如知道小明今天打猎的兔子的数量是多少.另外一方面,我们也需要判断,今天哪个人打猎打得多,我们需要比较. 所以,排序这个很自然的需求就出来了.比如小明打了5只兔 ...

随机推荐

  1. Prometheus联邦

    联邦使得一个 Prometheus 服务器可以从另一个 Prometheus 服务器提取选定的时序. 1. 使用场景 Prometheus 联邦有不同的使用场景.通常,联邦被用来实现可扩展的 Prom ...

  2. Kubernetes中Deployment部署故障排除

    Kubernetes中Deployment部署故障排除 字符型思维导图 排查pod状态(带标签):kubectl get pods,是否有等待处理的pod? 是?kubectl describe po ...

  3. web编辑工具 - Brackets - 强大免费的开源跨平台Web前端开发工具IDE

      简单使用可以参考: https://blog.csdn.net/melon19931226/article/details/68066971/ https://www.iplaysoft.com/ ...

  4. matlab mashgrid 函数

    meshgrid 有三种语法,用来生成三维网格矩阵或二维网格矩阵 [X,Y] = meshgrid(x,y) , x和y 都是一维数组,如x=[1:3]; y= [4:5]; 则生成的 X 和 Y 都 ...

  5. C/C++中的const

    1 C中的const C中const修饰的变量是只读变量,在使用const关键字声明定义变量时会给该变量分配内存空间. const修饰的全局变量默认是外部链接的,即其它源文件可以直接使用该变量. co ...

  6. JavaWeb 补充(JSP&EL&JSTL)

    1. JSP:     1. 指令     2. 注释     3. 内置对象 2. MVC开发模式 3. EL表达式 4. JSTL标签 5. 三层架构 JSP: 1. 指令     * 作用:用于 ...

  7. Spring Boot demo系列(八):Swagger

    2021.2.24 更新 1 概述 Swagger主要用于生成API文档,本文演示了如何使用目前最新的OpenAPI3以及Swagger来进行接口文档的生成. 2 依赖 <dependency& ...

  8. jasypt-spring-boot提示Failed to bind properties

    1 问题描述 在Spring Boot中使用jasypt-spring-boot进行加密,但是提示: Description: Failed to bind properties under 'spr ...

  9. 微服务的进程间通信(IPC)

    微服务的进程间通信(IPC) 目录 微服务的进程间通信(IPC) 术语 概述 通信视角 APIs 消息格式 RPC REST gRPC 断路器 API通信的健壮性 服务发现 异步消息 概念 消息 消息 ...

  10. Linux下查看CPU、内存占用率

    linux下查看最消耗CPU.内存的进程 CPU占用最多的前10个进程: ps auxw|head -1;ps auxw|sort -rn -k3|head -10 内存消耗最多的前10个进程: ps ...