本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中奇数值的结点重新组成一个新的链表。链表结点定义如下:
struct ListNode {
int data;
ListNode *next;
};
函数接口定义:
struct ListNode *readlist();
struct ListNode *getodd( struct ListNode **L );
函数readlist
从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。
函数getodd
将单链表L
中奇数值的结点分离出来,重新组成一个新的链表。返回指向新链表头结点的指针,同时将L
中存储的地址改为删除了奇数值结点后的链表的头结点地址(所以要传入L
的指针)。
struct ListNode *readlist(){
struct ListNode * head = (struct ListNode *)malloc(sizeof(struct ListNode)*1);
struct ListNode * last = (struct ListNode *)malloc(sizeof(struct ListNode)*1);
head->next = NULL;
last->next = NULL;
struct ListNode * current = NULL;
int number = 0;
do{
scanf("%d",&number);
if(number == -1){
return head->next;
}
current = (struct ListNode *)malloc(sizeof(struct ListNode)*1);
current->data = number;
current->next = NULL;
if(head->next == NULL){
head->next = current;
}
if(last->next == NULL){
last->next = current;
}else{
last->next->next = current;
last = current;
}
}while(number != -1);
return head->next;
}
struct ListNode *getodd( struct ListNode **L ){
struct ListNode * head = *L;
struct ListNode * currentNode = head;
struct ListNode * frontNode = NULL;
struct ListNode * odds = (struct ListNode *)malloc(sizeof(struct ListNode)*1);
struct ListNode * oddsLast = NULL;
struct ListNode * listNode = NULL;
odds->next = NULL;
int flag = 1;
while(currentNode != NULL){
if(currentNode->data % 2 == 1){
//将节点取出
if(frontNode != NULL){
frontNode->next = currentNode->next;
}
if(flag == 1){
head = currentNode->next;
}
listNode = currentNode;
//将节点插入奇数链表
if(oddsLast == NULL){
odds->next = listNode;
oddsLast = listNode;
}else{
oddsLast->next = listNode;
oddsLast = listNode;
}
}else{
flag = 0;
frontNode = currentNode;
}
currentNode = currentNode->next;
}
if(oddsLast != NULL && oddsLast->next != NULL){
oddsLast->next = NULL;
}
*L = head;
return odds->next;
}
Notice:
- 二重指针
首先总结一下我现在对于C语言的指针的理解。指针是什么?我会这样回答,指针是变量,存储地址的变量。那么二重指针是什么呢?存储指针地址的变量。
针对这里的二重指针的赋值,有两种方法:
//第一种方法
*L = head;
//第二种方法
L = &head;
但是经过测试,我发现第二种方法存在问题,经过debug,发现问题出现在题目自带的main函数中,
int main()
{
struct ListNode *L, *Odd;
L = readlist();
//注意这里传入的参数没有二重指针,只是存入L指针的地址(&L)
Odd = getodd(&L);
printlist(Odd);
printlist(L);
return 0;
}
从上述代码我们可以理解到,传入参数并没有存在二重指针,只是指针L的地址。所以当我们采用第二种办法为二重指针赋值的时候,赋值的结果会丢失。
- 链表头结点
在写链表相关代码的时候,我比较喜欢直接默认为有头结点的链表,这样可以减少很多的冗余代码。