研究出一个排序算法,比qsort快320%!!!!!

新快排的核心思想有四点:

1.  基于快排的二分对比;

2.  二分对比的同时用最小的代价让数组趋于有序,这样中间值大概率位于中间位置上,二分对比取中间值作基准值效率是最优的;

3.  二分对比的同时用最小的代价检查右边是否有逆序,如果右边非逆序则可跳过右边的判断;

4.  用循环取代递归调用;

 

新快排的步骤:

1.   设置左指针i、右指针j、中位指针p;

2.   取中位指针指向的元素为基准数s;

3.   判断左指针指向的元素是否小于基准数,小于,则循环判断下一项是否比当前项小,是则交换,不是则循环第3步;

4.   判断左指针指向的元素是否大于基准数,大于,则交换左指针i与中位指针p所指的元素;

5    判断右指针指向的元素是否大于基准数,大于,则循环判断下一项是否比当前项大,是则交换,不是则循环第5步;

6.   判断右指针指向的元素是否小于基准数,小于,则交换右指针j与左指针i所指的元素;

7.   循环1至7步,直到i>j;

 

代码如下( 注:如果汇编级优化,效率还可大幅提高)

#include "stdafx.h" 
#include <algorithm>
#include <ctime>

using namespace std;
#define MAX_SIZE 10000
#define TEST_TIMES 1000
#define  vksize 1000

// 新快速排序算法(新快排)
// 参数: 区间表起始,区间表结尾;  区间表格式: 起始位置1,结束位置1,起始位置2,结束位置2 .... 
void  xsort(int **r, int **x) {
	static int *i, *j, *p;  // 左指针,右指针,轴项指针
	static int **k = x; int **o = r;  // 起始暂存,结尾暂存  
	static int s;   // 关键字	 
	static bool b;  // 标记轴右边是否有交换位置; 

	while (r >= o) {
		i = *r;
		j = *(r + 1);
		while (i < j) { // >=2 个元素 
			p = j - ((j - i) >> 1); // 取中间值为轴项(偏右边)   
			s = *p;
			b = false;
			do {
				// 要点:
				// 1. 关键字s始终在 *i与*j之间,起到挡板作用,免去i,j比较的同时,也可防止i\j过头
				// 2. 相邻两项判断,逆序就反转;
				// 3. 如果右边没有一次交换,则右边为有序,b作为标记;
				while (*i < s) { register int vs = *i; i++; while (vs > *i) { *(i - 1) = *i; i++; }; if (*(i - 1) != vs) *(i - 1) = vs; }   
				// *i>=s
				if (*i > s) { *p = *i; *i = s; b = true; }
				// *i==s 
				while (*j > s) { register int vs = *j; j--; while (vs < *j) { *(j + 1) = *j; j--; }; if (*(j + 1) != vs) { *(j + 1) = vs; b = true; } }
				// *i==s  *j<=s
				if (*j < s) { *i = *j; *j = s; b = true; }
				// *i>=s
				p = j;
				++i;
			} while (i < j);

			while (--j > *r && *j == s);
			if (b) {
				i = p;
				while (++i < *(r + 1) && *i == s);

				if (i < *(r + 1)) { // 右边执行
					if (j > *r) { // 左边暂存
						// 区间暂存不够用时,把空间压缩一半;   
						if ((r + 3) > k) { // x>=o + 3
							if (k < x) { // 有折半
								*o = *k;
								*k = *x;
							} else { // 没折半
								k = x - ((x + 1 - o) >> 1);
								*k = *o;
								*(o + 1) = *(r + 1);
								*(r + 1) = j;
								r = o;
								*r = i;
								j = *(r + 1);
								continue;  // 下一次循环; 
							}
						}
						*(r + 3) = *(r + 1);
						*(r + 1) = j;
						r++; r++;
					}
					*r = i;
					j = *(r + 1);
					continue;  // 下一次循环; 
				}
			}
			if (j > *r) {
				*(r + 1) = j;
				i = *r;
				continue;  // 下一次循环;
			}
			break;
		};
		r--; r--;
	};
}
inline int cmp(const void *a, const void *b) {
	return(*(int *)a - *(int *)b);
} 

int main()
{  
	LARGE_INTEGER  num;
	long long start, end;
	double freq;
	QueryPerformanceFrequency(&num);
	freq = num.QuadPart;
	 
	srand((unsigned)time(NULL));
	int d1[MAX_SIZE],d2[MAX_SIZE],d3[MAX_SIZE];
	int * VK[vksize];
	long long sum;
	int i;
	for (int times = 0; times < TEST_TIMES; ++times)
	{
		sum = 0;
		for (i = 0; i <MAX_SIZE; ++i)
		{
			d1[i] = rand() % MAX_SIZE;
			// d1[i] = i;
			d2[i] = d1[i];
			d3[i] = d1[i];
			sum += d1[i];
		}
		QueryPerformanceCounter(&num);
		start = num.QuadPart;
		VK[0] = d1;
		VK[1] = &d1[MAX_SIZE - 1];
		xsort(VK, &VK[vksize - 1]); 
		QueryPerformanceCounter(&num);
		end = num.QuadPart; 
		for (i = 0; i < MAX_SIZE - 1; ++i)
		{
			sum -= d1[i];
			if (d1[i] > d1[i + 1])
			{
				printf("algorithm failed\n");
				for (int j = 0; j < MAX_SIZE - 1; ++j)
				{
					printf("%d,", d1[j]);
				}
				printf("%d", d1[MAX_SIZE - 1]);
				return 1;
			}
		}
		sum -= d1[i];
		printf("xsort: %f,%lld  ", ((double)(end - start)) / freq,sum);

		QueryPerformanceCounter(&num);
		start = num.QuadPart;
		qsort(d2, MAX_SIZE, sizeof(d2[0]), cmp);
		QueryPerformanceCounter(&num);
		end = num.QuadPart;
		printf("qsort: %f;   ", ((double)(end - start)) / freq);

		QueryPerformanceCounter(&num);
		start = num.QuadPart;
		sort(d3, d3 + MAX_SIZE);
		QueryPerformanceCounter(&num);
		end = num.QuadPart;
		printf("sort: %f \n", ((double)(end - start)) / freq);	
	}  

	getchar(); 
	return 0;
} 

采用随机数组测试:

采用有序数组测试 :

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