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;}  
    }  
}
原文地址:https://www.cnblogs.com/hlb430/p/2613062.html