找回密码
 欢迎注册
楼主: silitex

[原创] 位排序 -- 基于计数排序和基数排序产生的特例

[复制链接]
发表于 2009-11-3 16:25:47 | 显示全部楼层
while (i<j)
  {
      if  bitx( X[ i ],k) > bitx(X [ j],k) //元素想x[ i ]的第k比特大于X[j]的第k比特
          X [i ] <--> X[ j ]  //交换x[ i ]与x[j]
      i++;
     j--;
  }


这个逻辑有问题,等我有空儿时订正它。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-11-3 18:39:22 | 显示全部楼层
本帖最后由 liangbch 于 2009-11-3 18:43 编辑

以下是我写的位排序代码,包含排序函数和测试程序
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <memory.h>

  4. typedef unsigned long DWORD;
  5. typedef int BOOL;

  6. #define TRUE        1
  7. #define FALSE        0

  8. #define MAX_LEN        65536

  9. DWORD data[MAX_LEN];
  10. DWORD databak[MAX_LEN];

  11. void printArray(DWORD *p, int len);

  12. //bit 排序核心算法,这是一个递归函数
  13. void bitSort(DWORD *p, int begin, int end, DWORD mask )
  14. {
  15.         int i=begin;
  16.         int j=end;
  17.                
  18.         if ( j==i+1 && p[j]>=p[ i ])
  19.                 return;
  20.         if ( mask<=0)
  21.                 return ;
  22.         while (i<j)
  23.         {
  24.                 DWORD t;
  25.                 while ( (p[ i ] & mask) ==0 && i<=end)
  26.                         i++;
  27.                 while ( (p[j] & mask) >0 && j>=begin)
  28.                         j--;
  29.                
  30.                 if (i<j)
  31.                 {
  32.                         t=p[ i ];
  33.                         p[ i ]=p[j];
  34.                         p[j]=t;
  35.                 }
  36.         }
  37.        
  38.         mask/=2;        i--;        j++;
  39.         if (i>begin)
  40.         {
  41.                 bitSort(p,begin,i,mask);
  42.         }
  43.        
  44.         if (j<end)
  45.         {
  46.                 bitSort(p,j,end,mask);
  47.         }
  48. }

  49. //使用 bit sort 对数组p 进行排序
  50. void mySort1(DWORD *p, int len)
  51. {
  52.         DWORD max=p[0];
  53.         DWORD mask=2147483648;
  54.         int i;
  55.        
  56.         if (len<2)
  57.                 return;

  58.         for (i=1;i<len;i++)
  59.         {
  60.                 if (p [ i ] > max)
  61.                         max=p[ i ];
  62.         }

  63.         while ( mask > max)
  64.                 mask/=2;
  65.         bitSort(p,0,len-1,mask);
  66. }

  67. //打印数组
  68. void printArray(DWORD *p, int len)
  69. {
  70.         int i;
  71.         for (i=0;i<len;i++)
  72.         {
  73.                 if (i>0)
  74.                         printf(",");
  75.                 printf("%u",p[ i ]);
  76.         }
  77.         printf("\n");
  78. }

  79. //检查数组是否是增序排列
  80. BOOL checkArray(DWORD *p,int len)
  81. {
  82.         int i;
  83.         BOOL ret=TRUE;
  84.         for (i=0;i<len-1;i++)
  85.         {
  86.                 if (p[i+1]< p[ i ] )
  87.                 {
  88.                         ret=FALSE;        break;
  89.                 }
  90.         }

  91.         return ret;
  92. }

  93. //bit排序测试程序,产生1 到 MAX_LEN,对长度为1到 MAX_LEN的数组进行排序
  94. void testBitSort()
  95. {
  96.         int i,j;
  97.         for (i=1;i<=MAX_LEN;i++)
  98.         {
  99.                 for (j=0;j<i;j++)
  100.                 {
  101.                         data[j]= (rand() & 255);
  102.                 }
  103.                
  104.                 memcpy(databak,data,i*sizeof(DWORD));
  105.                 mySort1(data,i);
  106.                
  107.                 if ( !checkArray(data,i) )
  108.                 {
  109.                         printf("error\n");
  110.                        
  111.                         printf("Before sort\n\t");
  112.                         printArray(databak,i);

  113.                         printf("After sort\n\t");
  114.                         printArray(data,i);
  115.                         break;
  116.                 }
  117.         }
  118. }

  119. int main(int argc, char* argv[])
  120. {
  121.         testBitSort();
  122.         return 0;
  123. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-11-3 18:52:12 | 显示全部楼层
10# liangbch


当关键字的范围很窄是,可比较 ( p[ i ] - min)的第k比特,速度可大大加快。比如有1百万个数,关键字的范围为 1000000 到 1000200。 则其复杂度为 8*1百万,因为 p[ i ] - min 的范围为0 到 200, 第1遍检测 bit7,第2遍检测 bit6,第8遍检测 bit0。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-11-4 08:55:51 | 显示全部楼层
本帖最后由 silitex 于 2009-11-4 09:15 编辑
10# liangbch


当关键字的范围很窄是,可比较 ( p[ i ] - min)的第k比特,速度可大大加快。比如有1百万个数,关键字的范围为 1000000 到 1000200。 则其复杂度为 8*1百万,因为 p[ i ] - min 的范围为0 到 200, ...
liangbch 发表于 2009-11-3 18:52

感谢您的回答,程序中也考虑了关键字很窄的时候的范围,比如取值范围为:1000000 到 1000200,是则Hash成:0~200,那么就等于用8位(2^8=256)排序即可!(传入了UNIQUE_HASH_CALLBACK pUniqueHashFunc这个参数就是为了针对每一个不同的数据传入不同的Hash函数,以便做特殊处理)
您的算法我再花时间看看!
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-11-4 09:00:31 | 显示全部楼层
本帖最后由 silitex 于 2009-11-4 14:11 编辑
关于位排序,前人已有研究。请看 http://bbs.emath.ac.cn/viewthrea ... &fromuid=25#pid9829。
快速扫了你代码中的注释,感觉你的这个实现不太好,需要分配额外的空间。
《无符号整数按位快速排序算法》基本思想是 ...
liangbch 发表于 2009-11-3 15:02

呵呵,在写完这个位排序算法的时候,我看的就是您提供的前人的位排序算法,后来经过VC的单步跟踪,发现前人的位排序算法在边值判断上(会有重复判断的可能)要处理得没有那么好。
也很感谢您的批评和指正!
哎,做了一件前人做过的事情,还好这个事情不难做,没浪费多少时间!
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-11-4 09:09:47 | 显示全部楼层
看完了您的代码:
其中:
#                 if (i<j)
#                 {
#                         t=p[ i ];
#                         p[ i ]=p[j];
#                         p[j]=t;
#                 }
这里因为没有进行一次i++和j--,所以下次循环的时候又需要在当前位置再判断一次,所以造成了判断次数的增加!(我最开始也是这样做的,呵呵,后来单步跟踪的时候发现这里有多余的判断,所以在他们交换值完毕的时候立即进行了一次i++和j--,以便下次循环不用再判断了)
您的这段写得比我简洁,学习了!
#                 while ( (p[ i ] & mask) ==0 && i<=end)
#                         i++;
#                 while ( (p[j] & mask) >0 && j>=begin)
#                         j--;
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-11-4 11:31:11 | 显示全部楼层
哈哈,说点儿题外话,个人感觉那篇论文的代码很复杂,而且有错,不能编译。感觉作者的编程功底不是很好。现在有好多“学者”,就是为了写论文写论文。
  你的代码写的很工整!不错!
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-11-4 11:35:08 | 显示全部楼层
7# silitex

学术氛围使然,有些人就是喜欢弄虚作假。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-11-4 12:18:27 | 显示全部楼层
看完了您的代码:
其中:
#                 if (i=begin)
#                         j--;
silitex 发表于 2009-11-4 09:09


很不幸,你的修改时错的,你增加i++,j--这行代码,然后运行一下我的测试程序就明白了。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-11-4 12:31:35 | 显示全部楼层
看了一下周建钦写的那篇文章,本质上和我的代码是一致的。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-5-11 17:48 , Processed in 0.043777 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表