《编程珠玑》一段代码看不懂,“a[i>>SHIFT] |= (1<<(i & MASK));”

沭水河畔 2010-01-06 10:25:02
哪位朋友可以帮我解释一下啊?
完整代码是这样子的,顺便问一下,C代码写成这样,得几年功力?
/* Copyright (C) 1999 Lucent Technologies */
/* From 'Programming Pearls' by Jon Bentley */

/* bitsort.c -- bitmap sort from Column 1
* Sort distinct integers in the range [0..N-1]
*/

#include <stdio.h>

#define BITSPERWORD 32
#define SHIFT 5
#define MASK 0x1F
#define N 10000000
int a[1 + N/BITSPERWORD];

void set(int i) { a[i>>SHIFT] |= (1<<(i & MASK)); }
void clr(int i) { a[i>>SHIFT] &= ~(1<<(i & MASK)); }
int test(int i){ return a[i>>SHIFT] & (1<<(i & MASK)); }

int main()
{ int i;
for (i = 0; i < N; i++)
clr(i);
/* Replace above 2 lines with below 3 for word-parallel init
int top = 1 + N/BITSPERWORD;
for (i = 0; i < top; i++)
a[i] = 0;
*/
while (scanf("%d", &i) != EOF)
set(i);
for (i = 0; i < N; i++)
if (test(i))
printf("%d\n", i);
return 0;
}
...全文
585 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
Li103ZzZ 2011-07-19
  • 打赏
  • 举报
回复
对,是想法太好了,赞...
crazyhan00 2011-06-26
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 wplin5201314 的回复:]

我就不明白为什么要1<<
[/Quote]

是1左移(i & MASK)位,别以为是(i & MASK)左移1位了 呵呵
shuaiwang_01 2011-05-28
  • 打赏
  • 举报
回复
不错不错,位操作真是强大啊。
wplin5201314 2011-03-04
  • 打赏
  • 举报
回复
我就不明白为什么要1<<
wplin5201314 2011-03-03
  • 打赏
  • 举报
回复
大学快毕业了,回头看这本书,以为很容易就能看懂,没想到第一个程序就看了好久
科多兽 2010-08-27
  • 打赏
  • 举报
回复
一直都知道整数相乘没有直接移位效率高,但看到这个设置位、清除位、测试位操作,居然没有看明白,看来基本功还不到位啊,要努力。
gcanyon 2010-02-02
  • 打赏
  • 举报
回复
好啊, 高深其实都是将基本功用到最好
jernymy 2010-01-06
  • 打赏
  • 举报
回复
这代码好省啊
haohaokingXP 2010-01-06
  • 打赏
  • 举报
回复
#define BITSPERWORD 32
#define SHIFT 5
#define MASK 0x1F
#define N 10000000
int a[1 + N/BITSPERWORD];

void set(int i) { a[i>>SHIFT] |= (1<<(i & MASK)); } //就是将指定的bit赋1
void clr(int i) { a[i>>SHIFT] &= ~(1<<(i & MASK)); } //就是将指定的bit清0
int test(int i){ return a[i>>SHIFT] & (1<<(i & MASK)); } //就是取一下存入的值

是每5 bit是一组。
while (scanf("%d", &i) != EOF)
set(i);
根据输入的i ,放入指定位置。
作者的想法是,按照输入的数据,放入该数据的位置上。
比如你输入,4,2,3,1
那么第一个4就是
0000000000010000
而输入2的时候
0000000000010100
输入3时候
0000000000011100
输入1的时候
0000000000011110

然后从bit0~~~bit N判断该位是不是0,如果不是0的话,就为有数组,并作输出,相当排序。
for (i = 0; i < N; i++)
if (test(i)) //
printf("%d\n", i);

太经典了!!!!!!!!!

C语言功力不需要很强,关键是想法太好了!!
cattycat 2010-01-06
  • 打赏
  • 举报
回复
对,左移5位相当于除2^5也就是32,i & 0x1F 保留了低五位,相当于模32.
i是int类型,32位的,而a是int型数组,所以除以32可以知道是在a的数组中哪一个下标,模32可以确定某一位。
loveour 2010-01-06
  • 打赏
  • 举报
回复
void set(int i) { a[i>>SHIFT] |= (1<<(i & MASK)); }里面,
a[i>>SHIFT]是第i位应该在第几个int上
(1<<(i & MASK))是第i位在该int上的第几个bit
i&0x1F是i/32的余数


for (i = 0; i < N; i++)
clr(i);每位设为0,
while (scanf("%d", &i) != EOF)
set(i);
从读入获取数据,对应的位置为1
for (i = 0; i < N; i++)
if (test(i))
printf("%d\n", i);
return 0;
遍历所有位,则输出自然有序
jackzhhuang 2010-01-06
  • 打赏
  • 举报
回复
只要是2的倍数都可以这么玩

不用多少年功力,记住,2的倍数的乘除法用位移实现,会者不难,没点破之前是不是觉得很……哈哈
mstlq 2010-01-06
  • 打赏
  • 举报
回复
翻译一下……


void set(int i) { a[i/32] |= (1<<(i%32)); }
void clr(int i) { a[i/32] &= ~(1<<(i %32)); }
int test(int i){ return a[i/32] & (1<<(i %32)); }

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧