实现一个单链表的反转,如:
反转前链表节点保存数据依次为:10->9->8->7->6->5->4->3->2->1
翻转后链表节点保存数据依次为:1->2->3->4->5->6->7->8->9->10
要求注意代码风格及时间复杂度/空间复杂度。
考察分析:
(1) 基本概念:链表问题、代码规范问题以及代码健壮性问题
(2) 对时间复杂度的敏感度
方法1:
额外申请链表,使用前插方法即可。
析:链表为1->2->3->4->NULL,新申请一个链表,然后新链表的节点数据依次对应原链表的倒序节点数据,最后链表为:4->3->2->1->NULL
缺点:额外申请内存,没有考虑空间复杂度。
方法2:
先找最后一个节点,再找倒数第二个节点,依次进行
析:
缺点:未考虑时间复杂度
方法3:
prev指向链表头,temp为prev->next,在循环体中,执行:
next = temp->next; temp->next = prev; //让temp的next节点指向prev prev = temp; //prev与temp依次后移 temp = next;
循环的结束条件为temp的next节点指向为空。
该方法的运行时间为O(n)。
注意考虑情况:当链表为NULL或链表只有一个节点时。
程序如下:
#include <STDIO.H> #include <STDLIB.H> typedef struct node { int iData; struct node * next; }LNode,*LinkList; //插入节点数据 LinkList Link_insert(LinkList p,int num) { LinkList temp = NULL; temp = (LinkList)malloc(sizeof(LNode)); if (temp == NULL) { perror("malloc"); exit(EXIT_FAILURE); } temp->iData = num; temp->next = p; p = temp; return p; } //打印链表 void Link_print(LinkList temp) { while (temp != NULL) { printf("%d ",temp->iData); temp = temp->next; } printf("\n"); } LinkList Link_reverse(LinkList list) { if (list == NULL || list->next == NULL) { return list; } LinkList prev,temp,next; prev = list; temp = prev->next; prev->next = NULL; //prev用来保存链表翻转后的链表头 while (temp != NULL) { next = temp->next; temp->next = prev; prev = temp; temp = next; printf("反转处理中:"); Link_print(prev); } return prev; } int main() { LinkList head = NULL; int temp = 0; for (int i = 0; i < 10; i++) { printf("输入数字:"); scanf("%d",&temp); head = Link_insert(head,temp); Link_print(head); } head = Link_reverse(head); printf("反转后的结果:\n"); Link_print(head); return 0; }
运行结果: