以下代码包含 冒泡排序、选择排序、插入排序、谢尔排序、堆排序、归并排序、快速排序
这伙是测试用数据类
waitForSort.h
#ifndef WAITFORSORT_H
#define WAITFORSORT_H
#include <iostream>
#include "time.h"
const int MAXSIZE = 1000;
class waitForSort
{
public:
int data[MAXSIZE];
int length;
waitForSort(const int, const int);
void swap(const int, const int);
void outPut();
};
#endif
waitForSort.cpp
#include "waitForSort.h"
waitForSort::waitForSort(const int n, const int range) : length(n){
srand(static_cast<int>(time(0)));
for(int iter = 0; iter != n; ++iter)
data[iter] = rand() % range;
}
void waitForSort::swap(const int a, const int b){
int temp = data[a];
data[a] = data[b];
data[b] = temp;
}
void waitForSort::outPut(){
for(int iter = 0; iter != length; ++iter){
if(iter % 10 == 0)
std::cout<<std::endl;
std::cout<<data[iter]<<" ";
}
}
ok,上算法...
Sorting.h
#include "waitForSort.h"
#include <math.h>
/**********************冒泡排序(改)**********************/
void BubbleSort(waitForSort &L){
const int NUM = L.length - 1;//空间换时间
bool flag = true;
for(int iter = 0; iter != NUM && flag; iter++){
flag = false;
for(int r = NUM; r != iter; r--){
if(L.data[r] < L.data[r - 1]){
L.swap(r - 1, r);
flag = true;
}
}
}
}
/**********************选择排序**********************/
void SelectSort(waitForSort &L){
const int NUM = L.length - 1;
int min;
for(int iter = 0; iter != NUM; iter++){
min = iter;
for(int r = iter + 1; r != L.length; r++)
if(L.data[r] < L.data[min]){
min = r;
}
if(min != iter)
L.swap(min, iter);
}
}
/**********************插入排序**********************/
void InsertSort(waitForSort &L){
int temp, iter, r;
const int NUM = L.length - 1;
for(iter = 0; iter != NUM; iter++){
if(L.data[iter] > L.data[iter + 1]){
temp = L.data[iter + 1];
for(r = iter; L.data[r] > temp && r >= 0; r--)//此处要注意,防止越界
L.data[r + 1] = L.data[r];
L.data[r + 1] = temp;
}
}
}
/**********************谢尔排序**********************/
//谢尔排序可以看作选择排序的改进版,基本思想是通过元素的大
//范围跃迁减少不必要的迭代次数,从而降低时间复杂度。
void InsertShell(const int &gap, const int &NUM, waitForSort &L){
int iter, r, temp;
for(iter = gap; iter <= NUM; iter++){
temp = L.data[iter];
for(r = iter; r >= gap && L.data[r - gap] > temp; r -= gap)
L.data[r] = L.data[r - gap];
L.data[r] = temp;
}
}
void ShellSort(waitForSort &L, int key){
const int NUM = L.length - 1;
int k = 0, p[20];
int sedgewick[] = {//实践中总结出来的一个比较高效的增量集合
1073643521, 603906049, 268386305, 150958081, 67084289,
37730305, 16764929, 9427969, 4188161, 2354689,
1045505, 587521, 260609, 146305, 64769,
36289, 16001, 8929, 3905, 2161,
929, 505, 209, 109, 41,
19, 5, 1, 0};
switch(key){
case 1://使用谢尔增量
for(int gap = NUM / 2; gap > 0; gap /= 2)
InsertShell(gap, NUM, L);
break;
case 0://使用Hibbard增量
for(int iter = 0; iter != 20; iter++, k++){
p[iter] = pow(static_cast<double>(2), iter + 1) - 1;
if(p[iter] > NUM)
break;
}
while(k != 0){
InsertShell(p[--k], NUM, L);
}
break;
case -1://使用经验增量
while(sedgewick[k] > NUM)
k++;
k--;
while(sedgewick[k] > 0){
InsertShell(sedgewick[k++], NUM, L);
}
break;
}
}
/**********************堆排序**********************/
//堆,本质上是拥有特殊性质的完全二叉树
//makeHeap函数,将处于第i层的节点与其 已形成大顶堆
//的子树调整为一个新的大顶堆!
void makeHeap(waitForSort &L, int start, int end){//start, end均为第x个元素(A类),为(下标数 + 1)
int temp;
temp = L.data[start - 1];
for(int iter = 2 * start; iter <= end; iter *= 2){//attention! iter为A类数据
if(iter < end && L.data[iter - 1] < L.data[iter])//若left child < right child
++iter;
if(temp >= L.data[iter - 1])//可以看到,这里运用了选择排序的思想
break;
L.data[start - 1] = L.data[iter - 1];
start = iter;
}
L.data[start - 1] = temp;
}
void HeapSort(waitForSort &L){
int iter;//A类数据
for(iter = L.length / 2; iter > 0; --iter)//iter指向的是每个拥有子树的节点,从后往前遍历
makeHeap(L, iter, L.length);
for(iter = L.length; iter > 1; --iter){
L.swap(0, iter - 1);//将大顶堆的根节点(当前最大值)移至数据尾部
makeHeap(L, 1, iter - 1);
}
}
/**********************归并排序(递归版本)**********************/
void Merge(int left[], int right[], int a, int b, int c){//将left[a to b] 与 left[b + 1 to c]归并到right[a to b], abc为数组下标
int R_iter = a, A_stop = b;
for(++b; a <= A_stop && b <= c; ++R_iter)
right[R_iter] = left[a] < left[b] ? left[a++] : left[b++];//将下标a,b指向的值的较小者归入rigth[r_iter]
for(; a <= A_stop; ++R_iter)
right[R_iter] = left[a++];//将剩余值归并
for(; b <= c; ++R_iter)
right[R_iter] = left[b++]; //同上
}
void MSort(int left[], int right[], int a, int b){//分割元素后归并
if(a == b){
right[a] = left[a];
return;
}
else{
int TempSave[MAXSIZE];
int mid = (a + b) / 2;
MSort(left, TempSave, a, mid);
MSort(left, TempSave, mid + 1, b);
Merge(TempSave, right, a, mid, b);
}
}
void MergeSort_1(waitForSort &L){//这种编程方法有利于封装
MSort(L.data, L.data, 0, L.length - 1);
}
/**********************归并排序(迭代版本)**********************/
//俗话说,能不用递归就不用递归,为了保证空间跟时间复杂度,下面
//给出迭代版本
//将重用上面定义的Merge方法
void MergeStep(int left[], int right[], int width, int end){//注意,end为A类数据
int i = 1;
while(i <= end - 2 * width + 1){
Merge(left, right, i - 1, i + width - 2, i + 2 * width - 2);//宽度为width的数据两两归并
i += 2 * width;
}
if(i < end - width + 1)
Merge(left, right, i - 1, i + width - 2, end - 1);
else
for(int iter = i - 1; iter < end; ++iter)//此处可用以防止出现width>end的情况出现
right[iter] = left[iter];
}
void MergeSort_2(waitForSort &L){
int *p = new int[L.length];//用同一片地址来存储中间数据~
int k = 1;
while(k < L.length){
MergeStep(L.data, p, k, L.length);
k *= 2;
MergeStep(p, L.data, k, L.length);
k *= 2;
}
}
/**********************快速排序**********************/
//思路很简单,没啥好说的..
int Location(waitForSort &L, int low, int high){
int Key;
Key = L.data[low];//简单的取首值
while(low < high){
while(low < high && L.data[high] >= Key){
--high;
}
L.swap(low, high);
while(low < high && L.data[low] <= Key){
++low;
}
L.swap(low, high);
}
return low;
}
void QuickSortRecursion(waitForSort &L, int low, int high){
int pivot;//中轴
if(low < high){
pivot = Location(L, low, high);
QuickSortRecursion(L, low, pivot - 1);
QuickSortRecursion(L, pivot + 1, high);
}
}
void QuickSort(waitForSort &L){
QuickSortRecursion(L, 0, L.length - 1);
}
/**********************快排优化版**********************/
int better_Location(waitForSort &L, int low, int high){
int Key;
//Key = L.data[low];//简单的去首值
//优化1
int mid = (high + low) / 2;
if(L.data[low] > L.data[high])
L.swap(low, high);
if(L.data[mid] > L.data[high])
L.swap(mid, high);
if(L.data[low] < L.data[mid])
L.swap(mid, low);//low所指向的数为三数间的中间数,此为三数取中法。可考虑增加抽样率提高准确性
Key = L.data[low];
///
//优化2
while(low < high){
while(low < high && L.data[high] >= Key){
--high;
}
//L.swap(low, high);
L.data[low] = L.data[high];
while(low < high && L.data[low] <= Key){
++low;
}
//L.swap(low, high);
L.data[high] = L.data[low];
}
L.data[low] = Key;
return low;
}
///优化3///
void better_QuickSortRecursion(waitForSort &L, int low, int high){
int pivot;//中轴
if((high - low) > 50){//超过50时用快排,否则直接插入排序
while(low < high){
pivot = better_Location(L, low, high);
better_QuickSortRecursion(L, low, pivot - 1);
low = pivot + 1;//优化尾递归
}
}
else
InsertSort(L);
}
/
void better_QuickSort(waitForSort &L){
better_QuickSortRecursion(L, 0, L.length - 1);
}