◆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;} } }