编程珠玑第一章中的代码

使用位图法对七位正整数进行排序的算法。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

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

/*
 * i >> SHIFT      :i / (1 << SHIFT) 即i / (1 << 5) = i / 32, 这样获取i在数组a中的下标值,如i=100,则100/32=3,
 *                   所以100在数组a中的位置是3。
 * 1 << (i & MASK) :确定应该在当前数组位置中的第几个二进制位设置为1。
 * MASK的推导的过程:
 * 数字i在当前下标的数组内对应的二进制位是i - (i / 32) * 32,如i=100,就是100 - (100/32)*32 = 100 - 96 = 4
 * 因为前面已经确定100在a[3]中,前面还有a[0],a[1],a[2]三个元素,这三个元素所占的二进制位数正好是96个,所以
 * 100应该在a[3]中第4个二进制位。这是思路,下面说怎么确定MASK的值。
 * 在计算机里加减乘除都是用补码进行的,正整数的补码等于整数本身,负整数的补码等于其反码加1,所以,以i=100为例
 * i - (i / 32) * 32   = 100       - (100 / 32) * 32 = 100 - 96 = 100 + (-96) = 4,等价于
 * i - ((i >> 5) << 5) = 100       - ((100 >> 5) << 5)
 * 为了方便书写,这里用单字节表示。
 *                     = 0110 0100 - (0110 0100 & 1110 0000)
 *                     = 0110 0100 - (0110 0000)
 *                     = 100 + (-96)
 * -96的反码 = 0110 0000按位取反,即: 1001 1111
 * 对应的补码= 反码加1,即: 1010 0000, 故,
 *                     = 0110 0100 + 1010 0000 = 1 0000 0100
 * 结果的最高位多了一个1,这是溢出位,所以结果就是0000 0100 = 4
 * 即 100 + (~(100 & 0xe0) + 1) = i + (~(i & 0xe0) + 1) == i & 0x1f
 * 所以MASK = 0x1F
 */

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(void)
{
    int i, count=100;
    srand((unsigned)time(NULL));
    for (i = 0; i < N; i++)
        clr(i);
    while (count > 0)
    {
        i = rand() % 100;
        set(i);
        count--;
    }
    for (i = 0; i < N; i++)
    {
        printf("%d : ", i);
        if (test(i))
            printf("%d", i);
        else
            printf("%d", 0);
        printf("\n");
    }

    for(i = 0; i < (1 + N/BITSPERWORD); i++)
    {
        printf("%d : %d\n", i, a[i]);
    }
    return 0;
}
时间: 2024-08-05 09:31:51

编程珠玑第一章中的代码的相关文章

编程珠玑第一章习题

第一章习题1解析 以下代码均使用MSVC 6.0编译运行通过,为了便于学习,在原代码的基础上进行了一定的修改. 1.如何使用一个具有库的语言来实现一种排序算法以表示和排序集合,将代码实现可用 1 #include<stdio.h> 2 #include<stdlib.h> 3 int comp(const void *x,const void *y){ 4 return (*(int*)x-*(int*)y); 5 } 6 int a[5]={45,25,64,10,4}; 7 v

编程珠玑第一章习题6.1000个整数排序

题目描述: 1~1000万的整数,随机挑出1000个整数(可重复),每个整数最多可以出现10次.将这些整数按照升序排序. 分析:      1000个整数,我们可以用1000万个字符按大小来记录它出现的次数,如同 3, 1, 5, 6,5  用5个字符数组表示就是 { 1, 0, 1, 0, 2, 1}.1出现1次,所以第一个字符就用1记录:2出现0次,用0记录,以此类推. 然后,我们按从左往右的顺序,第 i 索引的字符是多少,就输出多少遍该索引(索引即是你要输出的整数).输出结果是:1,3,5

编程珠玑第一章习题答案

习题 1.1      如果不缺内存,如何使用一个具有库的语言来实现一种排序算法? 因为C++有sort,JAVA也有,这里以C++为例给出,记住如果用set集合来排序时,是不可以有元素重复的 代码: #include <iostream> #include <cstring> #include <cmath> #include <queue> #include <stack> #include <list> #include <

稀疏集:编程珠玑第一章第九题

<Programming Pearls> solutions for Column 1中的第9题题解 关键字: Sparse set 原题: The effect of  initializing the vector data[0..n-1] can be accomplised with a signature contained in two additional n-element vectors, from and to ,and an integer top. If the ele

编程珠玑——第一章习题

1.如果不缺内存,如何使用一个具有库的语言来实现以后总排序算法和排序集合? 答:这个不同语言有不同的库函数排序C有qsort,java有sort排序,具体就不贴代码了.C++有实现排序的库函数:sort,该函数的实现是快速排序.另外C++的容器Map和set均可以实现排序.由于Map和set的实现是红黑树,所以具有自动排序功能. 2.如何使用位逻辑运算(如与.或.移位)来实现位向量? 这个道题的核心就在于想要把某bit置0,将该位直接和0做与操作,想要保持某bit位不变,将该位与1做与操作,想要

编程珠玑 第一章

题目:一个最多包含n个正整数的文件,每个数都小于n,其中n=10^7,且所有正整数都不重复.求如何将这n个正整数升序排列. 约束:最多有1MB的内存空间可用,有充足的磁盘存储空间. 习题2 习题3 实现位向量用于排序. #include<stdio.h> #define N 10000000 #define Shift 5 #define BitPerWord (sizeof(int)*8) #define Mask ((1<<Shift)-1) int a[1+N/BitPerW

一维向量旋转算法 编程珠玑 第二章

看了编程珠玑第二章,这里面讲了三道题目,这里说一下第二题,一维向量旋转算法. 题目:将一个n元一维向量(例数组)向左旋转i个位置. 解决方法:书上讲解了5种方法,自己只想起来2种最简单方法(下面讲的前两种). 1.原始方法. 从左向右依次移动一位,对所有数据平移:这样循环i次,算法最坏时间复杂度达n^2.耗时不推荐. 2.空间换时间. 顾名思义,申请一个i长度的空间,把前i半部分放到申请空间中,再把后面的所有数据向左移动i个位置,最后把申请的空间中的数据放到后半部分.浪费空间,不推荐. 3.杂技

编程珠玑第二章

编程珠玑第二章 A题 给定一个最多包含40亿个随机排列的32位整数的顺序文件,找出一个不在文件中一32位整数. 1.在文件中至少存在这样一个数? 2.如果有足够的内存,如何处理? 3.如果内存不足,仅可以用文件来进行处理,如何处理? 答案: 1.32位整数,包括-2146473648~~2146473647,约42亿个整数,而文件中只有40亿个,必然有整数少了. 2.如果采用位数思想来存放,则32位整数最多需要占用43亿个位.约512MB的内存空间. 可以采用前一章的位处理方法.然后判断每个in

现代软件工程—构建之法》第一章 中出现的计算机专业术语

现代软件工程-构建之法>第一章 中出现的计算机专业术语 1.软件 2.程序 3.软件工程 4.二叉树 5.遍历算法 6.数据结构 7.算法 8.应用软件 9.软件服务 10.源程序 11.软件架构 12.软件设计与实现 13.依赖关系 14.编译参数 15.链接参数 16.构建 17.源代码管理 18.配置管理 19.质量保证 20.软件测试 21.需求分析 22.程序理解 23.软件维护 24.服务运营 25.软件的生命周期 26.软件项目的管理 27.用户体验 28.国际化和本地化 29.A