◆2.11② 设顺序表L中的数据元素递增有序。
试写一算法,将x插入到L的适当位置上,并保
持该表的有序性。
要求实现下列函数:
void InsertOrderList(SqList &L, ElemType x)
/* 在有序的顺序表 L 中保序插入数据元素 x */
顺序表类型定义如下:
typedef struct {
ElemType *elem;
int length;
int listsize;
} SqList;
void InsertOrderList(SqList &L, ElemType x) // 在有序的顺序表 L 中保序插入数据元素 x { ElemType *p,*q; p=L.elem; while(*p<x&&p<=(L.elem+L.length-1)){//注意此处必须要注意-1, //容易粗心犯错的地方! ++p; } //p为大于X的第一个元素指针 if(L.length==L.listsize){ L.elem=(ElemType *)realloc(L.elem,L.listsize+10); if(L.elem){ exit(OVERFLOW); } L.listsize+=10; } for(q=L.elem+L.length-1;q>=p;q--){ *(q+1)=*q; } *p=x; ++L.length; }
◆2.12③ 设A=(a1,…,am)和B=(b1,…,bn)均为有序顺序表,
A’和B’分别为A和B中除去最大共同前缀后的子表(例如,
A=(x,y,y,z,x,z),B=(x,y,y,z,y,x,x,z),则两者中最大
的共同前缀为(x,y,y,z), 在两表中除去最大共同前缀后
的子表分别为A’=(x,z)和B’=(y,x,x,z))。若A’=B’=空表,
则A=B;若A’=空表,而B’≠ 空表,或者两者均不为空表,
且A’的首元小于B’的首元,则A<b;否则a>B。试写一个比
较A和B大小的算法。(注意:在算法中,不要破坏原表A
和B,也不一定先求得A’和B’才进行比较)。
要求实现下列函数:
char Compare(SqList A, SqList B);
/* 比较顺序表A和B, */
/* 返回’<', 若A<b; *="" <br=""> /* '=', 若A=B; */
/* '>‘, 若A>B */
顺序表类型定义如下:
typedef struct {
ElemType *elem;
int length;
int listsize;
} SqList;
char Compare(SqList A, SqList B) // 比较顺序表A和B, // 返回'<', 若A<B; // '=', 若A=B; // '>', 若A>B { char a,b; int la=1,lb=1; while(la<=A.length&&lb<=B.length){ if(*(A.elem+la-1)>*(B.elem+lb-1)){return '>';} else if(*(A.elem+la-1)<*(B.elem+lb-1)){return '<';} ++la; ++lb; } if(A.length==B.length) return '='; //此处应先判断长度是否相等!! if(la==A.length+1){return '<';} if(lb==B.length+1){return '>';} }
2.13② 试写一算法在带头结点的单链表结构上实现线性表操作
Locate(L,x)。
实现下列函数:
LinkList Locate(LinkList L, ElemType x);
// If ‘x’ in the linked list whose head node is pointed
// by ‘L’, then return pointer pointing node ‘x’,
// otherwise return ‘NULL’
单链表类型定义如下:
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList Locate(LinkList &L, ElemType x) // If 'x' in the linked list whose head node is pointed // by 'L', then return pointer ha pointing node 'x', // otherwise return 'NULL' { LinkList p=L->next; while(p){ if(x==p->data){ return p; } p=p->next; } return NULL; }
2.14② 试写一算法在带头结点的单链表结构上实现线性表
操作Length(L)。
实现下列函数:
int Length(LinkList L);
// Return the length of the linked list
// whose head node is pointed by ‘L’
单链表类型定义如下:
typedef struct LNode{
ElemType data;
struct LNode *next;
} LNode, *LinkList;
int Length(LinkList L) // Return the length of the linked list // whose head node is pointed by 'L' { int i=0; LinkList p=L; while(p->next){ ++i; p=p->next; } return i; }
2.17② 试写一算法,在无头结点的动态单链表上实现
线性表操作INSERT(L,i,b),并和在带头结点的动态单
链表上实现相同操作的算法进行比较。
实现下列函数:
void Insert(LinkList &L, int i, ElemType b);
单链表类型定义如下:
typedef struct LNode{
ElemType data;
struct LNode *next;
} LNode, *LinkList;
//思路不是很清晰,很多细节问题,调试了很长时间 //主要考虑问题:1、i为0或负数时 2、i在链表长度内 3、i为链表长度+1时 4、代码精简 void Insert(LinkList &L, int i, ElemType b) { int j,count; LinkList p=L,q=L; if(i<0){exit(OVERFLOW);} for(count=0;p!=NULL;++count){ p=p->next; } if(1==i){ p=(LinkList)malloc(sizeof(LNode)); p->data=b; p->next=L; L=p; } else if (i>1&&i<=count+1){ for(p=L,j=1;j<=i-1&&p;++j){ q=p;//p为第j个元素的指针,q为p的j-1个指针 p=p->next; } p=(LinkList)malloc(sizeof(LNode)); p->data=b; p->next=q->next; q->next=p; } }
2.18② 同2.17题要求。试写一算法,
实现线性表操作DELETE(L,i)。
实现下列函数:
void Delete(LinkList &L, int i);
单链表类型定义如下:
typedef struct LNode{
ElemType data;
struct LNode *next;
} LNode, *LinkList;
void Delete(LinkList &L, int i) { int j; int count=0; LinkList p=L,q; //1、求链表长度 while(p){ p=p->next; ++count; } //2、查找第i-1号元素 //特殊位置首位、末尾 p=L; if(1==i){ L=p->next; free(p); } //i==0时没问题 else if(i>1&&i<=count) { for(p=L,j=1;j<i-1;++j){ p=p->next; } q=p->next; p->next=q->next; free(q); } }
2.20② 同2.19题条件,试写一高效的算法,删除表中所
有值相同的多余元素 (使得操作后的线性表中所有元素的
值均不相同) 同时释放被删结点空间,并分析你的算法的
时间复杂度。
实现下列函数:
void Purge(LinkList &L);
单链表类型定义如下:
typedef struct LNode{
ElemType data;
struct LNode *next;
} LNode, *LinkList;
void Purge(LinkList &L) { ElemType last=L->next->data; LinkList q=L->next,p=L->next; while(p){ if(last==p->data&&p!=L->next){ q->next=p->next; free(p); p=q; } else {last=p->data;} q=p; p=p->next; } }
◆2.21③ 试写一算法,实现顺序表的就地逆置,
即利用原表的存储空间将线性表(a1,a2,…,an)
逆置为(an,an-1,…,a1)。
实现下列函数:
void Inverse(SqList &L);
顺序表类型定义如下:
typedef struct {
ElemType *elem;
int length;
int listsize;
} SqList;
void Inverse(SqList &L) { int i; ElemType *p,temp; p=L.elem; for(i=0;i<L.length/2;++i){ temp=*(L.elem+i); *(L.elem+i)=*(L.elem+L.length-i-1); *(L.elem+L.length-i-1)=temp; } }
◆2.22③ 试写一算法,对单链表实现就地逆置。
实现下列函数:
void Inverse(LinkList &L);
/* 对带头结点的单链表L实现就地逆置 */
单链表类型定义如下:
typedef struct LNode{
ElemType data;
struct LNode *next;
} LNode, *LinkList;
void Inverse(LinkList &L) /* 对带头结点的单链表L实现就地逆置 */ { LinkList last,cur,q; q=L->next; //保存首元素地址 last=L->next;//上一个指针 cur=L->next; //当前操作的指针 if(cur){ while(cur){//此处没注意,写成了!cur,大意失荆州啊! cur=L->next; L->next=cur->next; cur->next=last; if(cur){last=cur;} } L->next=last; q->next=NULL; } }
2.23③ 设线性表A=(a1,…,am), B=(b1,…,bn),试写
一个按下列规则合并A、B为线性表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均未
显式存储。
实现下列函数:
void Merge(LinkList ha, LinkList hb, LinkList &hc)
/* 依题意,合并带头结点的单链表ha和hb为hc */
单链表类型定义如下:
typedef struct LNode{
ElemType data;
struct LNode *next;
} LNode, *LinkList;
void Merge(LinkList ha, LinkList hb, LinkList &hc) /* 依题意,合并带头结点的单链表ha和hb为hc */ { LinkList cur_a,cur_b,cur_c; cur_a=ha->next; cur_b=hb->next; cur_c=ha;//这里要注意给cur_c赋值,不然地址为空 while(cur_a&&cur_b){ cur_c->next=cur_a;//Lc的next指向a; cur_c=cur_c->next;//cur_c指向c->next cur_a=cur_a->next;//cur_a指向a->next cur_c->next=cur_b;//cur_c的next指向b cur_c=cur_c->next;//cur_c指向b cur_b=cur_b->next;//cur_b指向b->next } if(cur_a){ cur_c->next=cur_a; } if(cur_b){ cur_c->next=cur_b; } hc=ha; }
◆2.24④ 假设有两个按元素值递增有序排列的线性表
A和B,均以单链表作存储结构,请编写算法将A表和B表
归并成一个按元素值递减有序(即非递增有序,允许表
中含有值相同的元素)排列的线性表C, 并要求利用原
表(即A表和B表)的结点空间构造C表。
实现下列函数:
void Union(LinkList &lc, LinkList la, LinkList lb);
/* 依题意,利用la和lb原表的结点空间构造lc表 */
单链表类型定义如下:
typedef struct LNode{
ElemType data;
struct LNode *next;
} LNode, *LinkList;
void Union(LinkList &lc, LinkList &la, LinkList &lb) { LinkList temp,last,q; if(la->next->data<=lb->next->data){ q=la->next;last=la->next; } else { q=lb->next;last=lb->next; } while(la->next&&lb->next){ if(la->next->data<=lb->next->data){ temp=la->next; la->next=temp->next; temp->next=last; last=temp; } else{ temp=lb->next; lb->next=temp->next; temp->next=last; last=temp; } } // while(la->next){ temp=la->next; la->next=temp->next; temp->next=last; last=temp; } while(lb->next){ temp=lb->next; lb->next=temp->next; temp->next=last; last=temp; } q->next=NULL; lc=la; lc->next=temp; }
2.31② 假设某个单向循环链表的长度大于1,且表
中既无头结点也无头指针。已知s为指向链表中某个
结点的指针,试编写算法在链表中删除指针s所指结
点的前驱结点。
实现下列函数:
ElemType DeleteNode(LinkList s);
/* 删除指针s所指结点的前驱结点,并返回被删结点的元素值 */
单链表类型定义如下:
typedef struct LNode{
ElemType data;
struct LNode *next;
} LNode, *LinkList;
ElemType DeleteNode(LinkList s) /* 删除指针s所指结点的前驱结点,并返回被删结点的元素值 */ { ElemType e; LinkList p,temp=s; while(temp->next->next!=s){ temp=temp->next; } e=temp->next->data; p=temp->next; temp->next=s; free(p); return e; }
2.32② 已知有一个单向循环链表,其每个结点中
含三个域:prev、data和next,其中data为数据域,
next为指向后继结点的指针域,prev也为指针域,
但它的值为空(NULL),试编写算法将此单向循环链
表改为双向循环链表,即使prev成为指向前驱结点
的指针域。
实现下列函数:
void PerfectBiLink(BiLinkList &CL);
双向循环链表类型定义如下:
typedef struct BiNode {
ElemType data;
int freq; // 2.38题用
struct BiNode *prev,
*next;
} BiNode, *BiLinkList;
void PerfectBiLink(BiLinkList &CL) { BiLinkList p; p=CL; p->next->prev=p; p=p->next; while(p!=CL){ p->next->prev=p; p=p->next; } }
◆2.33③ 已知由一个线性链表表示的线性表中含有
三类字符的数据元素(如:字母字符、数字字符和其
它字符),试编写算法将该线性链表分割为三个循环
链表,其中每个循环链表表示的线性表中均只含一类
字符。
实现下列函数:
void Split(LinkList &lc, LinkList &ld, LinkList &lo, LinkList ll);
单链表类型定义如下:
typedef struct LNode{
ElemType data;
struct LNode *next;
} LNode, *LinkList;
void Split(LinkList &lc, LinkList &ld, LinkList &lo, LinkList ll) { LinkList p,cur_c,cur_d,cur_o; p=ll->next; cur_c=lc; cur_d=ld; cur_o=lo; while(p){ if(p->data>='A'&&p->data<='z'){ cur_c->next=p; cur_c=cur_c->next; } else if(p->data>='0'&&p->data<='9'){ cur_d->next=p; cur_d=cur_d->next; } else{ cur_o->next=p; cur_o=cur_o->next; } p=p->next; } cur_c->next=lc; cur_d->next=ld; cur_o->next=lo; }
2.37④ 设以带头结点的双向循环链表表示的线性
表L=(a1,a2,…,an)。试写一时间复杂度为O(n)的
算法,将L改造为L=(a1,a3,…,an,…,a4,a2)。
实现下列函数:
void ReverseEven(BiLinkList &L);
双向循环链表类型定义如下:
typedef struct BiNode {
ElemType data;
int freq; // 2.38题用
struct BiNode *prev,
*next;
} BiNode, *BiLinkList;
void ReverseEven(BiLinkList &L) { BiLinkList last,p,temp; int count=0; //用count计结点个数 p=L->next; //p指向第一个元素 while(p!=L->prev){//求链表长度-1 ++count; p=p->next; } last=p;//获得最后一个元素的地址 if(count>=2){ p=p->prev; while(p!=L->next){//当p指向的不是第一个元素时 if(0==count%2){//判断是否序号为偶数的结点 temp=p; p=p->prev; temp->prev->next=temp->next; temp->next->prev=temp->prev; last->next=temp; temp->prev=last; last=temp; } else{//奇号结点则继续往前 p=p->prev; } --count; } last->next=L;//构建循环 L->prev=last;//构建循环 } }
◆2.39③ 试对稀疏多项式Pn(x)采用存储量同多项式项
数m成正比的顺序存储结构,编写求Pn(x0)的算法(x0为
给定值),并分析你的算法的时间复杂度。
实现下列函数:
float Evaluate(SqPoly pn, float x);
/* pn.data[i].coef 存放ai, */
/* pn.data[i].exp存放ei (i=1,2,…,m) */
/* 本算法计算并返回多项式的值。不判别溢出。 */
/* 入口时要求0≤e1<e2<...<em,算法内不对此再作验证* <br=""> 多项式的顺序存储结构:
typedef struct {
int coef;
int exp;
} PolyTerm;
typedef struct {
PolyTerm *data;
int length;
} SqPoly;
float Evaluate(SqPoly pn, float x) /* pn.data[i].coef 存放ai, */ /* pn.data[i].exp存放ei (i=1,2,...,m) */ /* 本算法计算并返回多项式的值。不判别溢出。 */ /* 入口时要求0≤e1<e2<...<em,算法内不对此再作验证*/ { int i=0,j=1,cur;//没想到这题目的数据i是从零开始的。 float total=0,temp=1; while(i<pn.length){ for(cur=pn.data[i].exp;j<=cur;++j){ temp*=x; } total+=temp*(pn.data[i].coef); ++i; } return total; }
◆2.41② 试以循环链表作稀疏多项式的存储结构,
编写求其导函数的算法,要求利用原多项式中的结
点空间存放其导函数(多项式),同时释放所有无
用(被删)结点。
实现下列函数:
void Difference(LinkedPoly &pa);
/* 稀疏多项式 pa 以循环链表作存储结构, */
/* 将此链表修改成它的导函数,并释放无用结点 */
链式多项式的类型定义:
typedef struct PolyNode {
int coef;
int exp;
struct PolyNode *next;
} PolyNode, *PolyLink; // 多项式元素(项)结点类型
typedef PolyLink LinkedPoly; // 链式多项式
void Difference(LinkedPoly &pa) /* 稀疏多项式 pa 以循环链表作存储结构, */ /* 将此链表修改成它的导函数,并释放无用结点 */ { LinkedPoly cur=pa->next,last=pa->next,tail=pa->next; if(pa->next){//此处改为cur时遇到空表会出错,不知道为什么 if(0==last->exp){cur=cur->next;last->coef=0;} while(cur!=pa){ last->coef=cur->coef*(cur->exp); last->exp=cur->exp-1; tail=last; last=last->next; cur=cur->next; } if(cur=last->next){free(last);tail->next=pa;} } }