习题11-7 奇数值结点链表 (20分)

本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中奇数值的结点重新组成一个新的链表。链表结点定义如下:

struct ListNode {
    int data;
    ListNode *next;
};

函数接口定义:

struct ListNode *readlist();
struct ListNode *getodd( struct ListNode **L );

函数readlist从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。

函数getodd将单链表L中奇数值的结点分离出来,重新组成一个新的链表。返回指向新链表头结点的指针,同时将L中存储的地址改为删除了奇数值结点后的链表的头结点地址(所以要传入L的指针)。

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>

struct ListNode {
    int data;
    struct ListNode *next;
};

struct ListNode *readlist();
struct ListNode *getodd( struct ListNode **L );
void printlist( struct ListNode *L )
{
     struct ListNode *p = L;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\n");
}

int main()
{
    struct ListNode *L, *Odd;
    L = readlist();
    Odd = getodd(&L);
    printlist(Odd);
    printlist(L);

    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例:

1 2 2 3 4 5 6 7 -1

输出样例:

1 3 5 7

2 2 4 6

struct ListNode *readlist()//这是用C/C++写的,按理说在学了一门C++语言或者C语言,以及线性表的知识后应该就能写出来了
{
    struct ListNode *p,*head=(struct ListNode *)malloc(sizeof(struct ListNode));//这里不多说,很简单。就两个,头结点,然后用结构指针来“逐渐往后增加值”
    struct ListNode *p1=head;
    int number,size=sizeof(struct ListNode);
    scanf("%d",&number);
    while(number!=-1)
    {
        p=(struct ListNode *)malloc(size);
        p->data=number;
        //这里用的是“尾插法”
        p1->next=p;
        p1=p;
        scanf("%d",&number);
    }
    p1->next=NULL;
    return head->next;//因为用了头指针,所以返回的头节点后面的结点
}
struct ListNode *getodd( struct ListNode **L )//这个方法实际上是在三个链表间“操作”,但是后面可以free掉原来的链表L,所以空间复杂度和其他没有多大区别
{
    //以下建立的两个链表是带有头结点的
    struct ListNode *H1=(struct ListNode *)malloc(sizeof(struct ListNode));//存放奇数结点
    struct ListNode *t1=H1;//用这个结构指针来操作,运用“尾插法”,H1后面要用来返回地址
    struct ListNode *H2=(struct ListNode *)malloc(sizeof(struct ListNode));//存放偶数结点
    struct ListNode *t2=H2;//同理
    struct ListNode *a1,*a2;//用来“开辟”结点的,这个说法貌似不太正确……
    while((*L))
    {
        if((*L)->data%2!=0)
        {
            a1=(struct ListNode *)malloc(sizeof(struct ListNode));
            a1->data=(*L)->data;
            //接下来是尾插法
            t1->next=a1;
            t1=a1;
        }
        else
        {
            a2=(struct ListNode *)malloc(sizeof(struct ListNode));
            (*a2).data=(**L).data;//这里这样写和a2->data=(*L)->data是等价的
            //尾插法
            (*t2).next=a2;//指针很重要,但学C++时老师只是一点而过,所以如果有地大的同学看到这个贴子,建议还是好好学下指针,链表无非就是在堆的地址里,划定区域地址放数据,当然话可能说得有点狂……
            t2=a2;
        }
        *L=(*L)->next;
    }
    free(*L);//这里是想把原来的链表占用的内存释放,用了C语言里的‘free’,
    *L=H2->next;//将头节点“减一”
    t2->next=NULL;//尾插法一定要将最后的节点指向NULL
    t1->next=NULL;
    return H1->next;//同理
}

补充,我想释放原来的列表所占的内存空间,但那个写法是错的,没有删除成功,原因不详解释了。但可以再添加一个结构指针存放L未变换时所指向的地址,然后在 L变化后,用free函数清空,例如free(“一个结构指针存放L未变换时所指向的地址”),但我并不像改动了,因为每当你回顾一次都会发现以前写的代码写得不是很满意,等我刷了很多数据结构的题后,这个题也会像当初的简单编程题,比如输入两个值,输出其和。所以有感兴趣的可以自己修改完善。我要开始刷力扣了!当然也会写下数据结构严蔚敏版的课后代码习题,因为有的粉丝是地大的同学(虽然就只有那么一丢丢),当记录贴,大家可以一起回顾复习。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值