《数据结构题集(C语言版)》第2章(线性表)习题自解答

说明:《数据结构题集(C语言版)》(严蔚敏等编著,清华大学出版社,旧版电子书封面为蓝灰色,简称《题集》)是《数据结构(C语言版)》(严蔚敏等编著,清华大学出版社,封面为紫色,下称“主书”)的配套书籍。《题集》的习题篇与主书相对应,分为12章。
题号后的带圈数字表示难度系数,难度级别从①至⑤逐渐加深。题号前有标注◆的题目是编者自认为值得向读者推荐的“好题”。(难度系数与“好题”均为《题集》编者标注,非本人标注)
部分算法使用了主书的配套代码中定义的数据类型和函数,在这些算法的头部省略了#include指令。
《题集》第1章为绪论,理论知识较多,本人也进行了自解答,不公开发布。本文是第2章(线性表)习题的部分自解答。后续章节不再进行自解答。本自解答在完成后参考了《题集》中的提示和答案、康建伟给出的自解答来进行订正,并经过简单测试运行。如发现错误,可留言指出。
2020年4月2日更新,2020年2-3月编写

◆2.12②

int ListCompare_Sq(SqList A,SqList B)
{
   //本算法比较顺序表A和B的大小
    int la=A.length,lb=B.length;
    int i=0,d=0;
    while(i<la&&i<lb&&d==0)
    {
   
        d=A.elem[i]-B.elem[i];
        i++;
    }
    if(d!=0) return d;
    else return la-lb;
}

2.15②

Status ListConnect(LinkList ha,LinkList hb,LinkList &hc){
   
//本程序将以hb为头结点的链表连接到以ha为头结点的链表之后,
//并用hc返回连接后链表的头结点,已知两个链表的长度分别为m和n
    LinkList p,q;//p指向短链表,q指向长链表
    if(m<n) {
   p=ha;q=hb;}
    else{
   p=hb;q=ha;}
    hc=p;
    while(p->next) p=p->next;
    p->next=q->next;
    free(q);
    return OK;
}

时间复杂度:O(min(m,n))

2.17②

注释中有标明本算法与主书P29算法2.9的不同之处。

Status ListInsert(LinkList &L,int i,ElemType e) // 算法2.9。不改变L
{
    // 在无头结点的单链线性表L中第i个位置之前插入元素e
    int j=1;//主书:j=0
    LinkList p=L,s;
    while(p&&j<i-1) // 寻找第i-1个结点
    {
   
        p=p->next;
        j++;
    }
    if(!p L&&p==NULL||j>i-1&&i!=1) // 此条件不同,空表的L=NULL;i小于1或者大于表长(i=1时j>0)
        return ERROR;
	s=(LinkList)malloc(sizeof(LNode)); // 生成新结点
	if(!s) return OVERFLOW;
    s->data=e; // 插入L中
    if(i==1)//增加此段
    {
   
        s->next=p;//插在p的前面
        L=s;
    }
    else
    {
   
        s->next=p->next;
        p->next=s;
    }
    return OK;
}

注意:无头结点的单链表的InitList(LinkList &L)函数简化为一句话:L=NULL;

2.18②

注释中有标明本算法与主书P30算法2.10的不同之处。

Status ListDelete(LinkList L,int i,ElemType &e) // 算法2.10。不改变L
{
    // 在无头结点的单链线性表L中,删除第i个元素,并由e返回其值
    int j=1;//主书:j=0
	LinkList p=L,q;
	if(!p) return ERROR;//此句新增,空表:出错
    while(p->next&&j<i-1) // 寻找第i个结点,并令p指向其前趋
    {
   
        p=p->next;
        j++;
    }
    if(!p->next||j>i-1&&i!=1) // 此句不同,删除位置不合理
    return ERROR;
    if(i==1)//此段新增
    {
   
        q=p;//首元结点无前驱
        L=p->next;
    }
    else
    {
   
        q=p->next; // 删除并释放结点
        p->next=q->next;
    }
    e=q->data;
    free(q);
    return OK;
}

◆2.19③

Status ListDelete(LinkList L,int mink,int maxk)
{
   //本算法删除单链表L中所有值大于mink且小于maxk的元素
    if(mink>maxk) return ERROR;
    LinkList p=L,q=p->next,r;
    while(q&&q->data<=mink)
    {
   
        p=q;
        q=q->next;
    }//使p指向删除段的前驱
    while(q&&q->data<maxk)
    {
   
        r=q;
        q=q->next;//使q指向删除段的后继
        free(r);
    }
	p->next=q;
	return OK;
}

2.20②

Status ListDelete(LinkList &L)
{
   //本算法删除递增有序的单链表L中所有值相同的多余元素
    LinkList p=L->next,q,r;
    while(p)//p指向删除段前驱
    {
   
        q=p->next;
        while(q&&q->data==p->data)
        {
   
            r=q;
            q=q->next;
            free(r);
        }//出循环时,q指向删除段后继
        p->next=q;
        p=p->next;
    }
    return OK;
}

时间复杂度:O(n)

◆2.21③

void Reverse(SqList &L)
{
   //本算法实现顺序表的就地逆置
    ElemType t;
    ElemType *p=L.elem,*q=p+L.length-1;
    while(p<q)
    {
   
        t=*p;
        *p=*q;
        *q=t;
        p++;
        q--;
    }
}

◆2.22③

对单链表实现就地逆置。
第一次写出的算法如下。

void Reverse(LinkList &L){
   
    if(!L->next) return;
    LinkList p=L->next,q=p->next,r;
    while(q){
   
        r=q->next;
        q->next=p;
        p=q;
        q=r;
    }
    L->next->next=NULL;
    L->next=p;
}

(答案提示)正确做法:将原链表中的头结点和第一个元素结点断开,先构成一个新的空表,然后将原链表中各结点依次插入新表的头部。

以下为根据此提示写出的算法。

void Reverse(LinkList L){
   
    LinkList p=L->next,q;
    L->next=NULL;
    while(p){
   
        q=p->next;
        p->next=L->next;
        L->next=p;
        p=q;
    }
}

◆2.24④

void ListMerge_OrderReverse(LinkList 

你可能感兴趣的:(本科课程,数据结构,算法,链表,c语言)