05下半年试题有错!?C语言高手进

much0726 2006-05-15 12:09:02
05年软件设计师下午试题的第四题,C语言程序填空题,出现了不易发现的错误,本题是计算散列文件存储的题目,按题目要求的子函数InsertToHashTable(int NewElemKey)的功能是:若新元素NewElemKey 正确插入散列文件中,则返回值 1 ;否则返回值 0 。
在网络上对题目的答案是:
(1) Index=NewElemKey%P,或Index=Hash(NewElemKey)
(2) i<ITEMS
(3) front=&Bucket[Index],或front=Bucket+Index
(4) k=ITEMS,或k>=ITEMS
(5) t=NULL
(6) front ->Link = s
(注:原题目另附文件)
其中(3)和(6)两个答案有点出入,错误发生在front指针指向的问题上。为了证实这个错误,我针对这个子函数编写了主程序。并把题目中的测试数据存储在同目录下的HASH.dat文件里。
按照测试数据:15 , 14 , 21 , 87 , 96 , 293 , 35 , 24 , 149 , 19 , 63 , 16 , 103 , 77 , 5 , 153 , 145 , 356 , 51 , 68 , 705 , 453
输出的结果应该是:
0.14 21 35 ->63 77 -1
1.15 -1 -1
2.149 16 51
3.87 24 -1
4.-1 -1 -1
5.96 19 103 ->5 145 68 ->705 453 -1
6.293 153 356
以下是编写的C主程序:(我给我加入的函数写了注释)
#include<stdio.h>
#include<alloc.h>
#define NULLKEY -1
#define P 7
#define ITEMS 3
typedef struct BucketNode{
int KeyData[ITEMS];
struct BucketNode *Link;
}BUCKET;
BUCKET Bucket[P];

void InitBucket()
{//按题目要求初始化了桶的数据,所有KeyData[]、Link域已分别初始化为NULLKEY、NULL
int i,j;
for(i=0;i<P;i++)
for(j=0;j<ITEMS;j++)
Bucket[i].KeyData[j]=NULLKEY;
}

int InsertToHashTable(int NewElemKey)
{
int Index;
int i,k;
BUCKET *s,*front,*t,*p;
Index=NewElemKey%P;
for(i=0;i<ITEMS;i++)
if(Bucket[Index].KeyData[i]==NULLKEY){
Bucket[Index].KeyData[i]=NewElemKey;break;
}
if(i<ITEMS)return 0;
//front=&Bucket[Index];
p=&Bucket[Index];
while(p->Link!=NULL)
p=p->Link;
front=p;
t=Bucket[Index].Link;
if(t!=NULL)
{
while(t!=NULL)
{
for(k=0;k<ITEMS;k++)
if(t->KeyData[k]==NULLKEY){
t->KeyData[k]=NewElemKey;break;
}
if(k==ITEMS)t=t->Link;
else break;
}//while
}//if
if(t==NULL)
{
s=(BUCKET*)malloc(sizeof(BUCKET));
if(!s) return -1;
s->Link=NULL;
for(k=0;k<ITEMS;k++)
s->KeyData[k]=NULLKEY;
s->KeyData[0]=NewElemKey;
front->Link=s;
}//if
return 0;
}

void print()
{//打印7个桶数据
int items;
int p;
BUCKET *q;
for(p=0;p<P;p++)
{
printf("\n%d.",p);
for(items=0;items<ITEMS;items++)
printf("%d\t",Bucket[p].KeyData[items]);
if(Bucket[p].Link!=NULL)
{
q=Bucket[p].Link;
while(q!=NULL)
{
printf("->");
for(items=0;items<ITEMS;items++)
printf("%d\t",q->KeyData[items]);
q=q->Link;
}//while
}//if
}
}
void main()
{//主程序
int a,dat[40]={0};//数组初始化为0,方便条件判断
int i=0,j=0;
FILE *fp;
fp=fopen("HASH.dat","r");
if(!fp)printf("FILE OPEN ERROR");else printf("FILE OPEN SUCCESS!");
while(!feof(fp)){fscanf(fp,"%d",&dat[i]);i++;}//把文件HASH.dat里的数据读入数组dat[]
InitBucket();//初始化桶
while(dat[j]!=0)
{//把非零数据全部调用InsertToHashTable()子函数
a=InsertToHashTable(dat[j]);
if(a==0)printf("Insert %d Success!",j);//显示数据操作结果
else printf("Error!");
j++;
}
print();//打印全局数组Bucket[P]
}
如果按答案上的写法,结果就是:
0.14 21 35 ->63 77 -1
1.15 -1 -1
2.149 16 51
3.87 24 -1
4.-1 -1 -1
5.96 19 103 ->705 453 -1
6.293 153 356
区别就是第五桶后面的溢出桶少了一个。原因就出在front的赋值上,(3)的答案是front=&Bucket[Index],或front=Bucket+Index。即取得基桶的地址,然后(6)的答案是(6)front->Link = s。即把新生成的溢出桶s接到front后面。但是,第五个基桶有两个溢出桶,在生成第二个溢出桶的时候,front的取地址还是基桶,所以,第一个溢出桶的连接就丢失了。依次推理,当溢出桶大于2时,只连接到最后一个溢出桶。应该把(3)的位置改为:
p=&Bucket[Index];
while(p->Link!=NULL)
p=p->Link;
front=p;
并申明一个BUCKET类型的指针p
这样front就指向最后一个溢出桶,如果没有溢出桶,就指向基桶的地址。即指向Link为NULL的地址。
(6)位置不变,就可以得出正确结果。
...全文
198 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
striker_un 2006-05-15
  • 打赏
  • 举报
回复
你的答案是哪搞的。很多盗版的。
much0726 2006-05-15
  • 打赏
  • 举报
回复
你说的那个网站的这题答案是
试题四.
1. Index=NewElemkey%P
2. i3. t=(BUCKET*)malloc(sizeof(BUCKET))
4. t->link!=NULL
5. k>=ITEMS
6. return 0
很荒谬啊,特别是6,。。。让我都不知道哪个才是标准的答案了。。管他的可以实现才是硬道理

much0726 2006-05-15
  • 打赏
  • 举报
回复
http://www.hbsoft.net/ws/shiti/2005/200502_rjsjs.htm
你说的原题是这里吧。我看了,题目没有错。我上面写的不是真题。除了InsertToHashTable(int NewElemKey)子函数,其他都是我自己加上去的,可以实现,你可以拷贝的本地看看,记得添加一个HASH.dat文件,里面写上关键字就可以了。
原题是
if(t!=NULL)
{
while(t!=NULL)
{
for(k=0;k<ITEMS;k++)
if(t->KeyData[k]==NULLKEY){
t->KeyData[k]=NewElemKey;break;
}
if(k==ITEMS) t=t->Link;
else break;
}//while
}//if
你是说你在t=t->Link;后面添加一个front=t;就可以了吗?我觉得应该是可以的。front是指向最后一个溢出桶的就可以。
striker_un 2006-05-15
  • 打赏
  • 举报
回复
也不用太操心 。
其实就是一道常规题。
都是先寻找插入位置,再插入。没有位置就新开一个位置,再链进去。

马上就要考了。一起加油。
striker_un 2006-05-15
  • 打赏
  • 举报
回复
明白你的意思。
但一个空写上几行是不现实的。
还有一件很怪的事。
你发的题目和我做的不一样。
我是在www.hbsoft.net 上做的原题。(我软考报名位置的网站。还搞什么培训的。我估计是它们用假题来坑我!)

我觉得这个位置还是一空只写一行
front ->link = s,
是不是在后面做循环时原题掉了一句
if(t!=NULL)
{
while(t!=NULL)
{
for(k=0;k<ITEMS;k++)
if(t->KeyData[k]==NULLKEY){
t->KeyData[k]=NewElemKey;break;
}
if(k==ITEMS) t=t->Link; /***____这里变为*/////{t=t->Link; front=t;/******/
else break;
}//while
}//if

2,948

社区成员

发帖
与我相关
我的任务
社区描述
就计算机等级考试、软件初、中、高级不同级别资格考试相关话题交流经验,共享资源。
c1认证c4javac4前端 技术论坛(原bbs)
社区管理员
  • 软件水平考试社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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