测试环境为DEV-C++,并且选择排序,插入排序,冒泡排序,均为优化后的,若想了解具体优化过程,请参照:https://blog.csdn.net/qq_40164152

测试用例:

#ifndef OPTIONAL_02_SHELL_SORT_SORTTESTHELPER_H
#define OPTIONAL_02_SHELL_SORT_SORTTESTHELPER_H
#include <iostream>
#include <algorithm>
#include <ctime>
#include <string>
#include <cassert>
using namespace std;
namespace SortTestHelper {
// 生成有n个元素的随机数组,每个元素的随机范围为[rangeL, rangeR]
int *generateRandomArray(int n, int range_l, int range_r) {
int *arr = new int[n];
srand(time(NULL));
for (int i = ; i < n; i++)
arr[i] = rand() % (range_r - range_l + ) + range_l;
return arr;
}
// 生成一个近乎有序的数组
// 首先生成一个含有[0...n-1]的完全有序数组, 之后随机交换swapTimes对数据
// swapTimes定义了数组的无序程度
int *generateNearlyOrderedArray(int n, int swapTimes){
int *arr = new int[n];
for(int i = ; i < n ; i ++ )
arr[i] = i;
srand(time(NULL));
for( int i = ; i < swapTimes ; i ++ ){
int posx = rand()%n;
int posy = rand()%n;
swap( arr[posx] , arr[posy] );
}
return arr;
}
// 拷贝整型数组a中的所有元素到一个新的数组, 并返回新的数组
int *copyIntArray(int a[], int n){
int *arr = new int[n];
copy(a, a+n, arr);
return arr;
}
// 打印arr数组的所有内容
template<typename T>
void printArray(T arr[], int n) {
for (int i = ; i < n; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
// 判断arr数组是否有序
template<typename T>
bool isSorted(T arr[], int n) {
for (int i = ; i < n - ; i++)
if (arr[i] > arr[i + ])
return false;
return true;
}
// 测试sort排序算法排序arr数组所得到结果的正确性和算法运行时间
template<typename T>
void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) {
clock_t startTime = clock();
sort(arr, n);
clock_t endTime = clock();
cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s"<<endl;
assert(isSorted(arr, n));
return;
}
};
#endif //OPTIONAL_02_SHELL_SORT_SORTTESTHELPER_H

选择排序:
基本思想:每一趟在n-i+1(i=1,2,…,n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。直接选择排序和直接插入排序类似,都将数据分为有序区和无序区,所不同的是直接插入排序是将无序区的第一个元素直接插入到有序区以形成一个更大的有序区,而直接选择排序是从无序区选一个最小的元素直接放到有序区的最后。

#ifndef OPTIONAL_02_SHELL_SORT_SELECTIONSORT_H
#define OPTIONAL_02_SHELL_SORT_SELECTIONSORT_H
#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void selectionSort(T arr[], int n){
for(int i = ; i < n ; i ++){
int minIndex = i;
for( int j = i + ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] );
}
}
#endif //OPTIONAL_02_SHELL_SORT_SELECTIONSORT_H

插入排序:
基本思想:将一个记录插入到已排好序的有序表中,从而得到一个新的、记录数增1的有序表。
时间复杂度为O(n^2),若待排记录序列为正序,时间复杂度可提高至O(n);空间上只需要一个记录的辅助空间。

#ifndef OPTIONAL_02_SHELL_SORT_INSERTIONSORT_H
#define OPTIONAL_02_SHELL_SORT_INSERTIONSORT_H
#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void insertionSort(T arr[], int n){
for( int i = ; i < n ; i ++ ) {
T e = arr[i];
int j;
for (j = i; j > && arr[j-] > e; j--)
arr[j] = arr[j-];
arr[j] = e;
}
return;
}
#endif //OPTIONAL_02_SHELL_SORT_INSERTIONSORT_H

冒泡排序:
基本思想:首先将第一个记录的关键字和第二个记录的关键字进行比较,若为逆序,则将两个记录交换之,然后比较第二个记录和第三个记录的关键字。依次类推,直至第n-1个记录和第n个记录的关键字进行过比较为止。上述过程称做第一趟冒泡排序,其结果使得关键字最大的记录被安置到最后一个记录的位置上。然后进行第二趟冒泡排序,对前n-1个记录进行同样操作,其结果是使关键字次大的记录被安置到第n-1个记录的位置上。一般地,第i趟冒泡排序是从1到n-i+1依次比较相邻两个关键字,并在“逆序”时交换相邻记录,其结果是这n-i+1个记录中关键字最大的记录被交换到第n-i+1的位置上。判别冒泡排序结束的条件应该是“在一趟排序过程中没有进行过交换记录的操作”。

#ifndef OPTIONAL_02_SHELL_SORT_BUBBLESORT_H
#define OPTIONAL_02_SHELL_SORT_BUBBLESORT_H#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void bubbleSort( T arr[] , int n){
int newn; // 使用newn进行优化
do{
newn = ;
for( int i = ; i < n ; i ++ )
if( arr[i-] > arr[i] ){
swap( arr[i-] , arr[i] );
// 记录最后一次的交换位置,在此之后的元素在下一轮扫描中均不考虑
newn = i;
}
n = newn;
}while(newn > );
}
#endif //OPTIONAL_02_SHELL_SORT_BUBBLESORT_H

希尔排序与测试:
基本思想:先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。可以看出希尔排序其实只是改进了的插入排序,因此上面的插入排序也被称为直接插入排序。
特点:子序列的构成不是简单地“逐段分割”,而是将相隔某个“增量”的记录组成一个子序列。它通过比较相距一定间隔的元素来工作;各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止。

#include <iostream>
#include "SortTestHelper.h"
#include "SelectionSort.h"
#include "InsertionSort.h"
#include "BubbleSort.h"
using namespace std;
template<typename T>
void shellSort(T arr[], int n){
// 计算 increment sequence: 1, 4, 13, 40, 121, 364, 1093...
int h = ;
while( h < n/ )
h = * h + ;
while( h >= ){
// h-sort the array
for( int i = h ; i < n ; i ++ ){
// 对 arr[i], arr[i-h], arr[i-2*h], arr[i-3*h]... 使用插入排序
T e = arr[i];
int j;
for( j = i ; j >= h && e < arr[j-h] ; j -= h )
arr[j] = arr[j-h];
arr[j] = e;
}
h /= ;
}
}
// 比较SelectionSort, InsertionSort和BubbleSort和ShellSort四种排序算法的性能效率
// ShellSort是这四种排序算法中性能最优的排序算法
int main() {
int n = ;
// 测试1 一般测试
cout<<"Test for random array, size = "<<n<<", random range [0, "<<n<<"]"<<endl;
int *arr1 = SortTestHelper::generateRandomArray(n,,n);
int *arr2 = SortTestHelper::copyIntArray(arr1, n);
int *arr3 = SortTestHelper::copyIntArray(arr1, n);
int *arr4 = SortTestHelper::copyIntArray(arr1, n);
SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n);
SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n);
SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n);
SortTestHelper::testSort("Shell Sort", shellSort, arr4, n);
delete[] arr1;
delete[] arr2;
delete[] arr3;
delete[] arr4;
cout<<endl;
// 测试2 测试近乎有序的数组,只有100个数字无序
int swapTimes = ;
cout<<"Test for nearly ordered array, size = "<<n<<", swap time = "<<swapTimes<<endl;
arr1 = SortTestHelper::generateNearlyOrderedArray(n, swapTimes);
arr2 = SortTestHelper::copyIntArray(arr1, n);
arr3 = SortTestHelper::copyIntArray(arr1, n);
arr4 = SortTestHelper::copyIntArray(arr1, n);
SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n);
SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n);
SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n);
SortTestHelper::testSort("Shell Sort", shellSort, arr4, n);
delete[] arr1;
delete[] arr2;
delete[] arr3;
delete[] arr4;
return ;
}

测试结果:

四个O(n^2)级别的排序性能测试的更多相关文章

  1. 【Mysql】事务的四种特性和隔离级别

    四种特性: 原子性(Atomicity):事务里所有操作视为一个整理,要么全部完成,要么全回滚. 一致性(Consistency):操作前后,数据库内数据逻辑上一致.比如:1w元转账给不同的人,转出去 ...

  2. 【概念原理】四种SQL事务隔离级别和事务ACID特性

    摘要: SQL事务隔离级别和事务的ACID特性 事务是一组读写操作,并且具有只有所有操作都成功才算成功的特性.   事务隔离级别 SQL事务隔离级别由弱到强分别是:READ_UNCOMMITTED.R ...

  3. mysql必知必会(四、检索数据,五、排序检索数据,六、过滤数据,七、数据过滤)

    四.select语句 1.检索单个列 select prod_name from products; 2.检索多个列 select prod_name, prod_price from product ...

  4. O(n^2) 级别的排序算法

    o(n^2) 的排序算法.性能那么差,为什么还要学习? 首先,它是基础,千里之行,始于足下.它编码简单,容易实现,是一些简单情景的首选,它能给我们的问题一个暴力的解法,这样的解法也许不是最优的,但是它 ...

  5. ztree使用系列四(ztree实现同级拖拽排序并将排序结果保存数据库)

    ztree这个系列的最后一篇,也是ztree功能强大的体现之中的一个--排序功能. ztree能够实现全部节点之间任意的拖拽排序功能.我这里依据须要实现了仅仅同意同级之间任意拖拽排序,事实上原理都一样 ...

  6. CentOS(四)--Linux系统的启动级别

    对于绝大多数Linux程序员来说,进入Linux系统后一般看到的是黑乎乎的界面(开发模式),因为系统如果启动选择开发模式,会减少启动时间,优化内存等.但是通常我们刚安装完Linux系统,然后进去以后是 ...

  7. 四十:数据库之SQLAlchemy实现排序的三种方式

    SQLAlchemy实现排序有三种方式一:order_by:查询的时候使用此方式根据某个字段或模型下的属性进行排序二:模型定义的时候,指定排序方式三:一对多的时候,relationship的order ...

  8. hihoCoder hiho一下 第四十八周 题目1 : 拓扑排序·二

    题意: 给定一个拓扑图,其中部分结点含有1个病毒,每个结点只要收到病毒就会立即往出边所能到达的点传播,病毒数可叠加,求所有结点的病毒数总和. 思路: 根据拓扑的特点,每个入度为0的点肯定不会再被传播病 ...

  9. 十四、new Comparator<T>实现多重排序结果

    1.编写实现类 package com.abcd; public class Person{ private String name; private int age; private int sal ...

随机推荐

  1. navicat 几个 可用的东西

    1.常用的 表格 一启动 就进入的某某连接某某数据库某某表 2. 结构 比对(菜单栏 “工具里面”) 3.数据对比 同上 4.保持连接 5.全局查询 在工具中查找 ------在数据库或模式中查找

  2. 深入分析.NET应用程序SQL注入【危害】

    前言:   前面我们已经简单的剖析了一下.NET应用程序SQL注入.没有看过的朋友移步:http://bbs.ichunqiu.com/thread-7636-1-1.html,在上一篇文章我们已经了 ...

  3. 脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?

    本文引用了公众号纯洁的微笑作者奎哥的技术文章,感谢原作者的分享. 1.前言   老于网络编程熟手来说,在测试和部署网络通信应用(比如IM聊天.实时音视频等)时,如果发现网络连接超时,第一时间想到的就是 ...

  4. rem计算

    //jquery实现 // $(function(){ // $(window).on("resize",function(){ // var width=$(window).wi ...

  5. 从前端中的IOC理念理解koa中的app.use()

    忙里偷闲,打开平时关注的前端相关的网站,浏览最近最新的前端动态.佼佼者,平凡的我做不到,但还是要争取不做落后者. 前端中的IoC理念,看到这个标题就被吸引了.IoC 理念,不认识呢,点击去一看,果然没 ...

  6. ES6的Promise

    推荐一下我觉得不错关于Promise的好文章,通俗易懂 说起ES6的Promise就要提及一下JQ的$.when()方法,两者基本相同 面试的时候经常会问Promise,如果同学们能在回答Promis ...

  7. html标签详解(1)

     http标签详解及讲解        1.基础标签 <!DOCTYPE html> <!--表示文本类型--> <html> <!--<html> ...

  8. 提升 PLSQL 开发性能漫谈

    本文内容摘自<剑破冰山--Oracle开发艺术>一书,有删改. 1.触发器尽量考虑内部代码过程封装(解析次数) 2.避免动态 SQL 动态 SQL 和普通 SQL 在执行过程中最大的差别在 ...

  9. Thrift 基于zookeeper改造模式

    对于Thrift服务化的改造,主要是客户端,可以从如下几个方面进行: 1.服务端的服务注册,客户端自动发现,无需手工修改配置,这里我们使用zookeeper,但由于zookeeper本身提供的客户端使 ...

  10. 项目详解2—LVS负载均衡详解

    一.负载均衡集群介绍 1.集群 ① 集群(cluster)技术是一种较新的技术,通过集群技术,可以在付出较低成本的情况下获得在性能.可靠性.灵活性方面的相对较高的收益,其任务调度则是集群系统中的核心技 ...