c语言快排测试数据,[原创]快排改进算法

最近研究快排,对快排对低熵数据的效率很不满意,于是研究了对快排平均效率的提高的问题。

快排处理有序数据时,仍需要进行划分,一分到底,尤其是大部分数据集中在一个集合中,使快排退化为了冒泡。传统做法是在数据中任取一数作为划分轴,该法确实大大提高了快排的平均效率,但是这样仍不能达到对于已排序数据O(n)的时间效率。那么,还有什么办法改进呢?

我们发现,主要问题集中在传统快排无法对数据整体进行判断,所有情况都按照熵最高处理,那么,只要在快排中加入数据分析,就可以避免遇到低熵数据仍进行大量运算。

那么,我们在划分函数中,在high与low移动至中间时,比较相邻两个数据大小,并按照顺序进行交换,类似于冒泡法,并定义两个变量,对low与high是否交换过进行计数。若没有交换过,则表明该部分数据已经有序,在qsort函数递归时,不必再对low或high进行操作,即不必对low或high进行递归。这样,就大大减少了递归次数,降低了时间复杂度。如此一来,传统情况下的最差情况,似乎就成了最好情况,由O(n^2)变成了O(n)。

c版源代码:

void swap(int *px, int *py){

//定义交换函数

int temp;

temp = *px;

*px = *py;

*py = temp;

}

int partition(int data[], int low, int high, int *bol, int

*boh){

//定义划分函数

if(data[low] >= data[high]){

if (data[low] > data[(low + high) / 2]) swap(&data[low],

&data[(low + high) / 2]);

else if(data[high] > data[(low + high) / 2])

swap(&data[low], &data[high]);

}

else{

if(data[high] < data[(low + high) / 2]) swap(&data[low],

&data[high]);

else if(data[low] < data [(low + high) / 2])

swap(&data[low], &data[(low + high) /2]);

}//对data[low],data[high],data[(low + high) /

2]取中值与data[low]交换

//此处不推荐使用时间随机函数,因为好的随机函数本身有很大的时间复杂度

int key = data[low], countl = 0, counth = 0, n = high, m =

low;//countl,counth分别对low子表与high子表数据交换情况计数

int *temh = boh, *teml = bol;

while(low < high){

while(low < high && data[high] >= key){

if(high < n)

if(data[high] > data[high + 1]){

//进行冒泡操作

swap(&data[high], &data[high +

1]);

//对交换操作进行计数

counth = 1;

}

--high;//移动指针

}

data[low] = data[high];//交换高低指针数据

while(low < high && data[low] <= key){

if(low > m)

if(data[low - 1] > data[low]){

//进行冒泡操作

swap(&data[low - 1], &data[low]);

//对交换操作进行计数

countl = 1;

}

++low;//移动指针

}

data[high] = data[low];//交换高低指针数据

}

data[low] = key;

*temh = counth;

*teml = countl;

return low;

}

void qsort(int data[], int low, int high){

//定义递归实现qsort函数

if(low == high) return;//递归终点

else{

int bol,boh;

int key = partition(data, low, high, &bol, &boh);

if(bol ^ 0) qsort(data, low, key -

1);//根据标记判断是否对low子表进行操作

if(boh ^ 0) qsort(data, key + 1,

high);//根据标记判断是否对high子表进行操作

return;

}

}

好不容易调出来了,因为疏忽,把l和h搞反了,调了两晚上才弄出来,无语……再也不犯低级错误了!·¥#%!

测试者:stevenjl

一、测试系统

CPU: Intel Celeron 4 2.0 GHz Memory: 256MB

System: Windows XP SP2 \ Cena 0.6

二、待测试算法(均用C语言编写)

1.快速排序(无优化,追求程序简单)【Qsort】

2.随机化快速排序【Rnd_Qsort】

3.楼主提供的程序【DZ_Qsort】

4.希尔排序【Shell】

三、数据

测试点

长度

备注

1

1024

随机数据(随机范围0~maxint,下同)

2

10240

随机数据

3

102400

随机数据

4

102400

随机数据

5

1024000

随机数据

6

2000000

递增数据(1,2,3…2000000)

7

2000000

递减数据(2000000…3,2,1)

8

2000000

峰状数据(1,2,3…1000000…3,2,1)

9

2000000

相同数据(32767…)

10

2000000

谷状数据(1000000…3,2,1,1,2,3…1000000)

四、文件长度(已经删除所有注释和段首空格)

程序

长度

Qsort

286字符

Rnd_Qsort

359字符

DZ_Qsort

1184字符

Shell

200字符

五、测试成绩

测试点

Qsort

Rnd_Sort

DZ_Qsort

Shell

1

0.01

0.01

0.01

0.03

2

0.03

0.03

0.01

0.03

3

0.26

0.25

0.23

0.29

4

0.25

0.25

0.26

0.26

5

2.39

2.32

2.39

3.31

6

60.06(超时中止)

5.09

4.85

5.2

7

60.08(超时中止)

5.17

4.9

5.25

8

60.13(超时中止)

5.07

4.84

5.18

9

60.05(超时中止)

4.56

4.29

4.6

10

60.03(超时中止)

5.06

39.03s后崩溃

4.85

注:测试方法与数据参考Wasltone在OIBH的相关帖子

好久之前贴在oifans上了,其实觉得还有改进的余地。懒得弄了,谁喜欢谁去尝试一下吧。应付oi这个足够了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值