2024王道408数据结构 P39 T24

文章介绍了如何使用桶排序的思路优化算法,以牺牲空间来换取时间效率,解决链表中删除绝对值相同但非首个出现的节点的问题。通过创建一个辅助数组q,遍历链表并标记已出现的值,遇到重复值时直接删除,从而实现单链表的高效处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2024王道408数据结构 P39 T24

思考过程

  1. 首先我们还是先看懂题目的意思,题目说如果有绝对值相同的值,要我们删除只留下第一个值,然后题目说需要高效的算法,那我们就直接牺牲空间来换取时间。这道题我们可以用一个辅助数组*q,题目也说了data的绝对值≤n,我们就给数组q开辟n+1个int空间。
  2. 举个例子单链表长这个样子,请添加图片描述
    表中最大值是4,我们就给q开4+1个空间q=(int*)malloc(sizeof((int)*(n+1));同时把其中的值初始化为0,for(int i = 0;i<n;i++) *(q+i) = 0
  3. 桶排序的原理,我们只需要用一个指针p遍历单链表L,并且还需要一个int类型的s来帮我们存表中的绝对值。int s = abs(p->next->data);
  4. 以上面这个例子开始让p指针遍历链表L,当指针遍历到第一个元素4的时候,我们判断数组q中下标为4的位置中的值,如果为0的话就代表之前这个值没有出现过,这个时候就让p往下移,同时把数组下标为4的位置赋值为1。if (*(q+s)=0) *(q+s)=1;p=p->next;请添加图片描述
  5. 当p遍历到第二个元素-2时,同样我们判断数组q中下标为2的值是否为0,如果为0的话就代表之前这个数字没有出现过,我们就让p往下移,同时把q中下标为2的位置的值赋值为1。请添加图片描述
  6. 当p遍历到第三个元素2时,我们判断数组q中下标为2的值,发现此时下标为2的值已经为1,代表数字2之前就已经出现过,请添加图片描述
    这时候我们需要一个指针f用来删除第三个元素2,f = p->next;p->next = f->next;free(f);这样就把第三个元素2删除了,请添加图片描述
    接下来继续指针p继续往下遍历就行了。
    原理就是这么个原理,理解了桶排序之后就好做很多了,就是用空间换时间。记得最后再把我们申请的q空间给free掉就大功告成了。

完整代码附上:

//
// Created by 黎圣  on 2023/7/28.
//
#include "iostream"
typedef struct node
{
    int data;
    struct node *next;
}*linklist;

//我举的例子
int a[] = {4,-2,2,-3,-2};
int n = 5;

//创建单链表L
void CreateList(linklist &L)
{
    L = (linklist)malloc(sizeof(struct node));
    struct node *s, *r = L;
    for (int i = 0; i < n; i++)
    {
        s = (linklist)malloc(sizeof(struct node));
        s->data = a[i];
        r->next = s;
        r = r->next;
    }
    r->next = NULL;
}

//打印出来方便观察
void display(linklist L)
{
    struct node *s = L->next;
    while (s)
    {
        printf("%d ", s->data);
        s = s->next;
    }
    printf("\n");
}

//题目主代码
void deletesame(linklist L, int n)
{
    struct node *p = L, *f;
    int *q;
    int s = 0;
    q = (int *)malloc(sizeof(int)*(n+1));//给数组q开辟n+1个空间
    for (int i = 0; i < n; i++)
        *(q + i) = 0;//初始化数组q,里面全放0
    while (p->next != NULL)
    {
        s = abs(p->next->data);//s里面放data值的绝对值
        if (*(q + s) == 0)//没出现过
        {
            *(q + s) = 1;
            p = p->next;
        }
        else//该元素之前出现过
        {
            //删除结点
            f = p->next;
            p->next = f->next;
            free(f);
        }
    }
    free(q);
}

int main()
{
    linklist L;
    CreateList(L);
    display(L);
    deletesame(L, 5);
    display(L);
    return 0;
}

最后感谢b站up主@吸血小金鱼,好累…🥱

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值