[算法] O(n^2)排序算法的效率比较
选择、插入排序
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)排序算法的效率比较的更多相关文章
- 数据结构和算法(Golang实现)(25)排序算法-快速排序
快速排序 快速排序是一种分治策略的排序算法,是由英国计算机科学家Tony Hoare发明的, 该算法被发布在1961年的Communications of the ACM 国际计算机学会月刊. 注:A ...
- 数据结构和算法(Golang实现)(19)排序算法-冒泡排序
冒泡排序 冒泡排序是大多数人学的第一种排序算法,在面试中,也是问的最多的一种,有时候还要求手写排序代码,因为比较简单. 冒泡排序属于交换类的排序算法. 一.算法介绍 现在有一堆乱序的数,比如:5 9 ...
- 数据结构和算法(Golang实现)(20)排序算法-选择排序
选择排序 选择排序,一般我们指的是简单选择排序,也可以叫直接选择排序,它不像冒泡排序一样相邻地交换元素,而是通过选择最小的元素,每轮迭代只需交换一次.虽然交换次数比冒泡少很多,但效率和冒泡排序一样的糟 ...
- 数据结构和算法(Golang实现)(21)排序算法-插入排序
插入排序 插入排序,一般我们指的是简单插入排序,也可以叫直接插入排序.就是说,每次把一个数插到已经排好序的数列里面形成新的排好序的数列,以此反复. 插入排序属于插入类排序算法. 除了我以外,有些人打扑 ...
- 数据结构和算法(Golang实现)(22)排序算法-希尔排序
希尔排序 1959 年一个叫Donald L. Shell (March 1, 1924 – November 2, 2015)的美国人在Communications of the ACM 国际计算机 ...
- 数据结构和算法(Golang实现)(23)排序算法-归并排序
归并排序 归并排序是一种分治策略的排序算法.它是一种比较特殊的排序算法,通过递归地先使每个子序列有序,再将两个有序的序列进行合并成一个有序的序列. 归并排序首先由著名的现代计算机之父John_von_ ...
- 数据结构和算法(Golang实现)(24)排序算法-优先队列及堆排序
优先队列及堆排序 堆排序(Heap Sort)由威尔士-加拿大计算机科学家J. W. J. Williams在1964年发明,它利用了二叉堆(A binary heap)的性质实现了排序,并证明了二叉 ...
- 链表插入和删除,判断链表是否为空,求链表长度算法的,链表排序算法演示——C语言描述
关于数据结构等的学习,以及学习算法的感想感悟,听了郝斌老师的数据结构课程,其中他也提到了学习数据结构的或者算法的一些个人见解,我觉的很好,对我的帮助也是很大,算法本就是令人头疼的问题,因为自己并没有学 ...
- 冒泡排序算法和简单选择排序算法的js实现
之前已经介绍过冒泡排序算法和简单选择排序算法和原理,现在有Js实现. 冒泡排序算法 let dat=[5, 8, 10, 3, 2, 18, 17, 9]; function bubbleSort(d ...
- 数据结构和算法(Golang实现)(18)排序算法-前言
排序算法 人类的发展中,我们学会了计数,比如知道小明今天打猎的兔子的数量是多少.另外一方面,我们也需要判断,今天哪个人打猎打得多,我们需要比较. 所以,排序这个很自然的需求就出来了.比如小明打了5只兔 ...
随机推荐
- 树莓派WIFI
树莓派WIFI设置 在"开始使用树莓派"中,我们在boot根目录下创wpa_supplicant.conf文件,实现了第一次连接wifi.以后开机后,树莓派会自动连接那个wifi. ...
- Spring Boot demo系列(三):Spring Web+MyBatis Plus
2021.2.24 更新 1 概述 Spring Web+MyBatis Plus的一个Demo,内容和上一篇类似,因此重点放在MyBatis Plus这里. 2 dao层 MyBatis Plus相 ...
- Floyd算法C++实现与模板题应用
简介 Floyd算法算是最简单的算法,没有之一. 其状态转移方程如下map[i , j] =min{ map[i , k] + map[k , j] , map[i , j] }: map[i , j ...
- 这一次,彻底搞懂 Go Cond
hi,大家好,我是 haohongfan. 本篇文章会从源码角度去深入剖析下 sync.Cond.Go 日常开发中 sync.Cond 可能是我们用的较少的控制并发的手段,因为大部分场景下都被 Cha ...
- 重绘DevExpress的XtraMessageBox消息提示框控件
先来看提示框,可以看到框其实是一个去掉最大化.最小化按钮后的窗体,窗体的内容就是我们想要提示的内容,重绘提示框其实就是重绘窗体以及中间部分的内容. 首先重绘窗体,消息提示框的窗体不是XtraForm而 ...
- 01-Verilog基本语法元素
不知道能不能更新完,毕竟咱学校计院对硬件向来不太重视,现在对竞赛也不咋地重视了,也不加分,也没啥用.嘛,就随便写写玩玩吧. 一只狸无聊的时候对Verilog的业余描述笔记:以<Verilog数字 ...
- 02- Python的版本
python的官网 https://www.python.org/ Python的版本 python v2.7(2020结束维护) python v.3.5(当前使用的版本) python v3 ...
- php文件的自动加载
<?php spl_autoload_register(function ($class_name) { require_once $class_name . '.php'; });
- UVA10763交换学生
题意: 给你N组关系,每组关系是a,b,最后问你所有的a,b出现的次数和所有的b,a出现的此时是否全部都一样. 思路: 水题,直接开了个二维的map标记,map<int ...
- Portswigger web security academy:HTTP request smuggling
HTTP request smuggling 目录 HTTP request smuggling HTTP request smuggling, basic CL.TE vulnerability H ...