线性表链表表相关习题及详解(综合) ——数据结构

本文详细介绍了线性表链表的相关习题,包括删除特定值结点、链表反向输出、删除最小值结点、链表就地逆置、有序链表操作等。通过递归和迭代方法解决这些问题,涵盖了数据结构中的核心概念和技巧。

习题部分

第一题

设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点

第二题

在带头结点的单链表L中,删除所有值为x的结点,并释放空间,假设值为x的结点不唯一,试编写算法以实现上述操作。

第三题

设L为带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值

第四题

试编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点时唯一的)

第五题

试编写算法将带头结点的单链表就地逆置,所谓“就地”是指辅助空间复杂度为O(1)。

第六题

有一个带头结点的单链表L,设计一个算法使其元素递增有序。

第七题

设在一个带表投机诶单的单链表中所有元素结点的数据值无序,试编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素的元素(若存在)

第八题

给定两个单链表,编写算法找出两个链表的公共结点。

第九题

给定一个带表头结点的单链表,设head为头指针,结点的结构为(data,next),data为整形元素,next为指针,试写出算法:按递增次序输出单链表中各结点的数据元素,并释放结点所占的存储空间(要走:不允许使用数组作为辅助空间)

第十题

给定一个带表头结点的单链表A分解为两个带头结点的单链表A和B,使得A表中含有原表中序号为奇数的元素,而B表中含有原表中序号为偶数的元素,且保持其相对顺序不变

第十一题

设C={a1,b1,a2,b2…,an,bn}位线性表,采用带头结点的hc单链表存放,设计一个就地算法,将其拆分为两个线性表,使得

A={a1,a2,…,an} B={bn,…,b2,b1}

第十二题

在一个递增有序的线性表中,有数值想通的元素存在。若存储方式为单链表,设计算法去掉数值相同的元素,使表中不再有重复的元素。例如(7,10,10,21,30,42,42,42,51,70)将变作(7,10,21,30,42,51,70)

第十三题

假设有两个按元素值递增次序排列的线性表,均以单链表形式存储。请编写算法将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个单链表的结点存放归并后的单链表

第十四题

设A和B是两个单链表(带头结点),其中元素递增有序,设计一个算法从A和B中公共元素产生单链表C,要求不破坏A B 的结点

第十五题

一直两个链表A和B分别表示两个集合,其元素递增排列。绘制函数,求A与B的交集,并存放于A链表中。

第十六题

两个整数序列A=a1,a2,a3,…,am和B=b1,b2,b3,…,bn已经存入两个单链表中,设计一个算法,判断序列B是否是序列A的连续子序列

第十七题

设计一个算法用于判断带头结点的循环双链表是否对称

第十八题

有两个循环单链表,链表头指针分别为h1和h2,编写一个函数将链表h2链接到链表h1之后,要求链接后的链表仍保持循环链表形式。

第十九题

设有一个带头结点的循环单链表,其结点值均为正整数。设计一个算法,反复找出单链表中结点值最小的结点并输出,然后将该结点从中删除,直到单链表为空位置,再删除表头结点

第二十题

设头指针为L的带有表头节点的非循环双向链表,其每个结点中除了有pred(前去指针),data(数据)和next(后继指针)外,还有一个访问频度域freq。在链表被启用前,气质均初始化为零。每当在链表中进行一次Locate(L,x)运算时,令元素值为x的结点中freq域的值增加1,并使此链表中结点保持按访问频度非增(递减)的顺序排列,同事最近访问的结点排在频度相同的结点的前面,以便使频繁访问的结点总是靠近表头。试编写符合上述要求的Locate(L,x)运算的算法,该运算为函数过程,返回找到结点的地址,类型为指针型


解答部分

第一题

设f(L,x)的功能是删除以L为首结点指针的单链表中所有值等于x的结点,则显然有f(L->next,x)的功能是删除以L->next为首结点指针的单链表中所有值等于x的结点,由此,可以退出递归模型如下:

终止条件:f(L,x) 不作任何事情; 若L为空表
递归主体:f(L,x) 删除*L结点;f(L->next,x); 若L->data==x
                 f(L,x) f(L->next,x); 其他情况

本题代码如下:

void Del_X_3(Linklist &L,ElemType x){
    LNode *p;               //p指向待删除结点
    if (L==NULL)            //递归出口
    {
        return;
    }
    if(L->data == x){       //若L所指结点的值为x
        p=L;                //删除*L,并让L指向下一结点
        L=L->next;
        free(p);
        Del_X_3(L,x);       //递归调用

    }
    else                    //若L所指结点的值不为x
        Del_X_3(L->next,x); //递归调用
}

算法需要借助一个递归工作栈,深度为O(n),时间复杂度为O(n)。有人认为直接free屌结点会造成断链,实际上因为L为引用,是直接对原链表进行操作,因此不会断链。

第二题

解法一

用p从头到尾扫描单链表,pre指向*p结点的前驱。若p所指结点的值为x,则删除,并让p移向下一个结点,否则让pre、p指向同步后移一个结点。

void Del_X_1(Linklist &L,ElemType x){
    //L为带头结点的但俩你报,本算法删除L中所有值为x的结点
    LNode *p=L->next,*pre=L,*q;//置p和pre的初始值
    while(p!=NULL){
        if(p->data==x){
            q=p;                //q指向该结点
            p=p->next;
            pre->next=p;        //删除*q结点
            free(q);            //释放*q结点的空间
        }
        else{                   //柔则,pre和p同步后移
            pre=p;  
            p=p->next;
        }//else
    }//while
}

本算法是在无须单链表中删除满足某种太哦啊见的所有结点,这里的条件是结点的值为x。实际上,这个条件是可以任意指定的,只要修改if条件即可,比如,我们要求删除值介于mink和maxk之间的所有结点,则只需将if语句修改为ifp->datamink && p->data

void Del_X_2(Linklist &L,ElemType x){
    //L为带头结点的但俩你报,本算法删除L中所有值为x的结点
    LNode *p=L->next,*r=L,*q;       //r指向尾结点,其初值为头结点
    while(p!=NULL){
        if(p->data!=x){             //*p结点值不为x时将其链接到L尾部
            r->next=p;
            r=p;
            p=p->next;              //继续扫描
        }
        else{                       //*p结点值为x时将其释放
            q=p;
            p=p->next;              //继续扫描
            free(q);                //释放空间
        }
    }//while
    r->next=NULL;                   //插入结束后置尾结点指针为NULL
}

第三题

考虑到从头到尾输出比较简单,本题的思路很自然的联系到借助上题链表逆置的方法来实现,改变链表的方向,然后就可以从头到尾实现反向输出了

此外,本题还可以借助一个栈来实现,每经过一个结点时,将该结点访入栈中。在遍历完整个链表后,再从栈顶开始输出结点值即可。

既然能用栈的思想解决,也就很自然地联想到了用递归来实现,每当访问一个结点时,先递归输出它后面的结点,再输出该结点自身,这样链表就反向输出了。

本体代码如下:

void R_Print(LinkList L){
    //从尾到头输出单链表L中每个结点的值
    if(L->next!=NULL){
        R_Print(L->next);   //递归
    }//if
    printf(L->data);        //输出函数


}

第四题

算法思想:用p从头至尾扫描单链表,pre指向*p结点的前驱,用minp保存值最小的结点指针(初值为p),minpre指向*minp结点的前驱(初值为pre)。一边扫描,一边比较,若p->data小于minp->dara,则将p、pre分别复制给minp、minpre。

当p扫描完毕,minp指向最小值结点,minpre指向最小值结点的前驱结点,再将minp所指结点删除即可。

LinkList Delete_Min(LinkList &L){
    //L是带头结点的单链表,本算法删除其最小值结点
    LNode *pre=L,*p=pre->next;      //p为工作指针,pre指向其前驱
    LNode *minpre=pre,*minp =p;     //保存最小值结点及其前驱
    while(p!=NU
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值