辅助排序测试用例的函数
#include <iostream>
#include <ctime>
#include <cassert>
using namespace std;
namespace SortTestHelper {
// 生成有n个元素的随机数组,每个元素的随机范围为[rangeL, rangeR]
int *generateRandomArray(int n, int rangeL, int rangeR) {
assert(rangeL <= rangeR);
int *arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; i++)
arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
return arr;
}
// 生成一个近乎于有序的随机数组(将有序数组中的几个数进行交换)
// n指数组长度 swapTimes指交换次数
int *generateNearlyOrderedArray(int n, int swapTimes){
int *arr = new int[n];
for(int i = 0 ; i < n ; i ++ )
arr[i] = i;
srand(time(NULL));
for( int i = 0 ; i < swapTimes ; i ++ ){
int posx = rand()%n;
int posy = rand()%n;
swap( arr[posx] , arr[posy] );
}
return arr;
}
// 输出随机数组的模板函数
template<typename T>
void printArray(T arr[], int n) {
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
//判断排序是否成功
template<typename T>
bool isSorted(T arr[], int n) {
for (int i = 0; i < n - 1; i++)
if (arr[i] > arr[i + 1])
return false;
return true;
}
//计算运行时间的模板函数
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();
assert(isSorted(arr, n)); //验证数组是否有序
cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl;
return;
}
//复制整型数组功能的函数
int *copyIntArray(int a[], int n){
int *arr = new int[n];
copy(a, a+n, arr);
return arr;
}
};
自定义结构体(自定义数据类型)
#include <iostream>
#include <string>
using namespace std;
// 自定义Student结构体
struct Student{
string name;
int score;
bool operator<(const Student& otherStudent){
return score != otherStudent.score ?
score > otherStudent.score : name < otherStudent.name;
}
friend ostream& operator<<(ostream &os, const Student &student){
os<<"Student: "<<student.name<<" "<<student.score<<endl;
return os;
}
};
排序算法
O(n^2)的排序算法
选择排序(Selection Sort) 性能最低
插入排序(Insertion Sort) 性能可能高,可能低
冒泡排序(Bubble Sort) 不如插入排序
希尔排序(Shell Sort) 插入排序的延申 这些排序中最优
//选择排序
template<typename T>
void selectionSort(T arr[], int n){
for(int i = 0 ; i < n ; i ++){
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] ); //老版本 swap()函数在#include<algorithm>
}
}
//插入排序
template<typename T>
void insertionSort(T arr[], int n){
for( int i = 1 ; i < n ; i ++ ) {
// 寻找元素arr[i]合适的插入位置
// 写法1
// for( int j = i ; j > 0 ; j-- )
// if( arr[j] < arr[j-1] )
// swap( arr[j] , arr[j-1] );
// else
// break;
// 写法2
// for( int j = i ; j > 0 && arr[j] < arr[j-1] ; j -- )
// swap( arr[j] , arr[j-1] );
// 写法3
T e = arr[i];
int j; // j保存元素e应该插入的位置
for (j = i; j > 0 && arr[j-1] > e; j--)
arr[j] = arr[j-1];
arr[j] = e;
}
return;
}
//冒泡排序
template<typename T>
void bubbleSort( T arr[] , int n){
bool swapped;
//int newn; // 理论上,可以使用newn进行优化,但实际优化效果较差
do{
swapped = false;
//newn = 0;
for( int i = 1 ; i < n ; i ++ )
if( arr[i-1] > arr[i] ){
swap( arr[i-1] , arr[i] );
swapped = true;
// 可以记录最后一次的交换位置,在此之后的元素在下一轮扫描中均不考虑
// 实际优化效果较差,因为引入了newn这个新的变量
//newn = n;
}
//n = newn;
// 优化,每一趟Bubble Sort都将最大的元素放在了最后的位置
// 所以下一次排序,最后的元素可以不再考虑
// 理论上,newn的优化是这个优化的复杂版本,应该更有效
// 实测,使用这种简单优化,时间性能更好
n --;
}while(swapped);
}
//希尔排序
template<typename T>
void shellSort(T arr[], int n){
int h = 1;
while( h < n/3 )
h = 3 * h + 1;
// 计算 increment sequence: 1, 4, 13, 40, 121, 364, 1093...
while( h >= 1 ){
// 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 /= 3;
}
}
主函数中测试模板函数
int main() {
// 测试模板函数,传入整型数组
int a[10] = {10,9,8,7,6,5,4,3,2,1};
selectionSort( a , 10 );
for( int i = 0 ; i < 10 ; i ++ )
cout<<a[i]<<" ";
cout<<endl;
// 测试模板函数,传入浮点数数组
float b[4] = {4.4,3.3,2.2,1.1};
selectionSort(b,4);
for( int i = 0 ; i < 4 ; i ++ )
cout<<b[i]<<" ";
cout<<endl;
// 测试模板函数,传入字符串数组
string c[4] = {"D","C","B","A"};
selectionSort(c,4);
for( int i = 0 ; i < 4 ; i ++ )
cout<<c[i]<<" ";
cout<<endl;
// 测试模板函数,传入自定义结构体Student数组
Student d[4] = { {"D",90} , {"C",100} , {"B",95} , {"A",95} };
selectionSort(d,4);
for( int i = 0 ; i < 4 ; i ++ )
cout<<d[i];
cout<<endl;
//选择排序与插入排序的比较
int n = 10000;
cout<<"Test for Random Array, size = "<<n<<", random range [0, "<<n<<"]"<<endl;
int *arr1 = SortTestHelper::generateRandomArray(n,0,n);
int *arr2 = SortTestHelper::copyIntArray(arr1, n);
SortTestHelper::testSort("Insertion Sort", insertionSort,arr1,n);
SortTestHelper::testSort("Selection Sort", selectionSort,arr2,n);
delete[] arr1;
delete[] arr2;
cout<<endl;
return 0;
}