#include "stdafx.h"
#include <algorithm>
#include <ctime>
void xsort(int **, int **);
using namespace std;
#define MAX_SIZE 10000000
#define TEST_TIMES 100
inline int cmp(const void *a, const void *b) {
return(*(int *)a - *(int *)b);
}
void main() {
LARGE_INTEGER num;
long long start1, end1, start2, end2;
double freq;
QueryPerformanceFrequency(&num);
freq = num.QuadPart;
srand((unsigned)time(NULL));
int * d1 = new int[MAX_SIZE], *d2 = new int[MAX_SIZE];// , *d3 = new int[MAX_SIZE];
long long dm;
int i;
for (int times = 0; times < TEST_TIMES; ++times)
{
bool bzs = false;
int isdd = 0;
for (i = 0; i < MAX_SIZE; ++i)
{
// 隨機數組測試 3.5倍
d1[i] = ((rand() << 15) | rand()) % MAX_SIZE;
// 重複數組測試
/*if (bzs){
isdd--;
d1[i] = d1[i-isdd];
if(isdd==0) bzs = false;
}else {
d1[i] = ((rand() << 15) | rand()) % MAX_SIZE;
++isdd;
if(isdd>10) bzs = true;
}*/
// 正序數組測試 95倍
// d1[i] = i;
// 逆序測試 12倍
// d1[i] = MAX_SIZE - i;
d2[i] = d1[i];
}
QueryPerformanceCounter(&num);
start1 = num.QuadPart;
qsort(d2, MAX_SIZE, sizeof(d2[0]), cmp);
QueryPerformanceCounter(&num);
end1 = num.QuadPart;
printf("qsort: %f ", ((double)(end1 - start1)) / freq);
QueryPerformanceCounter(&num);
start2 = num.QuadPart;
int vksz = 4;
int sx = MAX_SIZE;
while (sx > 0) {
sx = sx >> 1;
vksz += 4;
};
int ** VK = new int *[vksz];
*VK = &d1[0];
*(VK+1)= &d1[MAX_SIZE - 1];
xsort(VK, VK+vksz-1);
delete(VK);
QueryPerformanceCounter(&num);
end2 = num.QuadPart;
printf("xsort: %f ", ((double)(end2 - start2)) / freq);
dm = 0;
for (i = 0; i < MAX_SIZE; ++i)
{
dm += d1[i] - d2[i];
}
printf("dm: %lld,%f; \n", dm, (double)(end1 - start1)/(double)(end2 - start2));
/*QueryPerformanceCounter(&num);
start = num.QuadPart;
sort(d3, d3 + MAX_SIZE);
QueryPerformanceCounter(&num);
end = num.QuadPart;
printf("sort: %f \n", ((double)(end - start)) / freq);*/
}
delete(d1);
delete(d2);
}
// 新快速排序算法(新快排)
// 參數: 區間表起始,區間表結尾; 區間表格式: 起始位置1,結束位置1,起始位置2,結束位置2 ....
void xsort(int **o, int **x) {
static int *i, *j, *p; // 左指針,右指針,軸項指針
static int **r; // 起始暫存,結尾暫存
static int s; // 關鍵字
static bool b; // 標記軸右邊是否有交換位置;
register int vs;
if (*o >= *(o + 1)) return; // >=2 個元素
i = *o;
j = *(o + 1);
r = o;
do{
p = j - ((j - i) >> 1); // 取中間值爲軸項(偏右邊)
s = *p;
b = false;
do {
// 要點:
// 1. 關鍵字s始終在 *i與*j之間,起到擋板作用,免去i,j比較的同時,也可防止i\j過頭
// 2. 相鄰兩項判斷,逆序就反轉;
// 3. 如果右邊沒有一次交換,則右邊爲有序,b作爲標記;
while(*i < s) {
vs = *i;
// 微型插值排序
while (vs > *(++i)) *(i - 1) = *i;
if (*(i - 1) != vs) *(i - 1) = vs;
}
if(*i>s) { *p = *i; *i = s;}
// *i==s (右邊*j插值排序的擋板)
while(*j > s) {
vs = *j;
// 微型插值排序
while (vs < *(--j)) *(j + 1) = *j;
if (*(j + 1) != vs) { *(j + 1) = vs; b = true; }
}
if (*j<s) { *i = *j; *j = s; b = true;}
// *j==s (左邊*i插值排序的擋板)
p = j;
} while (++i < j);
if (b && (++p < *(r + 1))) { // 右邊執行
if (--j <= *r) {
// 左邊捨棄
*r = p; // 新的起始條件
i = p;
j = *(r + 1);
continue; // 下一次循環;
}
if (r + 3 <= x) {
// 左邊暫存
*(r + 3) = *(r + 1);
*(r + 1) = j;
r += 2;
*r = p; // 新的起始條件
i = p;
j = *(r + 1); // 新的結束條件
continue; // 下一次循環;
}
// 左邊全部重排;
// printf("1,");
*(o + 1) = j;
r = o + 2;
*r = p;
i = p;
j = *x;
*(r + 1) = j;
continue; // 下一次循環;
}
while (--j > *r && *j == s);
if (j > *r) {
*(r + 1) = j;
i = *r;
continue; // 下一次循環;
};
do {
r -= 2;
if (r < o) return;
i = *r;
j = *(r + 1);
while (j > i && *j == *(j + 1)) j--;
} while (j <= i);
} while(1);
}