问题描述
编写带代码实现反转单链表。如 [1,2,3,4,5] 变为 [ 5,4,3,2,1 ]
要求空间复杂度为O(1)
先直接给出一份完整的代码,可以直接运行。
C:
#include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int datatype; //链表持有的数据的类型 typedef struct node //结点的定义 { datatype element; struct node*next; }_link_node_; typedef struct //链表的定义 { _link_node_*head; size_t size; }linkedlist; /** 初始化一个带头结点的链表 */ void init_list(linkedlist*plist) { plist->head = (_link_node_*)malloc(sizeof(_link_node_)); assert(plist->head!=NULL); plist->head->next = NULL; plist->size = 0; } /** 输入链表元素创建链表。 */ void creat_list(linkedlist*plist) { _link_node_*p1 , *p2 ; datatype temp; printf("input elemments , enter '#' to stop "); while(1==scanf("%d",&temp)) { p1 = (_link_node_*)malloc(sizeof(_link_node_)); p1->element = temp; p1->next = NULL; if(plist->head->next == NULL) plist->head->next = p1; else p2->next = p1; p2 = p1; plist->size++; } } /** 打印链表 */ void print_list(linkedlist* plist) { _link_node_*p = plist->head->next; printf("["); if(p!=NULL) { printf("%d",p->element); p = p->next; while(p!=NULL) { printf(",%d",p->element); p = p->next; } } printf("]"); } /** 求链表的长度 */ size_t size_list(linkedlist* plist) { return plist->size; } /** 销毁链表 */ void delete_list(linkedlist*plist) { _link_node_*p = plist->head; _link_node_*t; while(p!=NULL) { t = p; p = p->next; free(t); } }
/************************反转单链表********************************/ void reverse_list(linkedlist*plist) { _link_node_* pre; //3个游标结点指针 _link_node_* cur; _link_node_* nxt; if (1<size_list(plist)) //链表数据多余1个,才有反转操作的必要 { pre = NULL; //初始状态 cur = plist->head->next; nxt = cur->next; //循环 while(NULL != nxt) { cur->next = pre; pre = cur; cur = nxt; nxt = nxt->next; } //退出循环 cur->next = pre; plist->head->next = cur; } // end if } int main(void) { linkedlist list; init_list(&list); creat_list(&list); printf("反转前:"); print_list(&list); printf(" "); printf("反转后:"); reverse_list(&list); print_list(&list); printf(" "); delete_list(&list); return 0; }
测试的输入输出:
代码解析
思想是使用3个游标结点指针,一边修改结点的指针域,一边往后挪动。最后使得整个链表被反转。
构造的初始链表结构如下:
执行reverse_list函数的步骤: