快排优化
實(shí)驗(yàn)一:快速排序算法及其優(yōu)化
編程實(shí)現(xiàn)快速排序
// 編程實(shí)現(xiàn)的快排
void qSort(int n[],int l,int r){
if(l>=r){
return;
}
int i,j;
i=l-1;
j=r+1;
int x = n[ (i+j)/2 ];
while(i<j){
do i++ ;while(n[i]<x);
do j-- ;while(n[j]>x);
if(i<j){
int ten = n[i];
n[i] = n[j];
n[j] = ten;
}
}
qSort(n,l,j);
qSort(n,j+1,r);
}
快速排序的優(yōu)化
1)基準(zhǔn)的選擇
1)基準(zhǔn)的選擇:快速排序的運(yùn)行時(shí)間與劃分是否對(duì)稱有關(guān)。最壞情況下,每次劃分過(guò)程產(chǎn)生兩個(gè)區(qū)域分別包含n-1個(gè)元素和1個(gè)元素,其時(shí)間復(fù)雜度會(huì)達(dá)到O(n^2)。在最好的情況下,每次劃分所取的基準(zhǔn)都恰好是中值,即每次劃分都產(chǎn)生兩個(gè)大小為n/2的區(qū)域。此時(shí),快排的時(shí)間復(fù)雜度為O(nlogn)。
所以基準(zhǔn)的選擇對(duì)快排而言至關(guān)重要??炫胖谢鶞?zhǔn)的選擇方式主要有以下三種:① 固定基準(zhǔn); ② 隨機(jī)基準(zhǔn); ③ 三數(shù)取中
固定基準(zhǔn)
// 編程實(shí)現(xiàn)的快排
// 固定基準(zhǔn)
void qSort(int n[],int l,int r){
if(l>=r){
return;
}
int i,j;
i=l-1;
j=r+1;
int x = n[ (i+j)/2 ];
while(i<j){
do i++ ;while(n[i]<x);
do j-- ;while(n[j]>x);
if(i<j){
int ten = n[i];
n[i] = n[j];
n[j] = ten;
}
}
qSort(n,l,j);
qSort(n,j+1,r);
}
隨機(jī)基準(zhǔn)
std::mt19937_64 gen(std::random_device{}());
int generateRandomNumber(int min_value, int max_value) {
std::uniform_int_distribution<int> distribution(min_value, max_value);
return distribution(gen);
}
// 元素互換
void swap(int* arr,int i,int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 編程實(shí)現(xiàn)的快排
void qSort(int n[],int l,int r){
if(l>=r){
return;
}
int i,j;
i=l-1;
j=r+1;
int x = n[ (i+j)/2 ];
// 改為隨機(jī)基準(zhǔn)
int xx = generateRandomNumber(l,r);
swap(n ,(i+j)/2 , xx);
x = n[ (i+j)/2 ];
while(i<j){
do i++ ;while(n[i]<x);
do j-- ;while(n[j]>x);
if(i<j){
int ten = n[i];
n[i] = n[j];
n[j] = ten;
}
}
qSort(n,l,j);
qSort(n,j+1,r);
}
三數(shù)取中
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, x =(l + r) >> 1;
// 多數(shù)取中法
int lll = 3;
if(r-l+1>=lll){
for (int i = l+1; i <= l+lll; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
int te = q[l+lll];
q[l+lll] = q[x];
q[x] = te;
}
x = q[x];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
2)(習(xí)題7.4-5)
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
if(r-l+1<=10){
for (int i = l+1; i <= r; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
return;
}
int i = l - 1, j = r + 1, x =(l + r) >> 1;
x = q[x];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
我的其他優(yōu)化方式
拆遞歸
#include<stack>// 記得導(dǎo)入棧
void quick_sort2(int q[], int ll, int rr){
// int ind = 0;
int l,r;
stack<int> sta;
// 也可以用數(shù)組
sta.push(ll);
sta.push(rr);
while(!sta.empty()){
// r = sta[--ind];
// l = sta[--ind];
r = sta.top();
sta.pop();
l = sta.top();
sta.pop();
if (l >= r) continue;
if(r-l+1<=20){// 結(jié)合插入排序
for (int i = l+1; i <= r; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
continue;
}
// 多元取中
int lll = 5;
for (int i = l+1; i <= l+lll; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
int te = q[l+lll];
q[l+lll] = q[x];
q[x] = te;
i = l+lll-1;
x = q[x];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
sta.push(l);
sta.push(j);
sta.push(j+1);
sta.push(r);
}
}
多線程
雙線程
// 多線程之雙線程
#include <iostream>
#include <chrono>
#include<stack>//使用stack時(shí)需要的頭文件
#include<mingw.thread.h> // 我的vscode 如果是別的編譯器直接用thread包就可以
using namespace std;
void threadFunctionA(int q[], int ll, int rr){
// int ind = 0;
int l,r;
stack<int> sta;
sta.push(ll);
sta.push(rr);
while(!sta.empty()){
// r = sta[--ind];
// l = sta[--ind];
r = sta.top();
sta.pop();
l = sta.top();
sta.pop();
if (l >= r) continue;
if(r-l+1<=20){
for (int i = l+1; i <= r; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
continue;
}
int i = l - 1, j = r + 1, x =(l + r) >> 1;
// 多元取中
int lll = 5;
for (int i = l+1; i <= l+lll; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
int te = q[l+lll];
q[l+lll] = q[x];
q[x] = te;
i = l+lll-1;
x = q[x];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
sta.push(l);
sta.push(j);
sta.push(j+1);
sta.push(r);
}
}
void quick_sort3(int q[], int l, int r)
{
// 多線程
if (l >= r) return;
if(r-l+1<=10){
for (int i = l+1; i <= r; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
return;
}
int i = l - 1, j = r + 1, x =(l + r) >> 1;
// 另一種取中
int lll = 5;
for (int i = l+1; i <= l+lll; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
int te = q[l+lll];
q[l+lll] = q[x];
q[x] = te;
x = q[x];
i = l+lll-1;
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
// quick_sort(q, l, j), quick_sort(q, j + 1, r);
thread newTh1(threadFunctionA, q, l,j);
thread newTh2(threadFunctionA, q, j+1,r);
// 這里是拆分為兩個(gè)線程
newTh1.join();
newTh2.join();
}
四線程
// 四線程并發(fā)
#include <iostream>
#include <chrono>
#include<stack>//使用stack時(shí)需要的頭文件
#include<mingw.thread.h> // 我的vscode 如果是別的編譯器直接用thread包就可以
using namespace std;
void threadForSort(int q[], int ll, int rr)
{
// 消遞歸
int ind = 0;
int l,r;
int* sta1 = new int[1000000]; // 也可以用stack 沒太大差別 所以暫時(shí)沒優(yōu)化
sta1[ind++] = ll;
sta1[ind++] = rr;
while(ind>0){
r = sta1[--ind];
l = sta1[--ind];
if (l >= r) continue;
if(r-l+1<=20){
for (int i = l+1; i <= r; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
continue;
}
int i = l - 1, j = r + 1, x =(l + r) >> 1;
// 另一種取中
int lll = 5;
for (int i = l+1; i <= l+lll; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
int te = q[l+lll];
q[l+lll] = q[x];
q[x] = te;
i = l+lll-1;
x = q[x];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
sta1[ind++] =l ;
sta1[ind++] =j ;
sta1[ind++] =j+1 ;
sta1[ind++] =r ;
}
delete[] sta1;
}
// 元素互換
void swap(int* arr,int i,int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 數(shù)組分區(qū)
int partition(int* arr, int strat, int end) {
// 選取一個(gè)分區(qū)的-支點(diǎn)
int pivot = arr[strat];
// 左右指針指向
int left = strat, right = end;
while (left < right)
{
// 分別從左右兩邊遍歷數(shù)組
while (arr[left] <= pivot && left < right)
left++;
while (arr[right] >= pivot && left < right)
right--;
// 交換左右指針的值
swap(arr, left, right);
}
if (arr[left] < pivot)
{
swap(arr, strat, left);
return left;
}
else if (arr[left] > pivot)
{
swap(arr, strat, left - 1);
return left - 1;
}
}
// 四線程
// 定義快速排序函數(shù),遞歸實(shí)現(xiàn)
void quick_sort4(int* q, int l, int r) {
// 前提條件
if (l >= r)
return;
// 分區(qū),返回分區(qū)下標(biāo)
int mid = partition(q, l, r);
// 現(xiàn)在 拆成四個(gè)線程
// 遞歸調(diào)用
// quickSort(q, l, mid - 1); // 這里對(duì)應(yīng)兩個(gè)線程
int mid1 = partition(q, l, mid - 1);
thread newTh1(threadForSort, q, l,mid1-1);
thread newTh2(threadForSort, q, mid1+1,mid-1);
// quickSort(q, mid + 1, r);// 這里也對(duì)應(yīng)兩個(gè)線程
mid1 = partition(q, mid + 1, r);
thread newTh3(threadForSort, q, mid+1,mid1-1);
thread newTh4(threadForSort, q, mid1+1,r);
newTh1.join();
newTh2.join();
newTh3.join();
newTh4.join();
}
動(dòng)態(tài)多線程
除了多線程之外的方法都沒有特別明顯的速度提升
同時(shí),雙線程,四線程的提升也都不如這里的動(dòng)態(tài)多線程
所以 僅在這里展示一下 加速效果 同時(shí)提供我自己寫的測(cè)試函數(shù)
// 動(dòng)態(tài)進(jìn)行多線程劃分
#include <iostream>
#include <chrono>
#include<stack>//使用stack時(shí)需要的頭文件
#include<mingw.thread.h> // 我的vscode 如果是別的編譯器直接用thread包就可以
using namespace std;
int maxLength = 1000000;// 測(cè)試數(shù)據(jù)長(zhǎng)度
int devideSize = maxLength/100; // 開新線程標(biāo)準(zhǔn) 防止產(chǎn)生太多線程 數(shù)據(jù)長(zhǎng)度大于此數(shù)時(shí)開啟新線程
int testNum = 15;// 測(cè)試次數(shù)
// volatile int maxThread
int compare(const void *a, const void *b)
{
int *pa = (int*)a;
int *pb = (int*)b;
return (*pa )- (*pb); //從小到大排序
}
int* getRand(int length)
{
int* n = new int[length];
int i;
for(i=0;i<length;i++){
n[i] = rand();
}
return n;
}
void threadForSort(int q[], int ll, int rr)
{
// thread* all[10000];
// int thNum = 0;
// 消遞歸
int ind = 0;
int l,r;
int* sta1 = new int[1000000]; // 也可以用stack 沒太大差別 所以暫時(shí)沒優(yōu)化
sta1[ind++] = ll;
sta1[ind++] = rr;
while(ind>0){
r = sta1[--ind];
l = sta1[--ind];
if (l >= r) continue;
if(r-l+1<=20){
for (int i = l+1; i <= r; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
continue;
}
int i = l - 1, j = r + 1, x =(l + r) >> 1;
// 另一種取中
int lll = 5;
for (int i = l+1; i <= l+lll; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
int te = q[l+lll];
q[l+lll] = q[x];
q[x] = te;
i = l+lll-1;
x = q[x];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
// thread* point1 = NULL;
// thread* point2 = NULL;
if( j-l>devideSize ){
thread newTh1(threadForSort, q, l,j);
// all[thNum++] = &newTh1;
// point1 = &newTh1;
newTh1.join();
}else{
sta1[ind++] =l ;
sta1[ind++] =j ;
}
if( r-j>devideSize ){
thread newTh1(threadForSort, q, l,j);
// point2 = &newTh1;
newTh1.join();
// all[thNum++] = &newTh1;
}else{
sta1[ind++] =j+1 ;
sta1[ind++] =r ;
}
}
delete[] sta1;
}
// 元素互換
void swap(int* arr,int i,int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
void mysort(int *n,int l){
threadForSort(n,0,l-1);
}
void comprehensiveTest()
{// 進(jìn)行100次測(cè)試 算平均時(shí)間 計(jì)算性能提升
double cAllTime = 0;
double myAllTime = 0;
int i,j;
int total = maxLength;
for(i=0;i<testNum;i++){
int *num1 = getRand(total);
int* num2 = new int[total];
for(j=0;j<total;j++){
num2[j] = num1[j];
}
auto start1 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
qsort(num1, total, sizeof(int), compare);
auto end1 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
auto start2 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
mysort(num2 , total);
auto end2 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
for(j=0;j<total;j++){
if(num1[i] !=num2[i]){
cout << "出錯(cuò)了" << endl;
break;
}
}
delete[] num1;
delete[] num2;
std::chrono::duration<double, std::milli> cTime = end1 - start1; // 計(jì)算執(zhí)行時(shí)間
std::chrono::duration<double, std::milli> myTime = end2 - start2; // 計(jì)算執(zhí)行時(shí)間
std::cout << "c++程序執(zhí)行時(shí)間:" << cTime.count() << " 毫秒" << " " << "我的程序執(zhí)行時(shí)間:" << myTime.count() << " 毫秒" ;
double gap = cTime.count()-myTime.count();
if(gap>0){
cout << " 快了 " << gap << " " <<endl;
}else{
cout << " 慢了 " << -1*gap << " " <<endl;
}
cAllTime +=cTime.count();
myAllTime+=myTime.count();
}
cAllTime/=testNum;
myAllTime/=testNum;
cout << "平均快了 " << cAllTime-myAllTime << endl;
cout << "提升比例 " << (cAllTime-myAllTime)/cAllTime << endl;
}
void compareTest(){
int count = 7;
int allLen[count] = {10000,50000,100000,1000000 , 5000000,8000000 , 10000000};
// int myScore;
// int cScore = myScore = 0;
int i,j;
for(i=0;i<count;i++){
int *num1 = getRand(allLen[i]);
int* num2 = new int[allLen[i]];
for(j=0;j<allLen[i];j++){
num2[j] = num1[j];
}
auto start1 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
qsort(num1, allLen[i], sizeof(int), compare);
auto end1 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
auto start2 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
mysort(num2 , allLen[i]);
auto end2 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
for(j=0;j<allLen[i];j++){
if(num1[i] !=num2[i]){
cout << "出錯(cuò)了" << endl;
break;
}
}
delete[] num1;
delete[] num2;
std::chrono::duration<double, std::milli> cTime = end1 - start1; // 計(jì)算執(zhí)行時(shí)間
std::chrono::duration<double, std::milli> myTime = end2 - start2; // 計(jì)算執(zhí)行時(shí)間
std::cout << "c++程序執(zhí)行時(shí)間:" << cTime.count() << " 毫秒" << " " << "我的程序執(zhí)行時(shí)間:" << myTime.count() << " 毫秒" ;
double gap = cTime.count()-myTime.count();
if(gap>0){
cout << " 快了 " << gap << " " <<endl;
}else{
cout << " 慢了 " << -1*gap << " " <<endl;
}
}
}
int main()
{
srand(time(0));
// compareTest();
comprehensiveTest();
return 0;
}
在我自己電腦上的輸出:
c++程序執(zhí)行時(shí)間:80.01 毫秒 我的程序執(zhí)行時(shí)間:19.538
毫秒 快了 60.472
c++程序執(zhí)行時(shí)間:79.171 毫秒 我的程序執(zhí)行時(shí)間:30.538 毫秒 快了 48.633
c++程序執(zhí)行時(shí)間:82.023 毫秒 我的程序執(zhí)行時(shí)間:36.338 毫秒 快了 45.685
c++程序執(zhí)行時(shí)間:78.11 毫秒 我的程序執(zhí)行時(shí)間:23.378
毫秒 快了 54.732
c++程序執(zhí)行時(shí)間:79.382 毫秒 我的程序執(zhí)行時(shí)間:27.272 毫秒 快了 52.11
c++程序執(zhí)行時(shí)間:79.223 毫秒 我的程序執(zhí)行時(shí)間:19.551 毫秒 快了 59.672
c++程序執(zhí)行時(shí)間:79.345 毫秒 我的程序執(zhí)行時(shí)間:23.529 毫秒 快了 55.816
c++程序執(zhí)行時(shí)間:78.306 毫秒 我的程序執(zhí)行時(shí)間:25.156 毫秒 快了 53.15
c++程序執(zhí)行時(shí)間:78.463 毫秒 我的程序執(zhí)行時(shí)間:21.429 毫秒 快了 57.034
c++程序執(zhí)行時(shí)間:78.98 毫秒 我的程序執(zhí)行時(shí)間:28.995
毫秒 快了 49.985
c++程序執(zhí)行時(shí)間:78.659 毫秒 我的程序執(zhí)行時(shí)間:22.821 毫秒 快了 55.838
c++程序執(zhí)行時(shí)間:78.817 毫秒 我的程序執(zhí)行時(shí)間:25.161 毫秒 快了 53.656
c++程序執(zhí)行時(shí)間:79.496 毫秒 我的程序執(zhí)行時(shí)間:25.921 毫秒 快了 53.575
c++程序執(zhí)行時(shí)間:78.601 毫秒 我的程序執(zhí)行時(shí)間:31.099 毫秒 快了 47.502
c++程序執(zhí)行時(shí)間:79.954 毫秒 我的程序執(zhí)行時(shí)間:21.93
毫秒 快了 58.024
平均快了 53.7256
提升比例 0.678045
PS E:\c++_proje
我的其他優(yōu)化方式--算法思想描述
- 在拆遞歸之前,也嘗試了多元取中法,以及在長(zhǎng)度足夠短的時(shí)候采用插入排序直接排序的算法,所以在我的其他優(yōu)化中都加入了這些成分。
拆遞歸思想
拆遞歸的優(yōu)化方式是考慮到算法的遞歸調(diào)用是有一定的代價(jià)的,但其實(shí)每次遞歸只是傳遞的兩個(gè)下標(biāo)的差異,所以采用棧來(lái)拆解遞歸,進(jìn)而算法執(zhí)行的整個(gè)流程就不再進(jìn)行遞歸調(diào)用。這樣就能降低成本
雙線程和四線程思想
因?yàn)槲覀冞M(jìn)行一次partition之后,就會(huì)分解成兩個(gè)序列,在對(duì)兩個(gè)序列進(jìn)行單獨(dú)處理。同時(shí)也沒有處理之后的合并操作。所以可以將兩個(gè)序列的操作分給兩個(gè)不同的線程進(jìn)行處理,然后等待兩個(gè)線程執(zhí)行完畢即可。 同樣的四線程也是這樣,進(jìn)行了兩次partition之后,拆成四段之后在進(jìn)行分線程。
動(dòng)態(tài)多線程思想
延續(xù)前面的多線程方法,前面給線程設(shè)計(jì)的方法是通過(guò)解遞歸的方式對(duì)其所分得的序列進(jìn)行快排處理,這里改動(dòng)了一下,為其新增了創(chuàng)建新線程的功能。這樣就是說(shuō),我們新建立的線程也能接著拆分出新的線程。這樣就可以動(dòng)態(tài)的進(jìn)行線程創(chuàng)建。進(jìn)而提高效率。
同時(shí)考慮到如果序列已經(jīng)夠短了,就不要接著劃分了,所以在代碼的全局變量加入了長(zhǎng)度限制,只對(duì)足夠長(zhǎng)的序列進(jìn)行下一步的拆分,交給不同的線程。否則就進(jìn)行普通的解遞歸的快排處理。
附錄----代碼和性能比較
另附 從最開始優(yōu)化,到最后的動(dòng)態(tài)多線程的代碼(可直接運(yùn)行測(cè)試性能對(duì)比)
綜合來(lái)看,每一次迭代 性能有提升,同時(shí) 在多線程,性能有極大提升
solution1:
// 插入排序 和取中法優(yōu)化
#include <iostream>
#include <chrono>
#include<stack>
#include<mingw.thread.h>
using namespace std;
int testLength = 1000000;// 測(cè)試數(shù)據(jù)長(zhǎng)度
int testNum = 15;// 測(cè)試次數(shù)
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
if(r-l+1<=10){
for (int i = l+1; i <= r; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
return;
}
int i = l - 1, j = r + 1, x =(l + r) >> 1;
int lll = 5;
for (int i = l+1; i <= l+lll; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
int te = q[l+lll];
q[l+lll] = q[x];
q[x] = te;
i = l+lll-1;
x = q[x];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
int* getRand(int length)
{
int* n = new int[length];
int i;
for(i=0;i<length;i++){
n[i] = rand();
}
return n;
}
int compare(const void *a, const void *b)
{
int *pa = (int*)a;
int *pb = (int*)b;
return (*pa )- (*pb); //從小到大排序
}
void mysort(int *n,int l){
quick_sort(n,0,l-1);
}
void comprehensiveTest()
{// 進(jìn)行100次測(cè)試 算平均時(shí)間 計(jì)算性能提升
double cAllTime = 0;
double myAllTime = 0;
int i,j;
int total = testLength;
for(i=0;i<testNum;i++){
int *num1 = getRand(total);
int* num2 = new int[total];
for(j=0;j<total;j++){
num2[j] = num1[j];
}
auto start1 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
qsort(num1, total, sizeof(int), compare);
auto end1 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
auto start2 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
mysort(num2 , total);
auto end2 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
for(j=0;j<total;j++){
if(num1[i] !=num2[i]){
cout << "出錯(cuò)了" << endl;
break;
}
}
delete[] num1;
delete[] num2;
std::chrono::duration<double, std::milli> cTime = end1 - start1; // 計(jì)算執(zhí)行時(shí)間
std::chrono::duration<double, std::milli> myTime = end2 - start2; // 計(jì)算執(zhí)行時(shí)間
std::cout << "c++程序執(zhí)行時(shí)間:" << cTime.count() << " 毫秒" << " " << "我的程序執(zhí)行時(shí)間:" << myTime.count() << " 毫秒" ;
double gap = cTime.count()-myTime.count();
if(gap>0){
cout << " 快了 " << gap << " " <<endl;
}else{
cout << " 慢了 " << -1*gap << " " <<endl;
}
cAllTime +=cTime.count();
myAllTime+=myTime.count();
}
cAllTime/=testNum;
myAllTime/=testNum;
cout << "平均快了 " << cAllTime-myAllTime << endl;
cout << "提升比例 " << (cAllTime-myAllTime)/cAllTime << endl;
}
void compareTest(){
int count = 7;
int allLen[count] = {10000,50000,100000,1000000 , 5000000,8000000 , 10000000};
int myScor=0;
// int cScore = myScore = 0;
int i,j;
for(i=0;i<count;i++){
int *num1 = getRand(allLen[i]);
int* num2 = new int[allLen[i]];
for(j=0;j<allLen[i];j++){
num2[j] = num1[j];
}
auto start1 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
qsort(num1, allLen[i], sizeof(int), compare);
auto end1 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
auto start2 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
mysort(num2 , allLen[i]);
auto end2 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
for(j=0;j<allLen[i];j++){
if(num1[i] !=num2[i]){
cout << "出錯(cuò)了" << endl;
break;
}
}
delete[] num1;
delete[] num2;
std::chrono::duration<double, std::milli> cTime = end1 - start1; // 計(jì)算執(zhí)行時(shí)間
std::chrono::duration<double, std::milli> myTime = end2 - start2; // 計(jì)算執(zhí)行時(shí)間
std::cout << "c++程序執(zhí)行時(shí)間:" << cTime.count() << " 毫秒" << " " << "我的程序執(zhí)行時(shí)間:" << myTime.count() << " 毫秒" ;
double gap = cTime.count()-myTime.count();
if(gap>0){
cout << " 快了 " << gap << " " <<endl;
}else{
cout << " 慢了 " << -1*gap << " " <<endl;
}
}
}
int main()
{
srand(time(0));
// compareTest();
comprehensiveTest();
return 0;
}
性能比較輸出:
PS E:\c++_project\test\算法實(shí)驗(yàn)1\output> cd 'e:\c++_project\test\算法實(shí)驗(yàn)1\output'
PS E:\c++_project\test\算法實(shí)驗(yàn)1\output> & .\'solution1.exe'
c++程序執(zhí)行時(shí)間:80.034 毫秒 我的程序執(zhí)行時(shí)間:75.85
毫秒 快了 4.184
c++程序執(zhí)行時(shí)間:79.018 毫秒 我的程序執(zhí)行時(shí)間:77.662 毫秒 快了 1.356
c++程序執(zhí)行時(shí)間:79.014 毫秒 我的程序執(zhí)行時(shí)間:76.007 毫秒 快了 3.007
c++程序執(zhí)行時(shí)間:78.297 毫秒 我的程序執(zhí)行時(shí)間:77.185 毫秒 快了 1.112
c++程序執(zhí)行時(shí)間:79.307 毫秒 我的程序執(zhí)行時(shí)間:76.601 毫秒 快了 2.706
c++程序執(zhí)行時(shí)間:79.042 毫秒 我的程序執(zhí)行時(shí)間:76.736 毫秒 快了 2.306
c++程序執(zhí)行時(shí)間:78.652 毫秒 我的程序執(zhí)行時(shí)間:76.327 毫秒 快了 2.325
c++程序執(zhí)行時(shí)間:83.278 毫秒 我的程序執(zhí)行時(shí)間:77.002 毫秒 快了 6.276
c++程序執(zhí)行時(shí)間:79.51 毫秒 我的程序執(zhí)行時(shí)間:77.103
毫秒 快了 2.407
c++程序執(zhí)行時(shí)間:77.844 毫秒 我的程序執(zhí)行時(shí)間:76.903 毫秒 快了 0.941
c++程序執(zhí)行時(shí)間:78.333 毫秒 我的程序執(zhí)行時(shí)間:78.68
毫秒 慢了 0.347
c++程序執(zhí)行時(shí)間:79.051 毫秒 我的程序執(zhí)行時(shí)間:76.808 毫秒 快了 2.243
c++程序執(zhí)行時(shí)間:82.108 毫秒 我的程序執(zhí)行時(shí)間:77.068 毫秒 快了 5.04
c++程序執(zhí)行時(shí)間:78.342 毫秒 我的程序執(zhí)行時(shí)間:77.008 毫秒 快了 1.334
c++程序執(zhí)行時(shí)間:79.231 毫秒 我的程序執(zhí)行時(shí)間:76.034 毫秒 快了 3.197
平均快了 2.53913
提升比例 0.0319774
solution2:
// 解遞歸
#include <iostream>
#include <chrono>
#include<stack>//
#include<mingw.thread.h>
using namespace std;
int testLength = 1000000;// 測(cè)試數(shù)據(jù)長(zhǎng)度
int testNum = 15;// 測(cè)試次數(shù)
void quick_sort2(int q[], int ll, int rr){
// int ind = 0;
int l,r;
stack<int> sta;
// 也可以用數(shù)組 不過(guò)還是略慢
// sta[ind++] = ll;
// sta[ind++] = rr;
sta.push(ll);
sta.push(rr);
while(!sta.empty()){
// r = sta[--ind];
// l = sta[--ind];
r = sta.top();
sta.pop();
l = sta.top();
sta.pop();
if (l >= r) continue;
if(r-l+1<=20){
for (int i = l+1; i <= r; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
continue;
}
int i = l - 1, j = r + 1, x =(l + r) >> 1;
// 多元取中
int lll = 5;
for (int i = l+1; i <= l+lll; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
int te = q[l+lll];
q[l+lll] = q[x];
q[x] = te;
i = l+lll-1;
x = q[x];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
sta.push(l);
sta.push(j);
sta.push(j+1);
sta.push(r);
}
}
int* getRand(int length)
{
int* n = new int[length];
int i;
for(i=0;i<length;i++){
n[i] = rand();
}
return n;
}
int compare(const void *a, const void *b)
{
int *pa = (int*)a;
int *pb = (int*)b;
return (*pa )- (*pb); //從小到大排序
}
void mysort(int *n,int l){
quick_sort2(n,0,l-1);
}
void comprehensiveTest()
{// 進(jìn)行100次測(cè)試 算平均時(shí)間 計(jì)算性能提升
double cAllTime = 0;
double myAllTime = 0;
int i,j;
int total = testLength;
for(i=0;i<testNum;i++){
int *num1 = getRand(total);
int* num2 = new int[total];
for(j=0;j<total;j++){
num2[j] = num1[j];
}
auto start1 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
qsort(num1, total, sizeof(int), compare);
auto end1 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
auto start2 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
mysort(num2 , total);
auto end2 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
for(j=0;j<total;j++){
if(num1[i] !=num2[i]){
cout << "出錯(cuò)了" << endl;
break;
}
}
delete[] num1;
delete[] num2;
std::chrono::duration<double, std::milli> cTime = end1 - start1; // 計(jì)算執(zhí)行時(shí)間
std::chrono::duration<double, std::milli> myTime = end2 - start2; // 計(jì)算執(zhí)行時(shí)間
std::cout << "c++程序執(zhí)行時(shí)間:" << cTime.count() << " 毫秒" << " " << "我的程序執(zhí)行時(shí)間:" << myTime.count() << " 毫秒" ;
double gap = cTime.count()-myTime.count();
if(gap>0){
cout << " 快了 " << gap << " " <<endl;
}else{
cout << " 慢了 " << -1*gap << " " <<endl;
}
cAllTime +=cTime.count();
myAllTime+=myTime.count();
}
cAllTime/=testNum;
myAllTime/=testNum;
cout << "平均快了 " << cAllTime-myAllTime << endl;
cout << "提升比例 " << (cAllTime-myAllTime)/cAllTime << endl;
}
void compareTest(){
int count = 7;
int allLen[count] = {10000,50000,100000,1000000 , 5000000,8000000 , 10000000};
int myScore;
int cScore = myScore = 0;
int i,j;
for(i=0;i<count;i++){
int *num1 = getRand(allLen[i]);
int* num2 = new int[allLen[i]];
for(j=0;j<allLen[i];j++){
num2[j] = num1[j];
}
auto start1 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
qsort(num1, allLen[i], sizeof(int), compare);
auto end1 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
auto start2 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
mysort(num2 , allLen[i]);
auto end2 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
for(j=0;j<allLen[i];j++){
if(num1[i] !=num2[i]){
cout << "出錯(cuò)了" << endl;
break;
}
}
delete[] num1;
delete[] num2;
std::chrono::duration<double, std::milli> cTime = end1 - start1; // 計(jì)算執(zhí)行時(shí)間
std::chrono::duration<double, std::milli> myTime = end2 - start2; // 計(jì)算執(zhí)行時(shí)間
std::cout << "c++程序執(zhí)行時(shí)間:" << cTime.count() << " 毫秒" << " " << "我的程序執(zhí)行時(shí)間:" << myTime.count() << " 毫秒" ;
double gap = cTime.count()-myTime.count();
if(gap>0){
cout << " 快了 " << gap << " " <<endl;
}else{
cout << " 慢了 " << -1*gap << " " <<endl;
}
}
}
int main()
{
srand(time(0));
// compareTest();
comprehensiveTest();
return 0;
}
性能比較輸出:
PS E:\c++_project\test\算法實(shí)驗(yàn)1\output> & .\'solution2.exe'
c++程序執(zhí)行時(shí)間:80.02 毫秒 我的程序執(zhí)行時(shí)間:81.006
毫秒 慢了 0.986
c++程序執(zhí)行時(shí)間:81.984 毫秒 我的程序執(zhí)行時(shí)間:80.97
毫秒 快了 1.014
c++程序執(zhí)行時(shí)間:79.043 毫秒 我的程序執(zhí)行時(shí)間:78.169 毫秒 快了 0.874
c++程序執(zhí)行時(shí)間:78.602 毫秒 我的程序執(zhí)行時(shí)間:80.156 毫秒 慢了 1.554
c++程序執(zhí)行時(shí)間:79.379 毫秒 我的程序執(zhí)行時(shí)間:81.455 毫秒 慢了 2.076
c++程序執(zhí)行時(shí)間:78.129 毫秒 我的程序執(zhí)行時(shí)間:80.998 毫秒 慢了 2.869
c++程序執(zhí)行時(shí)間:77.955 毫秒 我的程序執(zhí)行時(shí)間:80.001 毫秒 慢了 2.046
c++程序執(zhí)行時(shí)間:78.999 毫秒 我的程序執(zhí)行時(shí)間:83.083 毫秒 慢了 4.084
c++程序執(zhí)行時(shí)間:77.839 毫秒 我的程序執(zhí)行時(shí)間:80.166 毫秒 慢了 2.327
c++程序執(zhí)行時(shí)間:77.955 毫秒 我的程序執(zhí)行時(shí)間:81.564 毫秒 慢了 3.609
c++程序執(zhí)行時(shí)間:79.192 毫秒 我的程序執(zhí)行時(shí)間:83.518 毫秒 慢了 4.326
c++程序執(zhí)行時(shí)間:83.464 毫秒 我的程序執(zhí)行時(shí)間:79.676 毫秒 快了 3.788
c++程序執(zhí)行時(shí)間:80.032 毫秒 我的程序執(zhí)行時(shí)間:79.001 毫秒 快了 1.031
c++程序執(zhí)行時(shí)間:78.992 毫秒 我的程序執(zhí)行時(shí)間:82.914 毫秒 慢了 3.922
c++程序執(zhí)行時(shí)間:78.137 毫秒 我的程序執(zhí)行時(shí)間:78 毫
秒 快了 0.137
平均快了 -1.397
提升比例 -0.0176134
solution3:
// 多線程之雙線程
#include <iostream>
#include <chrono>
#include<stack>//使用stack時(shí)需要的頭文件
#include<mingw.thread.h> // 我的vscode 如果是別的編譯器直接用thread包就可以
using namespace std;
int testLength = 10000000;// 測(cè)試數(shù)據(jù)長(zhǎng)度
int testNum = 15;// 測(cè)試次數(shù)
void threadFunctionA(int q[], int ll, int rr){
// int ind = 0;
int l,r;
stack<int> sta;
// 也可以用數(shù)組 不過(guò)還是略慢
// sta[ind++] = ll;
// sta[ind++] = rr;
sta.push(ll);
sta.push(rr);
while(!sta.empty()){
// r = sta[--ind];
// l = sta[--ind];
r = sta.top();
sta.pop();
l = sta.top();
sta.pop();
if (l >= r) continue;
if(r-l+1<=20){
for (int i = l+1; i <= r; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
continue;
}
int i = l - 1, j = r + 1, x =(l + r) >> 1;
// 多元取中
int lll = 5;
for (int i = l+1; i <= l+lll; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
int te = q[l+lll];
q[l+lll] = q[x];
q[x] = te;
i = l+lll-1;
x = q[x];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
// sta[ind++] =l ;
// sta[ind++] =j ;
// sta[ind++] =j+1 ;
// sta[ind++] =r ;
sta.push(l);
sta.push(j);
sta.push(j+1);
sta.push(r);
}
}
void quick_sort3(int q[], int l, int r)
{
// 多線程
if (l >= r) return;
if(r-l+1<=10){
for (int i = l+1; i <= r; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
return;
}
int i = l - 1, j = r + 1, x =(l + r) >> 1;
// 另一種取中
int lll = 5;
for (int i = l+1; i <= l+lll; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
int te = q[l+lll];
q[l+lll] = q[x];
q[x] = te;
x = q[x];
i = l+lll-1;
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
// quick_sort(q, l, j), quick_sort(q, j + 1, r);
thread newTh1(threadFunctionA, q, l,j);
thread newTh2(threadFunctionA, q, j+1,r);
// 這里是拆分為兩個(gè)線程
newTh1.join();
newTh2.join();
}
int* getRand(int length)
{
int* n = new int[length];
int i;
for(i=0;i<length;i++){
n[i] = rand();
}
return n;
}
int compare(const void *a, const void *b)
{
int *pa = (int*)a;
int *pb = (int*)b;
return (*pa )- (*pb); //從小到大排序
}
void mysort(int *n,int l){
quick_sort3(n,0,l-1);
}
void comprehensiveTest()
{// 進(jìn)行100次測(cè)試 算平均時(shí)間 計(jì)算性能提升
double cAllTime = 0;
double myAllTime = 0;
int i,j;
int total = testLength;
for(i=0;i<testNum;i++){
int *num1 = getRand(total);
int* num2 = new int[total];
for(j=0;j<total;j++){
num2[j] = num1[j];
}
auto start1 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
qsort(num1, total, sizeof(int), compare);
auto end1 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
auto start2 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
mysort(num2 , total);
auto end2 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
for(j=0;j<total;j++){
if(num1[i] !=num2[i]){
cout << "出錯(cuò)了" << endl;
break;
}
}
delete[] num1;
delete[] num2;
std::chrono::duration<double, std::milli> cTime = end1 - start1; // 計(jì)算執(zhí)行時(shí)間
std::chrono::duration<double, std::milli> myTime = end2 - start2; // 計(jì)算執(zhí)行時(shí)間
std::cout << "c++程序執(zhí)行時(shí)間:" << cTime.count() << " 毫秒" << " " << "我的程序執(zhí)行時(shí)間:" << myTime.count() << " 毫秒" ;
double gap = cTime.count()-myTime.count();
if(gap>0){
cout << " 快了 " << gap << " " <<endl;
}else{
cout << " 慢了 " << -1*gap << " " <<endl;
}
cAllTime +=cTime.count();
myAllTime+=myTime.count();
}
cAllTime/=testNum;
myAllTime/=testNum;
cout << "平均快了 " << cAllTime-myAllTime << endl;
cout << "提升比例 " << (cAllTime-myAllTime)/cAllTime << endl;
}
void compareTest(){
int count = 7;
int allLen[count] = {10000,50000,100000,1000000 , 5000000,8000000 , 10000000};
// int myScore;
// int cScore = myScore = 0;
int i,j;
for(i=0;i<count;i++){
int *num1 = getRand(allLen[i]);
int* num2 = new int[allLen[i]];
for(j=0;j<allLen[i];j++){
num2[j] = num1[j];
}
auto start1 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
qsort(num1, allLen[i], sizeof(int), compare);
auto end1 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
auto start2 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
mysort(num2 , allLen[i]);
auto end2 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
for(j=0;j<allLen[i];j++){
if(num1[i] !=num2[i]){
cout << "出錯(cuò)了" << endl;
break;
}
}
delete[] num1;
delete[] num2;
std::chrono::duration<double, std::milli> cTime = end1 - start1; // 計(jì)算執(zhí)行時(shí)間
std::chrono::duration<double, std::milli> myTime = end2 - start2; // 計(jì)算執(zhí)行時(shí)間
std::cout << "c++程序執(zhí)行時(shí)間:" << cTime.count() << " 毫秒" << " " << "我的程序執(zhí)行時(shí)間:" << myTime.count() << " 毫秒" ;
double gap = cTime.count()-myTime.count();
if(gap>0){
cout << " 快了 " << gap << " " <<endl;
}else{
cout << " 慢了 " << -1*gap << " " <<endl;
}
}
}
int main()
{
srand(time(0));
// compareTest();
comprehensiveTest();
return 0;
}
性能比較輸出:
PS E:\c++_project\test\算法實(shí)驗(yàn)1\output> & .\'solution3.exe'
c++程序執(zhí)行時(shí)間:77.988 毫秒 我的程序執(zhí)行時(shí)間:74.044 毫秒 快了 3.944
c++程序執(zhí)行時(shí)間:83.498 毫秒 我的程序執(zhí)行時(shí)間:79.803 毫秒 快了 3.695
c++程序執(zhí)行時(shí)間:79.749 毫秒 我的程序執(zhí)行時(shí)間:52.482 毫秒 快了 27.267
c++程序執(zhí)行時(shí)間:77.736 毫秒 我的程序執(zhí)行時(shí)間:47.673 毫秒 快了 30.063
c++程序執(zhí)行時(shí)間:78.066 毫秒 我的程序執(zhí)行時(shí)間:62.493 毫秒 快了 15.573
c++程序執(zhí)行時(shí)間:80.071 毫秒 我的程序執(zhí)行時(shí)間:78.52
毫秒 快了 1.551
c++程序執(zhí)行時(shí)間:78.476 毫秒 我的程序執(zhí)行時(shí)間:79.85
毫秒 慢了 1.374
c++程序執(zhí)行時(shí)間:79.398 毫秒 我的程序執(zhí)行時(shí)間:75.689 毫秒 快了 3.709
c++程序執(zhí)行時(shí)間:79.142 毫秒 我的程序執(zhí)行時(shí)間:80.422 毫秒 慢了 1.28
c++程序執(zhí)行時(shí)間:81.046 毫秒 我的程序執(zhí)行時(shí)間:74.736 毫秒 快了 6.31
c++程序執(zhí)行時(shí)間:79.603 毫秒 我的程序執(zhí)行時(shí)間:52.47
毫秒 快了 27.133
c++程序執(zhí)行時(shí)間:79.955 毫秒 我的程序執(zhí)行時(shí)間:57.383 毫秒 快了 22.572
c++程序執(zhí)行時(shí)間:84.608 毫秒 我的程序執(zhí)行時(shí)間:75.01
毫秒 快了 9.598
c++程序執(zhí)行時(shí)間:79.721 毫秒 我的程序執(zhí)行時(shí)間:67.263 毫秒 快了 12.458
c++程序執(zhí)行時(shí)間:82.756 毫秒 我的程序執(zhí)行時(shí)間:77.532 毫秒 快了 5.224
平均快了 11.0962
提升比例 0.138493
solution4:
// 四線程并發(fā)
#include <iostream>
#include <chrono>
#include<stack>//使用stack時(shí)需要的頭文件
#include<mingw.thread.h> // 我的vscode 如果是別的編譯器直接用thread包就可以
using namespace std;
int testLength = 1000000;// 測(cè)試數(shù)據(jù)長(zhǎng)度
int testNum = 15;// 測(cè)試次數(shù)
int compare(const void *a, const void *b)
{
int *pa = (int*)a;
int *pb = (int*)b;
return (*pa )- (*pb); //從小到大排序
}
int* getRand(int length)
{
int* n = new int[length];
int i;
for(i=0;i<length;i++){
n[i] = rand();
}
return n;
}
void threadForSort(int q[], int ll, int rr)
{
// 消遞歸
int ind = 0;
int l,r;
int* sta1 = new int[1000000]; // 也可以用stack 沒太大差別 所以暫時(shí)沒優(yōu)化
sta1[ind++] = ll;
sta1[ind++] = rr;
while(ind>0){
r = sta1[--ind];
l = sta1[--ind];
if (l >= r) continue;
if(r-l+1<=20){
for (int i = l+1; i <= r; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
continue;
}
int i = l - 1, j = r + 1, x =(l + r) >> 1;
// 另一種取中
int lll = 5;
for (int i = l+1; i <= l+lll; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
int te = q[l+lll];
q[l+lll] = q[x];
q[x] = te;
i = l+lll-1;
x = q[x];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
sta1[ind++] =l ;
sta1[ind++] =j ;
sta1[ind++] =j+1 ;
sta1[ind++] =r ;
// sta.push(l);
// sta.push(j);
// sta.push(j+1);
// sta.push(r);
}
delete[] sta1;
}
// 元素互換
void swap(int* arr,int i,int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 數(shù)組分區(qū)
int partition(int* arr, int strat, int end) {
// 選取一個(gè)分區(qū)的-支點(diǎn)
int pivot = arr[strat];
// 左右指針指向
int left = strat, right = end;
while (left < right)
{
// 分別從左右兩邊遍歷數(shù)組
while (arr[left] <= pivot && left < right)
left++;
while (arr[right] >= pivot && left < right)
right--;
// 交換左右指針的值
swap(arr, left, right);
}
if (arr[left] < pivot)
{
swap(arr, strat, left);
return left;
}
else if (arr[left] > pivot)
{
swap(arr, strat, left - 1);
return left - 1;
}
}
// 四線程
// 定義快速排序函數(shù),遞歸實(shí)現(xiàn)
void quick_sort4(int* q, int l, int r) {
// 前提條件
if (l >= r)
return;
// 分區(qū),返回分區(qū)下標(biāo)
int mid = partition(q, l, r);
// 現(xiàn)在 拆成四個(gè)線程
// 遞歸調(diào)用
// quickSort(q, l, mid - 1); // 這里對(duì)應(yīng)兩個(gè)線程
int mid1 = partition(q, l, mid - 1);
thread newTh1(threadForSort, q, l,mid1-1);
thread newTh2(threadForSort, q, mid1+1,mid-1);
// quickSort(q, mid + 1, r);// 這里也對(duì)應(yīng)兩個(gè)線程
mid1 = partition(q, mid + 1, r);
thread newTh3(threadForSort, q, mid+1,mid1-1);
thread newTh4(threadForSort, q, mid1+1,r);
newTh1.join();
newTh2.join();
newTh3.join();
newTh4.join();
}
void mysort(int *n,int l){
quick_sort4(n,0,l-1);
}
void comprehensiveTest()
{// 進(jìn)行100次測(cè)試 算平均時(shí)間 計(jì)算性能提升
double cAllTime = 0;
double myAllTime = 0;
int i,j;
int total = testLength;
for(i=0;i<testNum;i++){
int *num1 = getRand(total);
int* num2 = new int[total];
for(j=0;j<total;j++){
num2[j] = num1[j];
}
auto start1 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
qsort(num1, total, sizeof(int), compare);
auto end1 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
auto start2 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
mysort(num2 , total);
auto end2 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
for(j=0;j<total;j++){
if(num1[i] !=num2[i]){
cout << "出錯(cuò)了" << endl;
break;
}
}
delete[] num1;
delete[] num2;
std::chrono::duration<double, std::milli> cTime = end1 - start1; // 計(jì)算執(zhí)行時(shí)間
std::chrono::duration<double, std::milli> myTime = end2 - start2; // 計(jì)算執(zhí)行時(shí)間
std::cout << "c++程序執(zhí)行時(shí)間:" << cTime.count() << " 毫秒" << " " << "我的程序執(zhí)行時(shí)間:" << myTime.count() << " 毫秒" ;
double gap = cTime.count()-myTime.count();
if(gap>0){
cout << " 快了 " << gap << " " <<endl;
}else{
cout << " 慢了 " << -1*gap << " " <<endl;
}
cAllTime +=cTime.count();
myAllTime+=myTime.count();
}
cAllTime/=testNum;
myAllTime/=testNum;
cout << "平均快了 " << cAllTime-myAllTime << endl;
cout << "提升比例 " << (cAllTime-myAllTime)/cAllTime << endl;
}
void compareTest(){
int count = 7;
int allLen[count] = {10000,50000,100000,1000000 , 5000000,8000000 , 10000000};
// int myScore;
// int cScore = myScore = 0;
int i,j;
for(i=0;i<count;i++){
int *num1 = getRand(allLen[i]);
int* num2 = new int[allLen[i]];
for(j=0;j<allLen[i];j++){
num2[j] = num1[j];
}
auto start1 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
qsort(num1, allLen[i], sizeof(int), compare);
auto end1 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
auto start2 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
mysort(num2 , allLen[i]);
auto end2 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
for(j=0;j<allLen[i];j++){
if(num1[i] !=num2[i]){
cout << "出錯(cuò)了" << endl;
break;
}
}
delete[] num1;
delete[] num2;
std::chrono::duration<double, std::milli> cTime = end1 - start1; // 計(jì)算執(zhí)行時(shí)間
std::chrono::duration<double, std::milli> myTime = end2 - start2; // 計(jì)算執(zhí)行時(shí)間
std::cout << "c++程序執(zhí)行時(shí)間:" << cTime.count() << " 毫秒" << " " << "我的程序執(zhí)行時(shí)間:" << myTime.count() << " 毫秒" ;
double gap = cTime.count()-myTime.count();
if(gap>0){
cout << " 快了 " << gap << " " <<endl;
}else{
cout << " 慢了 " << -1*gap << " " <<endl;
}
}
}
int main()
{
srand(time(0));
// compareTest();
comprehensiveTest();
return 0;
}
性能比較輸出:
PS E:\c++_project\test\算法實(shí)驗(yàn)1\output> & .\'solution4.exe'
c++程序執(zhí)行時(shí)間:79.005 毫秒 我的程序執(zhí)行時(shí)間:45.277 毫秒 快了 33.728
c++程序執(zhí)行時(shí)間:80.556 毫秒 我的程序執(zhí)行時(shí)間:42.003 毫秒 快了 38.553
c++程序執(zhí)行時(shí)間:79.536 毫秒 我的程序執(zhí)行時(shí)間:39.296 毫秒 快了 40.24
c++程序執(zhí)行時(shí)間:77.783 毫秒 我的程序執(zhí)行時(shí)間:41.132 毫秒 快了 36.651
c++程序執(zhí)行時(shí)間:80.678 毫秒 我的程序執(zhí)行時(shí)間:41.417 毫秒 快了 39.261
c++程序執(zhí)行時(shí)間:79.392 毫秒 我的程序執(zhí)行時(shí)間:46.027 毫秒 快了 33.365
c++程序執(zhí)行時(shí)間:77.973 毫秒 我的程序執(zhí)行時(shí)間:62.482 毫秒 快了 15.491
c++程序執(zhí)行時(shí)間:78.536 毫秒 我的程序執(zhí)行時(shí)間:44.406 毫秒 快了 34.13
c++程序執(zhí)行時(shí)間:79.521 毫秒 我的程序執(zhí)行時(shí)間:49.285 毫秒 快了 30.236
c++程序執(zhí)行時(shí)間:78.469 毫秒 我的程序執(zhí)行時(shí)間:42.266 毫秒 快了 36.203
c++程序執(zhí)行時(shí)間:79.798 毫秒 我的程序執(zhí)行時(shí)間:48.401 毫秒 快了 31.397
c++程序執(zhí)行時(shí)間:83.086 毫秒 我的程序執(zhí)行時(shí)間:41.221 毫秒 快了 41.865
c++程序執(zhí)行時(shí)間:80.128 毫秒 我的程序執(zhí)行時(shí)間:34.254 毫秒 快了 45.874
c++程序執(zhí)行時(shí)間:83.818 毫秒 我的程序執(zhí)行時(shí)間:35.591 毫秒 快了 48.227
c++程序執(zhí)行時(shí)間:87.433 毫秒 我的程序執(zhí)行時(shí)間:37.273 毫秒 快了 50.16
平均快了 37.0254
提升比例 0.460625
solution5:
// 動(dòng)態(tài)進(jìn)行多線程劃分
#include <iostream>
#include <chrono>
#include<stack>//使用stack時(shí)需要的頭文件
#include<mingw.thread.h> // 我的vscode 如果是別的編譯器直接用thread包就可以
using namespace std;
int maxLength = 1000000;// 測(cè)試數(shù)據(jù)長(zhǎng)度
int devideSize = maxLength/100; // 開新線程標(biāo)準(zhǔn) 防止產(chǎn)生太多線程 數(shù)據(jù)長(zhǎng)度大于此數(shù)時(shí)開啟新線程
int testNum = 15;// 測(cè)試次數(shù)
// volatile int maxThread
int compare(const void *a, const void *b)
{
int *pa = (int*)a;
int *pb = (int*)b;
return (*pa )- (*pb); //從小到大排序
}
int* getRand(int length)
{
int* n = new int[length];
int i;
for(i=0;i<length;i++){
n[i] = rand();
}
return n;
}
void threadForSort(int q[], int ll, int rr)
{
// thread* all[10000];
// int thNum = 0;
// 消遞歸
int ind = 0;
int l,r;
int* sta1 = new int[1000000]; // 也可以用stack 沒太大差別 所以暫時(shí)沒優(yōu)化
sta1[ind++] = ll;
sta1[ind++] = rr;
while(ind>0){
r = sta1[--ind];
l = sta1[--ind];
if (l >= r) continue;
if(r-l+1<=20){
for (int i = l+1; i <= r; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
continue;
}
int i = l - 1, j = r + 1, x =(l + r) >> 1;
// 另一種取中
int lll = 5;
for (int i = l+1; i <= l+lll; i++) {
int key = q[i];
int j = i - 1;
while (j >= l && q[j] > key) {
q[j + 1] = q[j];
j--;
}
q[j + 1] = key;
}
int te = q[l+lll];
q[l+lll] = q[x];
q[x] = te;
i = l+lll-1;
x = q[x];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j){
int rdf = q[i];
q[i] = q[j];
q[j] = rdf;
}
}
// thread* point1 = NULL;
// thread* point2 = NULL;
if( j-l>devideSize ){
thread newTh1(threadForSort, q, l,j);
// all[thNum++] = &newTh1;
// point1 = &newTh1;
newTh1.join();
}else{
sta1[ind++] =l ;
sta1[ind++] =j ;
}
if( r-j>devideSize ){
thread newTh1(threadForSort, q, l,j);
// point2 = &newTh1;
newTh1.join();
// all[thNum++] = &newTh1;
}else{
sta1[ind++] =j+1 ;
sta1[ind++] =r ;
}
}
delete[] sta1;
}
// 元素互換
void swap(int* arr,int i,int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
void mysort(int *n,int l){
threadForSort(n,0,l-1);
}
void comprehensiveTest()
{// 進(jìn)行100次測(cè)試 算平均時(shí)間 計(jì)算性能提升
double cAllTime = 0;
double myAllTime = 0;
int i,j;
int total = maxLength;
for(i=0;i<testNum;i++){
int *num1 = getRand(total);
int* num2 = new int[total];
for(j=0;j<total;j++){
num2[j] = num1[j];
}
auto start1 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
qsort(num1, total, sizeof(int), compare);
auto end1 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
auto start2 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
mysort(num2 , total);
auto end2 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
for(j=0;j<total;j++){
if(num1[i] !=num2[i]){
cout << "出錯(cuò)了" << endl;
break;
}
}
delete[] num1;
delete[] num2;
std::chrono::duration<double, std::milli> cTime = end1 - start1; // 計(jì)算執(zhí)行時(shí)間
std::chrono::duration<double, std::milli> myTime = end2 - start2; // 計(jì)算執(zhí)行時(shí)間
std::cout << "c++程序執(zhí)行時(shí)間:" << cTime.count() << " 毫秒" << " " << "我的程序執(zhí)行時(shí)間:" << myTime.count() << " 毫秒" ;
double gap = cTime.count()-myTime.count();
if(gap>0){
cout << " 快了 " << gap << " " <<endl;
}else{
cout << " 慢了 " << -1*gap << " " <<endl;
}
cAllTime +=cTime.count();
myAllTime+=myTime.count();
}
cAllTime/=testNum;
myAllTime/=testNum;
cout << "平均快了 " << cAllTime-myAllTime << endl;
cout << "提升比例 " << (cAllTime-myAllTime)/cAllTime << endl;
}
void compareTest(){
int count = 7;
int allLen[count] = {10000,50000,100000,1000000 , 5000000,8000000 , 10000000};
// int myScore;
// int cScore = myScore = 0;
int i,j;
for(i=0;i<count;i++){
int *num1 = getRand(allLen[i]);
int* num2 = new int[allLen[i]];
for(j=0;j<allLen[i];j++){
num2[j] = num1[j];
}
auto start1 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
qsort(num1, allLen[i], sizeof(int), compare);
auto end1 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
auto start2 = std::chrono::high_resolution_clock::now(); // 記錄開始時(shí)間
mysort(num2 , allLen[i]);
auto end2 = std::chrono::high_resolution_clock::now(); // 記錄結(jié)束時(shí)間
for(j=0;j<allLen[i];j++){
if(num1[i] !=num2[i]){
cout << "出錯(cuò)了" << endl;
break;
}
}
delete[] num1;
delete[] num2;
std::chrono::duration<double, std::milli> cTime = end1 - start1; // 計(jì)算執(zhí)行時(shí)間
std::chrono::duration<double, std::milli> myTime = end2 - start2; // 計(jì)算執(zhí)行時(shí)間
std::cout << "c++程序執(zhí)行時(shí)間:" << cTime.count() << " 毫秒" << " " << "我的程序執(zhí)行時(shí)間:" << myTime.count() << " 毫秒" ;
double gap = cTime.count()-myTime.count();
if(gap>0){
cout << " 快了 " << gap << " " <<endl;
}else{
cout << " 慢了 " << -1*gap << " " <<endl;
}
}
}
int main()
{
srand(time(0));
// compareTest();
comprehensiveTest();
return 0;
}
性能比較輸出:
PS E:\c++_project\test\算法實(shí)驗(yàn)1\output> cd 'e:\c++_project\test\算法實(shí)驗(yàn)1\output'
PS E:\c++_project\test\算法實(shí)驗(yàn)1\output> & .\'solution5.exe'
c++程序執(zhí)行時(shí)間:79.938 毫秒 我的程序執(zhí)行時(shí)間:30.877 毫秒 快了 49.061
c++程序執(zhí)行時(shí)間:77.712 毫秒 我的程序執(zhí)行時(shí)間:34.406 毫秒 快了 43.306
c++程序執(zhí)行時(shí)間:80.698 毫秒 我的程序執(zhí)行時(shí)間:28.973 毫秒 快了 51.725
c++程序執(zhí)行時(shí)間:77.65 毫秒 我的程序執(zhí)行時(shí)間:30.457
毫秒 快了 47.193
c++程序執(zhí)行時(shí)間:78.662 毫秒 我的程序執(zhí)行時(shí)間:31.154 毫秒 快了 47.508
c++程序執(zhí)行時(shí)間:79.299 毫秒 我的程序執(zhí)行時(shí)間:22.993 毫秒 快了 56.306
c++程序執(zhí)行時(shí)間:79.999 毫秒 我的程序執(zhí)行時(shí)間:26.001 毫秒 快了 53.998
c++程序執(zhí)行時(shí)間:78.309 毫秒 我的程序執(zhí)行時(shí)間:24.786 毫秒 快了 53.523
c++程序執(zhí)行時(shí)間:79.532 毫秒 我的程序執(zhí)行時(shí)間:31.678 毫秒 快了 47.854
c++程序執(zhí)行時(shí)間:79.489 毫秒 我的程序執(zhí)行時(shí)間:22.993 毫秒 快了 56.496
c++程序執(zhí)行時(shí)間:79.261 毫秒 我的程序執(zhí)行時(shí)間:20.153 毫秒 快了 59.108
c++程序執(zhí)行時(shí)間:79.368 毫秒 我的程序執(zhí)行時(shí)間:26.855 毫秒 快了 52.513
c++程序執(zhí)行時(shí)間:77.946 毫秒 我的程序執(zhí)行時(shí)間:31.01
毫秒 快了 46.936
c++程序執(zhí)行時(shí)間:79 毫秒 我的程序執(zhí)行時(shí)間:26.999 毫
秒 快了 52.001
c++程序執(zhí)行時(shí)間:78.758 毫秒 我的程序執(zhí)行時(shí)間:19 毫
秒 快了 59.758
平均快了 51.8191
提升比例 0.655594
總結(jié)
- 上一篇: [WPF]浅析资源引用(pack URI
- 下一篇: 【调度算法】并行机调度问题遗传算法