南京师范大学数据结构考研真题.docx
《南京师范大学数据结构考研真题.docx》由会员分享,可在线阅读,更多相关《南京师范大学数据结构考研真题.docx(16页珍藏版)》请在冰豆网上搜索。
南京师范大学数据结构考研真题
(1)设计一个程序,找出1-200之间的所有水仙花数。
所谓水仙花数是指各个数字的立方和恰好等于该数本身。
例如:
153=1*1*1+5*5*5+3*3*3。
(本题15分)
#include
voidmain()
{
inti,j,k,n;
for(n=1;n<=200;n++)
{
i=n/100;
j=(n-i*100)/10;
k=n%100%10;
if(i*i*i+j*j*j+k*k*k==n)
printf("%3disanarcissusnumber.\n",n);
}
}
#include
voidmain()
{
inti,j,s,n;
for(n=1;n<=200;n++)
{
j=n;
i=0;
s=0;
while(j!
=0)
{
i=j%10;
s+=i*i*i;
j=j/10;
}
if(s==n)
printf("%3disanarcissusnumber.\n",n);
}
}
(2)设计一个程序,实现输入一个给定的正整数N,打印出所有不超过N的,其平方为回文(回文是指字符串两半的字符左右对称,例如1,22,121,4224等均是回文)的数(本题15分)
#includevoidtest(intn)
{
inti=0,j=-1,k;
inta[10];
k=n*n;
while(k!
=0)
{
a[++j]=k%10;
k=k/10;
}
while(i{
if(a[i]==a[j])
{
i++;
j--;
}
else
break;
}
if(i>=j)
printf("%d'ssquare%disapalindromenumber!
\n",n,n*n);
}
voidmain()
{
inti,n;
printf("pleaseinputanumber:
");
scanf("%d",&n);
for(i=1;itest(i);
}
(3)编写程序用于统计字符串中最长单词的长度和在字符串中的位置,其中单词由字母组成。
(本题20分)
#include
Voidmain()
{
inti,count=0,pos=0,maxlen=0;
charch;
chars[80]="whatareyoudoing";
//printf("inputastring:
");
//gets(s);
i=-1;
do{
i++;
ch=s[i];
if((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'))
{
count++;
}
else{
if(count>maxlen)
{
maxlen=count;
pos=i-maxlen;
}
count=0;
}
}while(s[i]!
='\0');
printf("Themaxlengthwordis\"");
for(i=0;i{
printf("%c",s[pos+i]);
}
printf("\"andit'spositionis%d.\n",pos+1);
}
(4)编写算法输出从n个自然数中取k个(k<=n)所有组合。
例如,当n=5,k=3时,你的算法应该输出:
543,542,541,532,531,521,432,431,421,321.(本题20分)
#include
Voidf(intn,intk,inta[],intm)
{
inti;
if(k==0)
{
for(i=0;iprintf("%d",a[i]);
printf("");
}
else{
for(i=n;i>=k;i--)
{
a[m]=i;
f(i-1,k-1,a,m+1);
}
}
}
voidmain()
{
intn,k,m=0;
inta[10];
printf("Pleaseenternandk:
");
scanf("%d%d",&n,&k);
f(n,k,a,m);
printf("\n");
}
(5)试采用递归函数实现将任意位数的整数转换成字符串输出,要求在主函数中输入整数并调用递归函数实现转换并输出结果,对于负数也能处理。
(本题20分)
#includevoidnumtostring(intn,chara[],intk)
{
if(k==0)return;
else{
a[--k]=n%10+48;
n/=10;
numtostring(n,a,k);
}
}
voidmain()
{
intn,m,k=0;
chara[100],sign='';
printf("Pleaseinputthenumber:
");
scanf("%d",&n);
if(n<0){sign='-';n=-n;}
m=n;
while(m)
{
k++;
m/=10;
}
a[k]='\0';
numtostring(n,a,k);
printf("Thenumberis:
%c%s\n",sign,a);
}
(6)假设有两个按元素值递增有序排列的线性表A和B,均以单链表作存储结构,请编写算法将A和表B归并成一个按元素非递减有序(允许值相同)排列的线性表C,并要求利用原表(即表A和表B)的结点空间存储放表。
(本题20分)
typedefstructNode
{
ElemTypedata;
structNode*next;
}LNode;
LNode*merge(LNode*A,LNode*B)
{
LNode*C;
LNode*pa,*pb,*pc;
pa=A->next;pb=B->next;
C=A;pc=C;pc->next=NULL;
while(pa&&pb)
{
if(pa->data<=pb->data)
{
pc->next=pa;
pa=pa->next;
pc=pc->next;
pc->next=NULL;
}
else{
pc->next=pb;
pb=pb->next;
pc=pc->next;
pc->next=NULL;
}
}
if(pa)pc->next=pa;
if(pb)pc->next=pb;
returnC;
}
(7)如果一棵Huffman树T有n个叶子结点,那么树T有多少个结点,要求给出详细的算法,然后再写出程序。
(本题20分)
参考解答:
解题思路:
假设有10个节点分别为9,7,5,3,1,8,6,4,2,0
将这些节点按从小到大的顺序存入链表中即0,1,2,3,4,5,6,7,8,9
取出前两个最小的节点,组成一个新的节点再放入到链表中,如下:
1,1,2,3,4,5,6,7,8,9
01
再对剩余的节点进行类似操作,直到剩余一个节点。
形成Huffman树后,然后统计节点的个数。
<1>voidInsertNode(LinkListh,LNode*s)是将*s指向的节点插入到以h为头节点的链表中适当位置,保证从小到大的排列顺序。
<2>voidFormLinkList(LinkList&h,inta[],intn)将数组a[n]中的n个元素放入到以h为头节点的链表中,保证链表从小到大
有序排列;将调用InsertNode(LinkListh,LNode*s)函数。
<3>BiTreeFormHuffman(LinkListh)是根据觛思路将带头节点的链表h逐步构建Huffman树,并将Huffman树返回。
<4>intcount(BiTreeroot)是对Huffman树root的节点进行计数。
<5>voidInOrder(BiTreeroot)和voidprintLinkList(LinkListh)是辅助函数,分别对树进行中序遍历和对链表进行打印。
#include
#include
#defineN10typedefstructBiNode
{
intdata;
structBiNode*lchild,*rchild;
structBiNode*next;
}LNode,*LinkList,BiNode,*BiTree;
voidInsertNode(LinkListh,LNode*s)
{
LNode*p,*q;
p=h;
q=p->next;
while(q&&q->data<=s->data)
{
p=q;
q=p->next;
}
p->next=s;
s->next=q;
(h->data)++;
}
voidFormLinkList(LinkList&h,inta[],intn)
{
inti;
LNode*s;
if(!
(h=(LNode*)malloc(sizeof(LNode))))exit(0);
h->data=0;
h->next=NULL;
h->lchild=NULL;
h->rchild=NULL;
for(i=0;i{
if(!
(s=(LNode*)malloc(sizeof(LNode))))exit(0);
s->data=a[i];
s->next=NULL;
s->lchild=NULL;
s->rchild=NULL;
InsertNode(h,s);
}
}
BiTreeFormHuffman(LinkListh)
{
LNode*p,*q;
BiNode*b;
if(h==NULL||h->data==0)returnNULL;
else{
while(h->data>1)
{
p=h->next;
q=p->next;
h->next=q->next;
(h->data)=h->data-2;
if(!
(b=(BiNode*)malloc(sizeof(BiNode))))exit(0);
b->data=p->data+q->data;
b->next=NULL;
b->lchild=p;
b->rchild=q;
InsertNode(h,b);
}
return(h->next);
}
}
intcount(BiTreeroot)
{
if(root==NULL)return0;
elseif(root->lchild==NULL&&root->rchild==NULL)return1;
else
return(
count(root->lchild)+
count(root->rchild)+1);
}
voidInOrder(BiTreeroot)
{
if(root)
{
InOrder(root->lchild);
printf("%d",root->data);
InOrder(root->rchild);
}
}
voidprintLinkList(LinkListh)
{
h=h->next;
while(h)
{
printf("%d",h->data);
h=h->next;
}
printf("\n");
}
voidmain()
{
inti;
inta[N]={9,7,5,3,1,8,6,4,2,0};
LinkListh;
BiTreeroot;
FormLinkList(h,a,N);
printLinkList(h);
root=FormHuffman(h);
InOrder(root);
i=count(root);
printf("\nTotalNumberofBiNodesis%d.\n",i);
}
(8)对于二叉树T的两个结点N1和N2,我们应该选择树T结点的前序、中序和后序中哪两个序列来判定结点N1必定是结点N2的祖先,并给出判断的方法。
要求给出详细的算法,然后再写出程序。
(本题20分)
参考答案:
有前中后三种序列,我们该选择哪一种呢?
我们先来做一个假设:
N1是N2的祖先。
此时N2有两种情况,一是N2在N1的左子树中,二是N2在N1的右子树中。
情况N2在N1的左子树N2在N1的右子树结果
前序N1...N2N1...N2相同
中序N2...N1N1...N2不同
后序N2...N1N2...N1相同
在前序序列中N1稳定排列于N2的前面,则N1有可能是N2的祖先,但并不代表N1一定是N2的祖先。
在后序序列中N1稳定排列于N2的后面,则N1有可能是N2的祖先,但并不代表N1一定是N2的祖先。
在中序序列中N1可能在N2的前面,也可能在N2的后面,这一点对我们判断N1是否可能是N2的祖先没有多大帮助。
由于中序序列存在这种不稳定性,我们只好采取前序和后序。
假如说有一种情况如下:
前序:
...N1...N2...
后序:
...N2...N1...
这两个序列,能判定N1是N2的祖先吗?
思考两个问题:
<1>N1是N2的祖先,则N1和N2的相对位置关系是上面的两个序列表现的这种前后关系吗?
<2>两个数列中N1和N2有这种前后关系,那N1一定是N2的祖先吗?
第1个问题,N1是N2的祖先,则N1和N2满足上述两个序列的前后关系。
第2个问题,不容易回答,因为当N1不是N2的祖先时,是否也能满足这种前后关系呢?
N1不是N2的祖先,分为两种情况:
一是N2是N1的祖先;二是N2是N1的兄弟树的结点,而第二种
情况又要分两种:
①N1是在左,N2在右;②N1在右,N2在左。
情况N1是N2的祖先N2是N1的祖先N1在左,N2在右N2在左,N1在右
前序N1...N2N2...N1N1...N2N2...N1
后序N2...N1N1...N2N1...N2N2...N1
后三组结果与第一组结果都不能完全相同,也就是说除了N1是N2祖先的情况,没有其它任何
情况可以产生上面的二个序列了,也就回答了第二个问题。
通过以上这些情况,可以看出前序和后序可以确定N1是否为N2的祖先。
#include
Intjudge(charpre[],charpost[],charch1,charch2)
{//pre[]代表前序序列,post[]代表后序序列,函数用检验ch1是否为ch2的祖先
Inti,k1=0,k2=0,flag=0;//k1、k2分别用来记录字符ch2在前序和后序中位置
while(pre[k1]!
=ch2)k1++;//flag用来标识进行判断ch1是否是ch2的祖先
while(post[k2]!
=ch2)k2++;
for(i=0;i{
if(pre[i]==ch1)
{
flag=1;//如果ch1在ch2的前面找到,则先假设ch1是ch2的祖先
break;
}
}
if(!
flag)returnflag;//如果ch1不在ch2前面,则返回
else{
flag=0;//将flag重新赋值为0
for(i=k2+1;post[i]!
='\0';i++)//进一步进行判断
if(post[i]==ch1)
{
flag=1;
break;
}
Returnflag;
}
}
voidmain()
{
inti=0;
charch1,ch2,pre[100]={"abdecfg"},post[100]={"debfgca"};
printf("请输入前序序列:
");
//gets(pre);
puts(pre);
printf("请输入后序序列:
");
//gets(post);
puts(post);
printf("请输入要查询的字符N1和N2(形式:
N1,N2):
");
scanf("%c,%c",&ch1,&ch2);
i=judge(pre,post,ch1,ch2);
if(i)
printf("%c是%c的祖先\n",ch1,ch2);
elseprintf("%c不是%c的祖先\n",ch1,ch2);
}