新快排二次優化,最優情況可比qsort快95倍,隨機數組測試平均3.4倍,!!!!

#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);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章