倒置链表

来源:互联网 发布:淘宝卖小饰品 编辑:程序博客网 时间:2024/04/27 21:26

        最近看了很多对于链表的操作,对链表的操作无非就是对指针的操作,因此,经常会使人晕头转账,今天跟大家分享一个逻辑不是很复杂,但是对指针的操作较为复杂的一个例子----倒置链表。

        顾名思义,倒置链表就是将一个链表里的数据颠倒过来,使得原来的头成为尾部,原来的尾部变成第一个节点。当然,一个简单的方法,可以每次都取得当前链表的最后一个节点,将其前插到新生成的链表的第一个节点的位置,再将该节点释放,最后把新生成的链表的头结点首地址赋给原先链表的头结点首地址。但是,这样做不管是时间复杂度还是空间复杂度,都是比较高的,而如果可以只更改链表里的每个节点的next成员的指向,效率则会大大提高。

        首先我们分析它的手工过程:我们首先要明确链表里的数值遍历的原理以及各个节点的指向关系。我们用一幅图来清晰地表示。

        完成倒置链表有以下几点需要注意:

        1、我们现在要做的就是使head的值变成#5,#1中next成员的值变为NULL,#2中next成员的值变为#1,#3中next成员的值变为#2... ...同时还要满足能够遍历整个链表,依次更改每一个节点中next的值,不能出现更改后无法找到下一个节点的情况。比如#2的next成员更改为了#1,当希望继续找到#3时,原来next空间中存储的#3的地址值已经被覆盖为#1了,因此就不能继续修改#3中next成员的值了,而且还会造成内存泄漏。

        2、我们发现需要将当前节点的next成员修改为当前节点的前一个节点的首地址,这就要求我们每次修改完能够将当前节点的首地址存储起来。而当前节点的首地址又是它的前驱节点的next成员没有更改时的值。

        3、第一个节点和最后一个节点情况较为特殊,因为第一个节点的next成员被更改为NULL,而末节点的首地址又应该赋值给head。


        知道了以上三点我们就可以开始编程了:

        1、我们需要一个变量now用来遍历链表,而更改这个变量的时机必须在我们修改当前节点的next成员之前。

        2、需要一个用来存储当前节点的前驱节点的地址的变量preNode。

        3、每次应先将preNode的值赋值给now的next成员,再将now的值赋值给preNode。

        4、preNode的初值应为NULL,而不应该是#1,因为我们遍历肯定是从第一个节点开始遍历,第一个节点的前一个节点当然应该是空,这样做,一是符合语义性,二是根据我们之前所说的操作“每次将preNode的值赋值给now的next成员”,可以不用单独处理第一个节点,就能够保证第一个节点的next成员的值为NULL。

        5、在最后,我们应该将now的值赋值给head,因为循环结束时,now的值一定是原先链表的最后一个节点。

具体代码如下:

#include <stdio.h>#include <malloc.h>typedef struct NODE{int data;struct NODE *next;}NODE;void initLine(NODE **head);void destoryLine(NODE **head);void showLine(NODE *head);void upSideDownLine(NODE **head);void upSideDownLine(NODE **head) {NODE *now = *head;NODE *preNode = NULL;NODE *temp;while (now != NULL) {temp = now->next;now->next = preNode;preNode = now; now = temp;}*head = preNode;}void showLine(NODE *head) {NODE *p;printf("\n");for (p = head; p != NULL; p = p->next) {printf("%d ", p->data);}printf("\n");}void destoryLine(NODE **head) {NODE *p;if (*head == NULL) {return;}while(*head != NULL) {p = *head;*head = p->next;free(p);}}void initLine(NODE **head) {int num;NODE *p = *head;if (*head != NULL) {return;}printf("请输入一个数(-1表示结束输入):");scanf_s("%d", &num);while (num != -1) {if (*head == NULL) {*head = (NODE *)calloc(1, sizeof(NODE));(*head)->data = num;p = *head;}else {p->next = (NODE *)calloc(1, sizeof(NODE));p->next->data = num;p = p->next;}printf("请输入一个数(-1表示结束):");scanf_s("%d", &num);}}void main(void) {NODE *head = NULL;initLine(&head);showLine(head);upSideDownLine(&head);showLine(head);destoryLine(&head);fflush(stdin);getchar();}


原创粉丝点击