链表习题选做

2、在单链表L中删除所有值为x的结点,x不唯一

LinkList deletx (LinkList &L,int x)//第二题
{
    LNode *r=L->next;//r是rr的前驱
    while(rr!=NULL)
    {
        LNode *rr=r->next;//rr是r的后继
        if(rr->data==x) {r->next=rr->next;free(rr);}
        r=r->next;//移动
    }
    return L;
}

就是找到前驱结点,然后建立链接关系就好,这里注意rr的定义是在循环内部的,如果写在外面rr就始终为空了,因为一次free,rr就没了,所以每次要建立一个新的rr。

4、删除单链表中的最小值结点,该最小值是唯一的

LinkList deletemin (LinkList &L,int x)//第四题
{
    int min=INT_MAX;
    LNode *s=L;
    LNode *ss;
    ss=(LNode*)malloc(sizeof(LNode));
    while(s->next!=NULL)
    {
        if(s->next->data<=min) {min=s->next->data;ss=s;}//ss存的是s->next的前驱节点
        s=s->next;//移动
    }
    LNode *sss=ss->next;
    ss->next=sss->next;
    free(sss);
    return L;
}

就是找前驱节点,这是要求s从L开始,因为后继结点要求从L->next开始找,即从第一个元素开始。最小值判断始终判断的是后继结点的内容,最小值的存储地址则是前驱结点。
然后就是常规的删除操作了。

21、找倒数第k个元素

int findk(LinkList &L,int k)//第21题
{
    if(L->next!=NULL)
        return(findk(L,k));
    if(L!=NULL)
    {
        int a=0;
        for(int i=1;i<=k;i++)
           a=L->data;
        return 1;
    }
    return 0;
}

第一个想法是拿递归或者栈做,但最好的方法还是快慢指针,具体在操作部分有写(上一篇文章)。

22、找两个单链表的共同后缀的其实位置,比如loading和being的起始位置是i。

LNode Thesame(LinkList &L1,LinkList &L2)//第22题
{
    LNode *s=L1->next;
    LNode *r=L2->next;
    while(s->next!=NULL)
    {
        while(r->next!=NULL)
        {
            if(s==r) return *s;
            else r=r->next;
        }
        s=s->next;
    }
    return *s;
}

常规方法当然是两个循环挨个找,更好的方法是先确定两个链表的长度,设置一个快慢指针,快指针指向长的,长的比短的要多走个两个长度差加1步,比如长度为7和长度为5的元素相比,快指针就需要先走个三步,loading走到a的位置,慢指针开始从being的b走,两个一起走,发现一样的直接输出就行了。时间复杂度便从O(n*m)变成O(m+n),或者说O(max(m,n))。

23、对于链表中data绝对值相等的结点,仅仅保存第一次出现的结点,删除其他绝对值相等的结点。

#define inital 100
LinkList deletesame(LinkList &L)//第23题
{
    int *a=new int[inital];
    LNode *s=L;
    while(s->next!=NULL)//s是前驱节点
    {
        LNode *ss=s->next;
        a[abs(ss->data)]++;
        if(a[ss->data]>1) {s->next=ss->next;free(ss);}
        s=s->next;//移动
    }
    return L;
}

借助辅助数组,我们可以确定每个元素的出现次数,为了避免第一次的元素刚出现就被删除的问题,这里把查找部分合并在了数组的增值部分,如果大于1再进行删除操作,这样第一个元素就不会被删除,避免了先增值后删除中必须引入first变量的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值