#include<iostream>
#include<stack>
#include<ctime>
#include"CaculateTime.h"
using namespace std;
/*
递归算法,使用 刘大有《数据结构》第二版 里的算法
*/
void QuikSort(int(&a)[100], int low, int high)
{
if (low < high)
{
int front = low;
int back = high + 1;
int item = a[low];
while (front < back)
{
front++;
while (a[front] < item)
front++;
back--;
while (a[back] > item)
back--;
if (front < back)
swap(a[front], a[back]);
}
swap(a[low], a[back]);
QuikSort(a, low, back - 1);
QuikSort(a, back + 1, high);
}
}
/*
在QuikSort基础上写了个迭代法,结果反而比QuikSort慢
*/
void QuikSort_iteration(int(&a)[100], int n)
{
stack<int> s;
s.push(0); //low
s.push(n); //high
while (!s.empty())
{
int low;
int high;
high = s.top();
s.pop();
low = s.top();
s.pop();
if (low < high)
{
int left = low;
int right = high;
int item = a[low];
while (left < right)
{
left++;
while (a[left] < item)
left++;
right--;
while (a[right] > item)
right--;
if (left < right)
swap(a[left], a[right]);
}
swap(a[low], a[right]);
//保存参数
s.push(right + 1);
s.push(high);
s.push(low);
s.push(right - 1);
}
}
}
/*
改进迭代,减少了对栈的操作,速度更快但还是比递归慢很多
据说是因为 STL的栈不适合用在这。。。。
*/
void QuikSort_iteration_EX(int(&a)[100], int n)
{
stack<int> s;
s.push(0); //low
s.push(n); //high
while (!s.empty())
{
int low;
int high;
high = s.top();
s.pop();
low = s.top();
s.pop();
while (low < high)
{
int left = low;
int right = high;
int item = a[low];
while (left < right)
{
left++;
while (a[left] < item)
left++;
right--;
while (a[right] > item)
right--;
if (left < right)
swap(a[left], a[right]);
}
swap(a[low], a[right]);
//保存参数
if (right - low < high - right) //前部分较小
{
//保存后部分
s.push(right + 1);
s.push(high);
high = right - 1;
}
else
{
s.push(low);
s.push(right - 1);
low = right + 1;
}
}
}
}
/*
非递归终极改进版,自己实现栈,速度比递归的快!!!
*/
void QuikSort_iteration_EX_EX(int(&a)[100], int n)
{
int myStack[100];
int top = -1;
myStack[++top] = 0; //low ++top:先top=top+1;再取top的值
myStack[++top] = n; //high
while (top != -1)
{
int low;
int high;
high = myStack[top--]; // top--:先取top的值;再top=top-1
low = myStack[top--];
while (low < high)
{
int left = low;
int right = high;
int item = a[low];
while (left < right)
{
left++;
while (a[left] < item)
left++;
right--;
while (a[right] > item)
right--;
if (left < right)
swap(a[left], a[right]);
}
swap(a[low], a[right]);
//保存参数
if (right - low < high - right) //前部分较小
{
//保存后部分
myStack[++top] = right + 1;
myStack[++top] = high;
high = right - 1;
}
else
{
myStack[++top] = low;
myStack[++top] = right - 1;
low = right + 1;
}
}
}
}
int main()
{
// int n = 20;
// int a[100] = { 2, 4, 6, 23, 7, 4, 8, 13, 56, 467, 3, 9, 56, 24, 56, 4, 58, 23, 12, 0 };
int n = 100;
int a[100];
MyRandom::g_srand();
for (int i = 0; i < 100; i++)
a[i] = MyRandom::g_random_int(0, 100);
CaculateTime caculateTime;
caculateTime.Init();
QuikSort(a, 0, n - 1);
double time1 = caculateTime.getDeltaTime();
cout << "递归时间: " << time1 << " us" << endl;
//打乱顺序
for (int i = 0; i < 100; i++)
a[i] = MyRandom::g_random_int(0, 100);
caculateTime.Init();
QuikSort_iteration(a, n);
double time2 = caculateTime.getDeltaTime();
cout << "迭代时间: " << time2 << " us" << endl;
//打乱顺序
for (int i = 0; i < 100; i++)
a[i] = MyRandom::g_random_int(0, 100);
caculateTime.Init();
QuikSort_iteration_EX(a, n);
double time3 = caculateTime.getDeltaTime();
cout << "迭代_改进版时间: " << time3 << " us" << endl;
//打乱顺序
for (int i = 0; i < 100; i++)
a[i] = MyRandom::g_random_int(0, 100);
caculateTime.Init();
QuikSort_iteration_EX_EX(a, n);
double time4 = caculateTime.getDeltaTime();
cout << "迭代_终极改进版时间: " << time4 << " us" << endl;
cout << "排序后:" << endl;
for (int i = 0; i < n; i++)
cout << a[i] << " ";
cout << endl;
return 0;
}
运行结果:迭代算法还是比较快的
其中CaculateTime.h文件内容
#pragma once
#include<Windows.h>
class CaculateTime
{
public:
static void Init();
static double getDeltaTime() //单位微秒
{
QueryPerformanceCounter(&liPerfEnd);
double dfTime = (double)liPerfEnd.QuadPart - liPerfStart.QuadPart;
double deltaTime = dfTime * 1000 * 1000 / liPerfFreq.QuadPart; //单位微秒
return deltaTime;
}
private:
static LARGE_INTEGER liPerfFreq;
static LARGE_INTEGER liPerfStart;
static LARGE_INTEGER liPerfEnd;
};
LARGE_INTEGER CaculateTime::liPerfFreq = { 0 };
LARGE_INTEGER CaculateTime::liPerfStart = { 0 };
LARGE_INTEGER CaculateTime::liPerfEnd = { 0 };
void CaculateTime::Init()
{
QueryPerformanceFrequency(&liPerfFreq);
QueryPerformanceCounter(&liPerfStart);
}
namespace MyRandom
{
void g_srand()
{
srand(unsigned(time(0)));
}
double g_random_double(double start, double end)
{
return start + (end - start)*rand() / (RAND_MAX + 1.0);
}
int g_random_int(int start, int end)
{
return start + (end - start)*rand() / (RAND_MAX + 1);
}
};