本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中奇数值的结点重新组成一个新的链表。链表结点定义如下:
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未变换时所指向的地址”),但我并不像改动了,因为每当你回顾一次都会发现以前写的代码写得不是很满意,等我刷了很多数据结构的题后,这个题也会像当初的简单编程题,比如输入两个值,输出其和。所以有感兴趣的可以自己修改完善。我要开始刷力扣了!当然也会写下数据结构严蔚敏版的课后代码习题,因为有的粉丝是地大的同学(虽然就只有那么一丢丢),当记录贴,大家可以一起回顾复习。