选择、插入排序

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. GitlabCI/CD&Kubernetes项目交付流水线实践

    GitlabCI实践 GitLabCI/CD基础概念 为什么要做CI/CD? GitLab CI/CD简介 GitLabCI VS Jenkins 安装部署GitLab服务 GitLabRunner实 ...

  2. Vue3 封装第三方组件(一)做一个合格的传声筒

    各种UI库的功能都是非常强大的,尤其对于我这种不会 css 的人来说,就更是帮了大忙了. 只是嘛,如果再封装一下的话,那么用起来就会更方便了. 那么如何封装呢? 封装三要素 -- 属性.插槽.事件.方 ...

  3. Spring Cloud Gateway 全局通用异常处理

    为什么需要全局异常处理 在传统 Spring Boot 应用中, 我们 @ControllerAdvice 来处理全局的异常,进行统一包装返回 // 摘至 spring cloud alibaba c ...

  4. 说一下的dubbo的工作原理?注册中心挂了可以继续通信吗?

    (1)dubbo工作原理 第一层:service层,接口层,给服务提供者和消费者来实现的 第二层:config层,配置层,主要是对dubbo进行各种配置的 第三层:proxy层,服务代理层,透明生成客 ...

  5. xctf - stack2

    xctf - stack2 文件check一下,几乎全开了 运行一下程序,好像很正常呢: 再来一个大的,好像有点儿问题,变1.00了 在ida中查看,在输入的时候没有检查数据大小 可以通过劫持eip获 ...

  6. 磁盘挖矿时代开启——GitHub 热点速览 v.21.16

    作者:HelloGitHub-小鱼干 本周的 GitHub 热点非常经常,因为一贫如洗的小鱼干突然发现了发家致富之道:磁盘挖矿.chia-blockchain 是一个将磁盘作为计算资源的项目,简而言之 ...

  7. Spring Boot demo系列(一):Hello World

    2021.2.24 更新 1 新建工程 打开IDEA选择新建工程并选择Spring Initializer: 可以在Project JDK处选择JDK版本,下一步是选择包名,语言,构建工具以及打包工具 ...

  8. 【Java】String、StringBuilder和StringBuffer

    [String] 首先,从String类的定义入手,可以看到String类是由final修饰,即不可变的,一旦创建出来就不可修改,因此首先明确,字符串的拼接.截取等操作都会产生新的字符串对象. 观察以 ...

  9. 病毒木马查杀实战第017篇:U盘病毒之专杀工具的编写

    前言 经过前几次的讨论,我们对于这次的U盘病毒已经有了一定的了解,那么这次我们就依据病毒的行为特征,来编写针对于这次U盘病毒的专杀工具. 专杀工具功能说明 因为这次是一个U盘病毒,所以我打算把这次的专 ...

  10. POJ3070矩阵快速幂简单题

    题意:       求斐波那契后四位,n <= 1,000,000,000. 思路:        简单矩阵快速幂,好久没刷矩阵题了,先找个最简单的练练手,总结下矩阵推理过程,其实比较简单,关键 ...