奇数值结点链表
解法一
struct ListNode *readlist()
{
struct ListNode *head = NULL, *p;
int data=0;
while(scanf("%d", &data)&&data != -1)
{
struct ListNode *q = (struct ListNode *)malloc(sizeof(struct ListNode));//为节点分配存储空间
if(q!=NULL)
{
q->data = data;
q->next = NULL;
}//增加了一个节点
else exit(1);//异常退出
if(head != NULL)
{
p->next = q;
}
else head = q;
p = q;
}
return head;
}
struct ListNode *getodd( struct ListNode **L )
{
struct ListNode *head0 = NULL, *head1 = NULL, *p0, *p1;
while((*L) != NULL)
{
int data = (*L)->data;
struct ListNode *q = (struct ListNode *)malloc(sizeof(struct ListNode));
if(data%2)
{
if(q != NULL)
{
q->data = data;
q->next = NULL;
}
else exit(1);
if(head1 != NULL)
{
p1->next = q;
}
else head1 = q;
p1 = q;
}
else
{
if(q != NULL)
{
q->data = data;
q->next = NULL;
}
else exit(1);
if(head0 != NULL)
{
p0->next = q;
}
else head0 = q;
p0 = q;
}
(*L) = (*L)->next;
}
*L = head0;//L存储偶数值
return head1;//返回奇数值
}
此解法是刚学习链表时从网上找到的一种解法,具体思路为新建两个链表,然后将L链表中的值各自放到对应链表中,最后把偶数链表的头节点给(*L)。
此解法需要申请新的内存,若不能及时释放会造成内存空间的浪费, 所以不能算是最优的算法。
解法二
struct ListNode *readlist() {
//尾插
struct ListNode *head = NULL, *tail = NULL;
int a;
scanf("%d", &a);
while(a!=-1) {
struct ListNode *newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->data = a;
newNode->next = NULL;
if(head == NULL) {
tail = head = newNode;
} else {
tail->next = newNode;
tail = newNode;
}
scanf("%d", &a);
}
tail->next = NULL;
return head;
}
struct ListNode *getodd(struct ListNode **L) {
/*解题思路, 将L链表中的奇数节点从链表中提出来放入新得奇数链表, L存放偶数节点*/
/*p1为计数指针,从L链表的头节点数到尾节点, p2为奇数链表计数(定位)指针, prev用于记录偶数链表当前节点*/
struct ListNode *p1 = (*L), *head1 = NULL, *p2 = NULL, *prev = NULL;//head1奇数链表的头
while(p1) {
if(p1->data%2!=0) {
if(head1 == NULL) {//只运行一次,放入奇数链表的头节点
head1 = p1;
p2 = head1;//定位奇数链表
} else {
p2->next = p1;//经典---尾添加节点
p2 = p1;
}
if(prev == NULL) {
(*L) = (*L)->next;//也只运行一次,如果L链表头节点为奇数时,L链表的头指向下一个, 如果L链表头节点为偶数节点时,此判断不会运行
} else {
if(p1->next == NULL) {//经典--打断指针指向
prev->next = NULL;
} else {
prev->next = p1->next;
}
}
} else { //**********此处由于未将prev作用弄清楚废了好长时间*********//
prev = p1;//(地址:(*L) = p1 = prev.) prev应该定位的是偶数链表的当前节点,不应该直接放在外层
}
p1 = p1->next;
}
if(head1!=NULL) {
p2->next = NULL;//将奇数链表的尾节点的指针置空,没啥好说的
}
return head1;
}
此解法为学习链表一周多后自己的解法,具体解法思路在代码中,此解法是在没有借鉴其他解法的情况下自己想出来的,虽然花费了好长时间思考,但着实能够加强思考问题的逻辑性与考虑的全面性,也同时使我加深和巩固了链表的相关知识,美滋滋。
tips:
1.链表中的指针主要是地址之间的指来指去,对链表操作时应注意地址指向,像空节点(NULL)在指向下一个节点时会发生越界(段错误)。
2.操作链表要注意链表的头不能丢,丢了头就找不到链表啦。
3.注意整个过程的逻辑性与思考问题的全面性,问题复杂时建议先在纸上画个简单的例子,帮助思考过程中的判断。