while(p->next->data<=mink) p=p->next; //p 是最后一个不大于mink 的元素 if(p->next) //如果还有比mink 更大的元素 {
q=p->next;
while(q->data
}//Delete_Between
2.7 试分别以不同的存储结构实现线性表的就地逆置算法,即在原表的存储空间将线性表(a, a ..., a )逆置为(a, a ,..., a )。
(1) 以一维数组作存储结构,设线性表存于 a(1:arrsize)的前 elenum 个分量中。 (2)以单链表作存储结构。
void reverse(SqList &A)//顺序表的就地逆置 {
for(i=1,j=A.length;i
2.8 假设两个按元素值递增有序排列的线性表A和B,均以单链表作为存储结构,请编写算法,将A表和B表归并成一个按元素值递减有序排列的线性表C,并要求利用原表(即A表和B表的)结点空间存放表C。 while(pa||pb) {
if(pa->data
pc=pa;q=pa->next;pa->next=pre;pa=q; //将A 的元素插入新表 } else {
pc=pb;q=pb->next;pb->next=pre;pb=q; //将B 的元素插入新表 }
pre=pc; }
C=A;A->next=pc; //构造新表头 }//reverse_merge
分析:本算法的思想是,按从小到大的顺序依次把A 和B 的元素插入新表的头部pc 处,最后处理A 或B 的剩余元素.
2.9 假设有一个循环链表的长度大于1,且表中既无头结点也无头指针。已知s为指向链表某个结点的指针,试编写算法在链表中删除指针s所指结点的前趋结点。 Status Delete_Pre(CiLNode *s)//删除单循环链表中结点 s 的直接前驱 { p=s;
while(p->next->next!=s) p=p->next; //找到s 的前驱的前驱p p->next=s; return OK;
}//Delete_Pre
2.10 已知有单链表表示的线性表中含有三类字符的数据元素(如字母字符、数字字符和其它字符),试编写算法来构造三个以循环链表表示的线性表,使每个表中只含同一类的字符,且利用原表中的结点空间作为这三个表的结点空间,头结点可另辟空间。Status LinkList_Divide(LinkList &L,CiList &A,CiList &B,CiList &C)//把单链表L的元素按类型分为三个循环链表.CiList 为带头结点的单循环链表类型. {
s=L->next;
A=(CiList*)malloc(sizeof(CiLNode));p=A; B=(CiList*)malloc(sizeof(CiLNode));q=B;
C=(CiList*)malloc(sizeof(CiLNode));r=C; //建立头结点 while(s) {
if(isalphabet(s->data)) {
p->next=s;p=s; }
else if(isdigit(s->data)) {
q->next=s;q=s; } else {
r->next=s;r=s; }
}//while
p->next=A;q->next=B;r->next=C; //完成循环链表 }//LinkList_Divide
2.11 设线性表A=(a , a ,?,a ),B= (b, b ,?,b ),试写一个按下列规则合并A、B为线性表C的算法,使得:
C= (a , b ,?,a , b , b ?,b ) 当m≤n时; 或者 C= (a , b ,?,a , b , a ?,a ) 当m>n时。
线性表A、B、C均以单链表作为存储结构,且C表利用A表和B表中的结点空间构成。注意:单链表的长度值m和n 均未显式存储。void merge1(LinkList &A,LinkList &B,LinkList &C)//把链表A 和B 合并为C,A 和B 的元素间隔排列,且使用原存储空间 {
p=A->next;q=B->next;C=A; while(p&&q) {
s=p->next;p->next=q; //将B 的元素插入 if(s) {
t=q->next;q->next=s; //如A 非空,将A 的元素插入 }
p=s;q=t; }//while }//merge1
2.12 将一个用循环链表表示的稀疏多项式分解成两个多项式,使这两个多项式中各自仅含奇次项或偶次项,并要求利用原链表中的结点空间来构成这两个链表。void Divide_LinkedPoly(LinkedPoly &L,&A,&B)//把循环链表存储的稀疏多项式L 拆成只含奇次项的A 和只含偶次项的B {
p=L->next;
A=(PolyNode*)malloc(sizeof(PolyNode)); B=(PolyNode*)malloc(sizeof(PolyNode)); pa=A;pb=B; while(p!=L) {
if(p->data.exp!=2*(p->data.exp/2)) {
pa->next=p;pa=p; } else {
pb->next=p;pb=p; }
p=p->next; }//while
pa->next=A;pb->next=B; }//Divide_LinkedPoly
2.14 设多项式P(x)采用课本中所述链接方法存储。写一算法,对给定的x值,求P(x)的值。float GetValue_SqPoly(SqPoly P,int x0)//求升幂顺序存储的稀疏多项式的值 {
PolyTerm *q; xp=1;q=P.data; sum=0;ex=0; while(q->coef) {
while(ex
return sum;
}//GetValue_SqPoly
第 3 章 限定性线性表——栈和队列
3.5 试写一个算法,判断依次读入的一个以@为结束符的字母序列,是否为形如‘序列1& 序列2’模式的字符序列。其中序列1和序列2 中都不含字符’&’,且序列2 是序列1的逆序列。例如,‘a+b&b+a’是属该模式的字符序列,而‘1+3&3-1’则不是。int
IsReverse()//判断输入的字符串中'&'前和'&'后部分是否为逆串,是则返回 1,否则返回0 {
InitStack(s);
while((e=getchar())!='&') push(s,e);
while((e=getchar())!='@') {
if(StackEmpty(s)) return 0; pop(s,c);
if(e!=c) return 0; }
if(!StackEmpty(s)) return 0; return 1; }//IsReverse
3.6 假设表达式由单字母变量和双目四则运算算符构成。试写一个算法,将一个通常书写形式且书写正确的表达式转换为逆波兰式。void NiBoLan(char *str,char *new)//把中缀表达式 str 转换成逆波兰式new {
p=str;q=new; //为方便起见,设str 的两端都加上了优先级最低的特殊符号 InitStack(s); //s 为运算符栈 while(*p) {
if(*p 是字母)) *q++=*p; //直接输出 else {
c=gettop(s);
if(*p 优先级比 c 高) push(s,*p); else {
while(gettop(s)优先级不比*p 低) {
pop(s,c);*(q++)=c; }//while
push(s,*p); //运算符在栈内遵循越往栈顶优先级越高的原则 }//else }//else p++; }//while
}//NiBoLan //参见编译原理教材
3.7 假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素结点(注意不设头指针),试编写相应的队列初始化、入队列和出队列的算法。 void InitCiQueue(CiQueue &Q)//初始化循环链表表示的队列Q {
Q=(CiLNode*)malloc(sizeof(CiLNode));