anyview 數據結構習題集 第2章答案


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM