scanf(“%f”,&a[i]);/*执行次数:
n次*/
p=a[0];
for(i=1;i<=n;i++)
{p=p+a[i]*x;/*执行次数:
n次*/
x=x*x;}
printf(“%f”,p);
}
算法的时间复杂度:
T(n)=O(n)
通过参数表中的参数显式传递
floatPolyValue(floata[],floatx,intn)
{
floatp,s;
inti;
p=x;
s=a[0];
for(i=1;i<=n;i++)
{s=s+a[i]*p;/*执行次数:
n次*/
p=p*x;}
return(p);
}
算法的时间复杂度:
T(n)=O(n)
第二章
1.填空:
(1)在顺序表中插入或删除一个元素,需要平均移动一半元素,具体移动的元素个数与插入或删除的位置有关。
(2)线性表有顺序和链式两种存储结构。
在顺序表中,线性表的长度在数组定义时就已经确定,是静态保存,在链式表中,整个链表由“头指针”来表示,单链表的长度是动态保存。
(3)在顺序表中,逻辑上相邻的元素,其物理位置_一定_____相邻。
在单链表中,逻辑上相邻的元素,其物理位置不一定相邻。
(4)在带头结点的非空单链表中,头结点的存储位置由头指针指示,首元素结点的存储位置由头结点指示,除首元素结点外,其它任一元素结点的存储位置由其直接前趋的next域指示。
2.选择题
(1)A
(2)已知L是无表头结点的单链表,且P结点既不是首元素结点,也不是尾元素结点。
按要求从下列语句中选择合适的语句序列。
a.在P结点后插入S结点的语句序列是:
D、A。
b.在P结点前插入S结点的语句序列是:
G、K、H、D、A。
c.在表首插入S结点的语句序列是:
E、L。
d.在表尾插入S结点的语句序列是:
(K)、I、A、F。
供选择的语句有:
AP->next=S;
BP->next=P->next->next;
CP->next=S->next;
DS->next=P->next;
ES->next=L;
FS->next=NULL;
GQ=P;
Hwhile(P->next!
=Q)P=P->next;
Iwhile(P->next!
=NULL)P=P->next;
JP=Q;
KP=L;
LL=S;
ML=P;
(3)D
(4)D
(5)D
4.已知顺序表L递增有序,编写一个算法,将X插入到线性表的适当位置上,以保持线性表的有序性。
voidinserX(Seqlist*L,Elemtypex){
inti;
i=L->length-1;
while(i>=0&&xelem[i]){
L->elem[i+1]=L->elem[i];
i--;
}
L->length++;
}
7试分别以不同的存储结构实现线性表的就地逆值的算法,即在原表的存储空间中将线性表 (a1,a2,…,an)逆置为(an,an-1,…,a1)。
(1)以顺序表作存储结构,设线性表存于a[1:
arrsize]的前elenum个分量中。
void reverseqlist(Seqlist *L){
int i;
int temp;
for(i=0;ilength/2;i++) {
temp=L->elem[i];
L->elem[i]=L->elem[L->length-i-1];
L->elem[L->length-i-1]=temp;
}
}
(2)以单链表作存储结构。
void reverselinklist(linklist *head) {
Linklist *p,*q;
p=head->next; head->next=NULL;
while(p->next!
=NULL) {
q=p->next;
p->next=head->next;
head->next=p;
p=q;
}
}
11将线性表A=(a1,a2,……am),B=(b1,b2,……bn)合并成线性表C,
C=(a1,b1,……am,bm,bm+1,…….bn) m<=n,
或
C=(a1,b1,……an,bn,an+1,……am)m>n,
线性表A、B、C以单链表作为存储结构,且C表利用A表和B表中的结点空间构成。
注意:
单链表的长度值m和n均未显式存储。
【解答】算法如下:
LinkListmerge(LinkListA,LinkListB,LinkListC)
{
Node*pa,*qa,*pb,*qb,*p;
pa=A->next;/*pa表示A的当前结点*/
pb=B->next;
p=A;/*利用p来指向新连接的表的表尾,初始值指向表A的头结点*/
while(pa!
=NULL&&pb!
=NULL)/*利用尾插法建立连接之后的链表*/
{
qa=pa->next;
qb=qb->next;
p->next=pa;/*交替选择表A和表B中的结点连接到新链表中;*/
p=pa;
p->next=pb;
p=pb;
pa=qa;
pb=qb;
}
if(pa!
=NULL)p->next=pa;/*A的长度大于B的长度*/
if(pb!
=NULL)p->next=pb;/*B的长度大于A的长度*/
C=A;
Return(C);
}
第三章
1B
2C
3C
8假设表达式由单字母变量和双目四则运算构成。
试写一个算法,将一个通常书写形式且书写正确的表达式转为逆波兰式。
【分析】算法的思想:
所有的变量在逆波兰式中出现的先后顺序和在原表达式中出现的相同,因此只需要设立一个"栈",根据操作符的"优先级"调整它们在逆波兰式中出现的顺序。
#include
#include
#defineSTACK_INIT_SIZE100
#defineSTACK_INCREAMENT10
typedefstruct{//栈
char*base;
char*top;
intstackSize;
}Stack;
voidinitStack(Stack&stack){//初始化栈
stack.base=stack.top=(char*)malloc(sizeof(char)*STACK_INIT_SIZE);
stack.stackSize=STACK_INIT_SIZE;
}
voidpush(Stack&S,charp){//入栈
if(S.top-S.base>=S.stackSize){
S.base=(char*)realloc(S.base,(S.stackSize+STACK_INCREAMENT)*sizeof(char));
S.top=S.stackSize+S.base;
S.stackSize+=STACK_INCREAMENT;
}
*S.top++=p;
}
voidpop(Stack&stack,char&p){//出栈
if(stack.base==stack.top){
p=NULL;return;
}
p=*--stack.top;
}
chargetTop(Stackstack){//获得栈顶元素
if(stack.base==stack.top)returnNULL;
return*(stack.top-1);
}
boolisAlpha(charp){//判断是不是字母
return(p>='a'&&p<='z')||(p>='A'&&p<='Z')?
true:
false;
}
intprecede(chara,charb){
switch(a){
case'/':
case'*':
return1;break;
case'+':
case'-':
switch(b){
case'/':
case'*':
return-1;break;
default:
return1;
}
break;
default:
switch(b){
case'#':
return0;break;
default:
return-1;
}
}
}
voidNiBoLan(char*str,char*newStr){//转换成逆波兰式
Stackstack;
initStack(stack);
char*p,*q,c;
p=str;q=newStr;
push(stack,'#');
while(*p){
if(isAlpha(*p))*q++=*p;
else{
c=getTop(stack);
if(precede(*p,c)>0)push(stack,*p);
else{
while(precede(getTop(stack),*p)>=0&&*p){
pop(stack,c);*q++=c;
}
push(stack,*p);
}
}
p++;
}
}
voidmain(){
charstr[100];
charnewStr[100];
inti;
for(i=0;i<100;i++)str[i]=newStr[i]='\0';
printf("请输入表达式:
\n");scanf("%s",str);
NiBoLan(str,newStr);
printf("其对应的逆波兰式为:
%s\n",newStr);
}
10要求循环队列不损失一个空间全部都能得到利用,设置一个标志tag,以tag为0或1来区分头尾指针相同时的队列状态的空与满,请编写与此相应的入队与出队算法。
入队算法:
intEnterQueue(SeqQueue*Q,QueueElementTypex)
{
/*将元素x入队*/
if(Q->front==Q->front&&tag==1)/*队满*/
return(FALSE);
if(Q->front==Q->front&&tag==0)/*x入队前队空,x入队后重新设置标志*/
tag=1;
Q->elememt[Q->rear]=x;
Q->rear=(Q->rear+1)%MAXSIZE;/*设置队尾指针*/
Return(TRUE);
}
出队算法:
intDeleteQueue(SeqQueue*Q,QueueElementType*x)
{
/*删除队头元素,用x返回其值*/
if(Q->front==Q->rear&&tag==0)/*队空*/
return(FALSE);
*x=Q->element[Q->front];
Q->front=(Q->front+1)%MAXSIZE;/*重新设置队头指针*/
if(Q->front==Q->rear)
tag=0;/*队头元素出队后队列为空,重新设置标志域*/
Return(TUUE);
}
15
(1)功能:
将栈中元素倒置。
(2)功能:
删除栈中的e元素。
(3)功能:
将队列中的元素倒置。
第四章
1.设s=’IAMASTUDENT’,t=’GOOD’,q=’WORKER’。
给出下列操作的结果:
【解答】StrLength(s)=14;
SubString(sub1,s,1,7)sub1=’IAMA’;
SubString(sub2,s,7,1)sub2=’’;
StrIndex(s,4,’A’)=6;
StrReplace(s,’STUDENT’,q);s=’IAMAWORKER’;
StrCat(StrCat(sub1,t),StrCat(sub2,q))sub1=’IAMAGOODWORKER’。
4.叙述以下每对术语的区别:
空串和空格串;串常量与串变量;主串和子串;串变量的名字和串变量的值。
【解答】不含任何字符的串称为空串,其长度为0。
仅含有空格字符的串称为空格串,其长度为串中空格字符的个数。
空格符可用来分割一般的字符,便于人们识别和阅读,但计算串长时应包括这些空格符。
空串在串处理中可作为任意串的子串。
用引号(数据结构教学中通常用单引号,而C语言中用双引号)括起来的字符序列称为串常量,串值可以变化的量称为串变量。
串中任意个连续的字符组成的子序列被称为该串的子串。
包含子串的串又被称为该子串的主串。
子串在主串中第一次出现的第一个字符的位置称子串在主串中的位置。
串变量的与其它变量一样,要用名字引用其值,串变量的名字也是标识符,串变量的值可以修改。
5.已知:
s="(xyz)+*",t="(x+z)*y"。
试利用联结、求子串和置换等基本运算,将s转化为t。
【答案】本题有多种解法,下面是其中的一种:
(1)s1=substr(s,3,1)/*取出子串:
"y"
(2)s2=substr(s,6,1)/*取出子串:
"+"
(3)s3=substr(s,1,5)/*取出子串:
"(xyz)"
(4)s4=substr(s,7,1)/*取出子串:
"*"
(5)s5=replace(s3,3,1,s2)/*形成部分串:
"(x+z)"
(6)s=s5/*s4/*s1/*形成串t即"(x+z)*y"
【解析】题中所给操作的含义如下:
/*:
连接函数,将两个串连接成一个串
substr(s,i,j):
取子串函数,从串s的第i个字符开始,取连续j个字符形成子串
replace(s1,i,j,s2):
置换函数,用s2串替换s1串中从第i个字符开始的连续j个字符
8编写下列算法:
(1)将顺序串r中所有值为ch1的字符换成ch2的字符。
(2)将顺序串r中所有字符按照相反的次序仍存放在r中。
(3)从顺序串r中删除其值等于ch的所有字符。
(4)从顺序串r1中第index个字符起求出首次与串r2相同的子串的起始位置。
(5)从顺序串r中删除所有与串r1相同的子串。
【解答】
(1)
Voidreplace(Str*r,charch1,charch2)//将串r中所有值为ch1的字符换成ch2的字符
{
for(inti=0;ilen;i++)
if(r->vec[i]==ch1)r->vec[i]=ch2;
return;
}
(2)
Voidconverse(str*r)//将串r中所有字符按照相反的次序存放在r中
{
for(inti=0;i<(r->len/2);i++){
Charch=r->vec[i];
r->vec[i]=r->vec[r->len-1-i];
r->vec[r->len-1-i]=ch;
}
Return;
}
(3)
Voiddelete(str*r,charch)//从串r中删除其值等于ch的所有字符
{
inti=0;intlen=r.len;
While(iif(r->vec[i]==ch}{
for(j=i;jr->vec[j]=r-vec[j+1];
len--;
}
else
i++;
}
return;
}
(4)
intposition(strr1,intindex,charr2)
//从串r1中第index个字符起求出首次与字符r2相同的子串的起始位置
{
if(index<1||index>r.len)returnERROR;
inti=index;
while(r,vec[i]!
=r2&&iif(i=r.len){cout<<”不存在”;return;}
returni+1;
}
(5)
intDelSub(SString*r,SStringr1){
inti,j,t;
if(r->lenfor(i=0;ilen-r1.len;){
j=i;
for(t=0;tif(r->ch[j++]!
=r1.ch[t])break;
if(t==r1.len){
for(j=i;j+r1.lenlen;j++)
r->ch[j]=r->ch[j+r1.len];
r->len-=r1.len;
}
if(t!
=r1.len)i++;
}
return
(1);
}
第五章
1.假设有6行8列的二维数组A,每个元素占用6个字节,存储器按字节编址。
已知A的基地址为1000,计算:
(1)数组A共占用多少字节;(288)
(2)数组A的最后一个元素的地址;(1282)
(3)按行存储时,元素A36的地址;(1126)
(4)按列存储时,元素A36的地址;(1192)
3.设有一个上三角矩阵A,将其上三角中的元素逐列压缩存储到一个n(n+1)/2的一维数组C(下标从1开始),请给出计算上三角矩阵中任意元素aij(iK=[n+n-(i-2)]*(i-1)/2+[j-(i-1)]=(2n-i+2)*(i-1)/2+(j-i+1)i<=j
4.设有三对角矩阵An×n,将其三条对角线上的元素逐行的存于数组B[1..3n-2]中,使得B[k]=aij,求:
(1)用i,j表示k的下标变换公式;
(2)用k表示i、j的下标变换公式。
【解答】
(1)k=2(i-1)+j
(2)i=[k/3]+1,j=[k/3]+k%3([]取整,%取余)
7.编写一个在十字链表按三元组表的形式打印输出。
解:
矩阵相加就是将两个矩阵中同一位置的元素值相加。
由于两个稀疏矩阵的非零元素按三元组表形式存放,在建立新的三元组表C时,为了使三元组元素仍按行优先排列,所以每次插入的三元组不一定是A的,按照矩阵元素的行列去找A中的三元组,若有,则加入C,同时,这个元素如果在B中也有,则加上B的这个元素值,否则这个值就不变;如果A中没有,则找B,有则插入C,无则查找下一个矩阵元素。
#defineMaxSize10//用户自定义
typedefintDataType;//用户自定义
typedefstruct
{//定义三元组
inti,j;
DataTypev;
}TriTupleNode;
typedefstruct
{//定义三元组表
TriTupleNodedata[MaxSize];
intm,n,t;//矩阵行,列及三元组表长度
}TriTupleTable;
//以下为矩阵加算法
voidAddTriTuple(TriTupleTable*A,TriTupleTable*B,TriTupleTable*C)
{//三元组表表示的稀疏矩阵A,B相加
intk,l;
DataTypetemp;
C->m=A->m;//矩阵行数
C->n=A->n;//矩阵列数
C->t=0;//三元组表长度
k=0;l=0;
while(kt&<)
{if((A->data[k].i==B->data[l].i)&&(A->data[k].j==B->data[l].j))
{temp=A->data[k].v+B->data[l].v;
if(!
temp)//相加不为零,加入C
{C->data[c->t].i=A->data[k].i;
C->data[c->t].j=A->data[k].j;
C->data[c->t++].v=temp;
}
k++;l++;
}
if((A->data[k].i==B->data[l].i)&&(A->data[k].jdata[l].j))
||(