p=p->link;
j++;
}
if(p->link==NULL)returnFALSE;/*第i个结点不存在*/
for(j=0;jlink!
=NULL;j++){
q=p->link;
p->link=q->link;
free(q);
}
returnTRUE;
}
代价分析
该算法访问单链表中前面i+k个结点,时间代价为O(i+k),最大不超过O(n)。
13.请设计一个算法,求出循环表中结点的个数。
【答】
数据结构
采用不带头结点的循环链表。
structNode;
typedefstructNode*PNode;
structNode{
DataTypeinfo;
PNodelink;
};
typedefstructNode*LinkList;
思路
遍历整个循环链表,同时计数即可。
错误算法
intcount(LinkListclist){
intcount;
PNodep,q;
p=clist;
q=p->link;
if(clist==NULL)return0;/*如果是空表*/
count=1;
while(q!
=p){
q=q->link;
count++;
}
returncount;
}
错误:
如果clist是一个空表,那么第5行的语句“q=p->link;”是非法的。
分析:
应把第6行语句(用下划线表示)提前1行或2行。
一定要放在语句“q=p->link;”之前。
缺点:
增加局部变量p。
分析:
这样做没有必要,因为p的初值置为clist,在程序中并没有对p做其他修改,所以程序中不需要引入p而直接使用clist即可。
算法
intcount(LinkListclist){
intcount;
PNodeq;
if(clist==NULL)return0;/*如果是空表*/
q=clist->link;
count=1;
while(q!
=clist){
q=q->link;
count++;
}
returncount;
}
代价分析
该算法访问循环链表中每个结点各一次,时间代价为O(n)。
4.栈与队列
1.写一个递归算法来把整数字符串转换为整数。
(例:
“43567”→43567。
)
【答】
思路
先递归调用本算法转换除去末位外剩余的字符串,结果乘以10。
再转换末位。
将两结果相加即为所求。
算法
intstringToInt1(char*s,intstart,intend){
/*把整数字符串s中从start到end的部分转换为整数*/
if(start>end)return-1;/*转换失败*/
if(start==end)returns[end]-'0';/*只有一个字符,直接转换*/
returnstringToInt1(s,start,end-1)*10+s[end]-'0';/*先转换其他位,再转换末位*/
}
intstringToInt(char*s){/*把整数字符串s转换为整数*/
inti=0;
while(s[i]!
='\0')i++;/*计算字符串的长度*/
returnstringToInt1(s,0,i-1);
}
代价分析
设n为字符串的长度。
该算法访问每个字符各一次,时间代价为O(n),计算字符串的长度的时间代价也为O(n)。
故总的时间代价为O(n)。
递归算法需要栈的支持,栈的大小与递归调用的深度成正比。
所以实际空间开销为O(n)。
2.编写一个算法,对于输入的十进制非负整数,将它的二进制表示打印出来。
【答】
数据结构
采用4.1.2节中栈的顺序表示。
思路
将输入的十进制数字反复除以2,直到它变为0。
将每次的数字模2的余数入栈。
栈中存放的就是所要求的二进制表示。
再将栈中的元素依次弹出打印即可。
算法
voidprint_bin(intdec_number){/*将十进制非负整数转化为二进制数打印出来*/
PSeqStackpastack;
inttemp=dec_number;
if(temp<0){
printf("Error!
\n");
return;
}
pastack=createEmptyStack_seq();/*建立一个空栈*/
if(pastack==NULL)return;
while(temp>0){
push_seq(pastack,temp%2);
temp/=2;
}
while(!
isEmptyStack_seq(pastack)){
printf("%d",top_seq(pastack));
pop_seq(pastack);
}
free(pastack);
}
代价分析
设输入的十进制数字为n,则算法的时间代价为O(
)。
空间代价主要是栈的大小,为O(
)。
3.写一个算法:
PSeqStackcreateEmptyStack_seq(intm)创建一个空栈。
数据结构
采用4.1.2节中栈的顺序表示。
PSegStackcreateEmptyStack_seq(intm){
/*创建一个空栈*/
PSeqStackpastack=(PSeqStack)malloc(sizeof(structSeqStack));
if(pastack!
=NULL){
pastack->s=(DataType*)malloc(sizeof(DataType)*m);
if(pastack->s){
pastack->MAXNUM=m;
pastack->t=-1;/*栈顶变量赋值为-1*/
return(pastack);
}
elsefreepastack;
}
printf(“Outofspace!
!
\n”);/*存储分配失败*/
returnNULL;
}
4,写一个算法:
intisEmptyStack_seq(PSeqStackpastack)判断pastack所指的栈是否为空栈。
数据结构
采用4.1.2节中栈的顺序表示。
intisEmptyStack_seq(PSeqStackpastack){
/*判断pastack所指的栈是否为空栈*/
if(pastack->t==-1)return1;
elsereturn0;
}
8.假设以循环链表表示队列,并且只设一个指针指向队尾元素结点(注意不设队头指针),试编写相应的创建空队列、入队列和出队列的算法。
【答】
数据结构
采用不带头结点的循环链表表示队列。
structNode;
typedefstructNode*PNode;
structNode{
DataTypeinfo;
PNodelink;
};
structClinkQueue{/*循环链表表示的队列类型*/
PNoder;/*尾指针*/
}
typedefstructClinkQueue*PClinkQueue;/*指向循环链表表示的队列的指针类型*/
思路
与队列的单链表表示相似,但节省了指向队头的指针变量,所以在需要找表头结点时必须通过表尾指针进行。
算法
PClinkQueuecreateEmptyQueue_clink(){/*创建空队列*/
PClinkQueuepcqu=(PClinkQueue)malloc(sizeof(structClinkQueue));
pcqu->r=NULL;
returnpcqu;
}
voidenQueue_clink(PClinkQueuepcqu,DataTypex){/*进队列*/
PNodep;
p=(PNode)malloc(sizeof(structNode));
p->info=x;
if(pcqu->r==NULL){
pcqu->r=p;
p->link=p;
return;
}/*进空队列,即往空队列中加入第一个结点*/
p->link=pcqu->r->link;
pcqu->r->link=p;
pcqu->r=p;
}
voiddeQueue_clink(PClinkQueuepcqu){/*出队列*/
PNodep;
if(pcqu->r==NULL){/*是空队列*/
printf("Underflow!
\n");
return;
}
if(pcqu->r->link==pcqu->r){/*只有一个元素的队列*/
free(pcqu->r);
pcqu->r=NULL;
return;
}
p=pcqu->r->link;/*指向队头