今天写完了做完了快速排序的实验,每组实验数据集有999999个,实验结果如下:
优化方法 | 随机数组 | 升序数组 | 重复数组 |
---|---|---|---|
原始算法 | 77ms | 164137ms | 44488ms |
随机枢轴 | 123ms | 64ms | 42905ms |
三数取中 | 84ms | 19ms | 42807ms |
三数取中+直排 | 93ms | 15ms | 43858ms |
三数取中+直排+“聚key” | 87ms | 21ms | 9ms |
STL-sort() | 74ms | 13ms | 3ms |
主方法代码
// Qksort.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "ReadFile.h"
#include "MethodA.h"
#include"MethodB.h"
#include "MethodC.h"
#include "InsertSort.h"
#include "MethodD.h"
#include"MethodE.h"
#include "time.h"
#include <algorithm>
using namespace std;
int main()
{
int size;
//得到数据集的数组
int *arr= ReadFile().GetArray("E://Sort_data//repeat.txt",size);
clock_t start, finish;
double useTime;
cout << "排序开始";
start= clock();
//原始排序算法
//int* result = MethodA(arr).QuickSort(0, size - 1);
//随机枢轴
//int* result = MethodB(arr).QuickSort(0, size - 1);
//三数取中
//int* result = MethodC(arr).QuickSort(0, size - 1);
//三数取中+插排的算法
int* result = MethodD(arr).QuickSort(0, size - 1);
//三数取中+插排+聚“key”算法
//int *result = MethodE(arr).QuickSort(0, size - 1);
//STL-sort算法
//sort(arr, arr + size);
finish = clock();
useTime = (double)(finish - start) / CLOCKS_PER_SEC*1000;
printf("%f 毫秒\n", useTime);
//插入排序结果验证
//int* result = InsertSort(arr).Sort(0, size - 1);
//ReadFile().SetArray("E://Sort_data//min.txt", arr, size);
//验证的排序结果
/*for (int i = 0; i<size; i++)
cout << arr[i] << " ";
cout << endl;*/
system("pause");
}
原始算法
medthodA.h
#pragma once
using namespace std;
//算法A:原始算法
class MethodA
{
public:
MethodA(int* arr);
~MethodA();
int* QuickSort(int p, int q);
int Partition(int p, int q);
void exchange(int a, int b);
int* A;
};
medthodA.cpp
#include "stdafx.h"
#include "MethodA.h"
#include "Stack.h"
MethodA::MethodA(int* arr)
{
A = arr;
}
MethodA::~MethodA()
{
}
int* MethodA::QuickSort( int p, int r)
{
/*if (p < r)
{
int q = Partition( p, r);
QuickSort(p, q - 1);
QuickSort(q + 1,r);
}
return A;*/
Stack stack(r+1);
int q;
stack.push(p);
stack.push(r);
while (!stack.empty()) {
r = stack.pop();
p = stack.pop();
q= Partition( p, r);
if (p<q- 1) {
stack.push(p);
stack.push(q - 1);
}
if (q + 1<r) {
stack.push(q + 1);
stack.push(r);
}
}
return A;
}
int MethodA::Partition( int p, int r)
{
int x = A[p];
while (p<r)
{
while (p<r&&A[r]>x) r--;
A[p] = A[r];
while (p<r&&A[p]<=x) p++;
A[r] = A[p];
}
A[p] = x;
return p;
}
void MethodA::exchange(int a, int b)
{
int x = A[a];
A[a] = A[b];
A[b] = x;
}
随机枢轴算法
medthodB.h
#pragma once
using namespace std;
//随机枢轴选取的快排算法
class MethodB
{
public:
MethodB(int* ve);
~MethodB();
int* QuickSort(int p, int q);
int Partition(int p, int q);
void exchange(int a, int b);
int* A;
};
medthodB.cpp
#include "stdafx.h"
#include "MethodB.h"
#include "stdlib.h"
#include "time.h"
#include "Stack.h"
MethodB::MethodB(int* ve)
{
A = ve;
}
MethodB::~MethodB()
{
}
int* MethodB::QuickSort(int p, int r)
{
/*if (p < r)
{
int q = Partition(p, r);
QuickSort(p, q - 1);
QuickSort(q + 1, r);
}
return A;*/
Stack stack(r + 1);
int q;
stack.push(p);
stack.push(r);
while (!stack.empty()) {
r = stack.pop();
p = stack.pop();
q = Partition(p, r);
if (p<q - 1) {
stack.push(p);
stack.push(q - 1);
}
if (q + 1<r) {
stack.push(q + 1);
stack.push(r);
}
}
return A;
}
int MethodB::Partition(int p, int r)
{
//生成随机的枢轴
srand(r);
int t = rand()%(r-p)+p;
exchange(t, p);
//下同原始快速排序
int x = A[p];
while (p<r)
{
while (p<r&&A[r]>x) r--;
A[p] = A[r];
while (p<r&&A[p] <= x) p++;
A[r] = A[p];
}
A[p] = x;
return p;
}
void MethodB::exchange(int a, int b)
{
int x = A[a];
A[a] = A[b];
A[b] = x;
}
三数取中算法
medthodC.h
#pragma once
using namespace std;
//随机三数取中的快排算法
class MethodC
{
public:
MethodC(int* ve);
~MethodC();
int* QuickSort(int p, int q);
int Partition(int p, int q);
void exchange(int a, int b);
int getMid(int a, int b, int c);
int* A;
};
medthodC.cpp
#include "stdafx.h"
#include "MethodC.h"
#include "Stack.h"
MethodC::MethodC(int* ve)
{
A = ve;
}
MethodC::~MethodC()
{
}
int* MethodC::QuickSort(int p, int r)
{
/*if (p < r)
{
int q = Partition(p, r);
QuickSort(p, q - 1);
QuickSort(q + 1, r);
}
return A;*/
Stack stack(r + 1);
int q;
stack.push(p);
stack.push(r);
while (!stack.empty()) {
r = stack.pop();
p = stack.pop();
q = Partition(p, r);
if (p<q - 1) {
stack.push(p);
stack.push(q - 1);
}
if (q + 1<r) {
stack.push(q + 1);
stack.push(r);
}
}
return A;
}
int MethodC::Partition(int p, int r)
{
//生成随机的枢轴
int t = getMid(p, (p + r) / 2, r);
exchange(t, p);
//下同原始快速排序
int x = A[p];
while (p<r)
{
while (p<r&&A[r]>x) r--;
A[p] = A[r];
while (p<r&&A[p] <= x) p++;
A[r] = A[p];
}
A[p] = x;
return p;
}
void MethodC::exchange(int a, int b)
{
int x = A[a];
A[a] = A[b];
A[b] = x;
}
int MethodC::getMid(int a, int b, int c)
{
if ((A[a] > A[b] && A[a] < A[c])||(A[a]>A[c]&&A[a]<A[b]))
{
return a;
}
else if ((A[b] > A[a] && A[b] < A[c]) || (A[b]<A[a] && A[b]>A[c]))
{
return b;
}
else
return c;
}
三数取中+直排算法
medthodD.h
#pragma once
using namespace std;
class MethodD
{
public:
MethodD(int *arr);
~MethodD();
int* QuickSort( int p, int q);
int Partition(int p, int q);
void exchange(int a, int b);
int getMid(int a, int b, int c);
int N;
int *A;
};
medthodD.cpp
#include "stdafx.h"
#include "MethodD.h"
#include "InsertSort.h"
#include "Stack.h"
MethodD::MethodD(int *arr)
{
A = arr;
N = 1000;
}
MethodD::~MethodD()
{
}
int* MethodD::QuickSort(int p, int r)
{
if (p < r)
{
int q = Partition(p, r);
if (r - p>N - 1)
{
Stack stack(r + 1);
int q;
stack.push(p);
stack.push(r);
while (!stack.empty()) {
r = stack.pop();
p = stack.pop();
q = Partition(p, r);
if (p<q - 1) {
stack.push(p);
stack.push(q - 1);
}
if (q + 1<r) {
stack.push(q + 1);
stack.push(r);
}
}
}
else
{
A=InsertSort(A).Sort(p, r);
}
}
return A;
}
int MethodD::Partition(int p, int r)
{
//生成随机的枢轴
int t = getMid(p, (p + r) / 2, r);
exchange(t, p);
int x = A[p];
while (p<r)
{
while (p<r&&A[r]>x) r--;
A[p] = A[r];
while (p<r&&A[p] <= x) p++;
A[r] = A[p];
}
A[p] = x;
return p;
}
void MethodD::exchange(int a, int b)
{
int x = A[a];
A[a] = A[b];
A[b] = x;
}
int MethodD::getMid(int a, int b, int c)
{
if ((A[a] > A[b] && A[a] < A[c]) || (A[a]>A[c] && A[a]<A[b]))
{
return a;
}
else if ((A[b] > A[a] && A[b] < A[c]) || (A[b]<A[a] && A[b]>A[c]))
{
return b;
}
else
return c;
}
三数取中+直排+聚“key”算法
medthodE.h
#pragma once
class MethodE
{
public:
MethodE(int *arr);
~MethodE();
int* QuickSort(int p, int q);
void Partition(int p, int r,int &q1,int &q2);
void exchange(int a, int b);
int getMid(int a, int b, int c);
int N;
int *A;
};
medthodE.cpp
#include "stdafx.h"
#include "MethodE.h"
#include "InsertSort.h"
#include "Stack.h"
MethodE::MethodE(int *arr)
{
A = arr;
N = 1000;
}
MethodE::~MethodE()
{
}
int* MethodE::QuickSort(int p, int r)
{
int q1;
int q2;
if (p < r)
{
Partition(p, r, q1, q2);
if (r - p>N - 1)
{
Stack stack(r + 1);
stack.push(p);
stack.push(r);
while (!stack.empty()) {
r = stack.pop();
p = stack.pop();
Partition(p, r,q1,q2);
//中间的不用排
if (p<q1 - 1) {
stack.push(p);
stack.push(q1 - 1);
}
if (q2+ 1<r) {
stack.push(q2 + 1);
stack.push(r);
}
}
}
else
{
A = InsertSort(A).Sort(p, r);
}
}
return A;
}
void MethodE::Partition(int p, int r,int &q1,int &q2)
{
//生成随机的枢轴
int t = getMid(p, (p + r) / 2, r);
exchange(t, p);
q1 = p - 1;
q2 = r + 1;
int size1=0;
int size2=0;
int x = A[p];
while (p<r)
{
while (p<r&&A[r]>=x)
{
if (A[r] == x)
{
q2--;
size2++;
exchange(r, q2);
}
r--;
}
A[p] = A[r];
while (p < r&&A[p] <= x)
{
if (A[r] == x)
{
q1++;
size1++;
exchange(r, q1);
}
p++;
}
A[r] = A[p];
}
A[p] = x;
r = p;
for (int i = 0; i < size1; i++)
{
p--;
exchange(q1, p);
q1--;
}
q1 = p;
for (int i = 0; i < size2; i++)
{
r++;
exchange(q2, r);
q2++;
}
q2 = r;
}
void MethodE::exchange(int a, int b)
{
int x = A[a];
A[a] = A[b];
A[b] = x;
}
int MethodE::getMid(int a, int b, int c)
{
if ((A[a] > A[b] && A[a] < A[c]) || (A[a]>A[c] && A[a]<A[b]))
{
return a;
}
else if ((A[b] > A[a] && A[b] < A[c]) || (A[b]<A[a] && A[b]>A[c]))
{
return b;
}
else
return c;
}
其他辅助
ReadFile.cpp
#include "stdafx.h"
#include "ReadFile.h"
ReadFile::ReadFile()
{
}
ReadFile::~ReadFile()
{
}
int * ReadFile::GetArray(char* filename,int &size)//获取文件的行数
{
ifstream ReadFile;
int temp;
ReadFile.open(filename, ios::in);//ios::in 表示以只读的方式读取文件
vector<int> ve;
while (ReadFile >> temp) //按空格读取,遇到空白符结束
{
ve.push_back(temp);
}
size=ve.size();
int *arr = new int[size];
for (int i = 0; i < size; i++)
{
arr[i] = ve[i];
}
ve.clear();
ReadFile.close();
return arr;
}
void * ReadFile::SetArray(char * filename,int * arr,int n)
{
//写入算法
ofstream in;
in.open(filename, ios::trunc);//ios::trunc表示在打开文件前将文件清空,由于是写入,文件不存在则创建
for (int i = 0; i < n; i++)
{
in << arr[i] << ' ';
}return NULL;
}
Stack.cpp
#include "stdafx.h"
#include "Stack.h"
Stack::Stack(int s)
{
stack = new int[s];
size = s;
length = 0;
}
Stack::~Stack()
{
}
void Stack::push(int number)
{
if(length<size)
{
stack[length] = number;
length++;
}
else
{
printf("对不起栈已满");
}
}
int Stack::pop()
{
if (!empty())
{
return stack[--length];
}
else
return NULL;
}
InsertSort.cpp
#include "stdafx.h"
#include "InsertSort.h"
InsertSort::InsertSort(int* ve)
{
A = ve;
}
InsertSort::~InsertSort()
{
}
int * InsertSort::Sort(int p, int q)
{
for (int i = p; i <= q; i++)
{
for (int j = p; j <i; j++)
{
if (A[i]<A[j])
{
int tmp = A[i];
for (int k = i- 1; k >= j; k--)
{
A[k + 1] = A[k];
}
A[j] = tmp;
break;
}
}
}
return A;
}