编程珠玑第一章 习题2,习题9

本文介绍了一种在访问稀疏数组时才进行初始化的方法,通过使用辅助向量from和to及变量top,确保只有未初始化的数据会被设置为0,以此减少不必要的初始化操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// 编程珠玑第一章习题2.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

#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));//a[i>>SHIFT] 找到a中的位置
}
void clr(int i)
{
	a[i>>SHIFT]&=~(1<<(i&MASK));//1<<(i&MASK) 取得低五位,做移动1移动1<<(i&MASK)位
}
bool test(int i)
{
	return a[i>>SHIFT]&(1<<(i&MASK));
}
int _tmain(int argc, _TCHAR* argv[])
{
	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);
	system("pause");
	return 0;
}

习题9

首先,我们需要明确问题是什么。

       在这里,我们有一个稀疏的数组需要访问,并且在第一次访问的时候将其初始化为0. 因为数组很大,并且需要访问的数组元素很稀疏,而程序要求的时间很宝贵。

       所以,我们不能直接将data数组的各个元素都初始化为0.

       我们需要做的是在第一次数组data中的某个元素的时候,将其初始化为0. 如果之后再次访问到该元素,应该能够判断其是否已经被初始化过,避免多次初始化从而覆盖数据。

       在提供的解决方案中,就使用了from,to两个向量和top变量来保存哪些变量已经被初始化了。

       当我们访问索引为i的data元素时,我们通过判断form[i]是否小于top,并且to[from[i]]是否等于i来判断元素树否被初始化过。

       需要注意的是我们使用to向量的原因是为了防止from中的未经初始化的数据刚好因为小于top而导致出现错误判断。也就是说,我们是不对from和to向量进行初始化的(因为我们连对data进行初始化的成本都不肯),所以无法判断from中的数据哪些是我们写入的,哪些是原来就有的。于是,我们就通过增加一个to数组,并且增加一个判断条件来保证我们的判断是正确的。

       当然,这样的保证也并不是绝对正确的。只是小概率事件,直接忽略了吧???

综上:

       我们在访问data中索引为i的元素时,通过条件from[i]<top和to[from[i]]=i来判断该数据是否被初始化过。

       如果已被初始化过,就直接访问该数据;

       否则,使用如下的语句对其进行初始化,并且在from,to和top中保存该数据已被初始化过这个信息:

       from[i]=top;

       to[top]=i

      data[i] = 0

      top++.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值