将一个单链表反序输出,比如原单链表位1->2->3->4->NULL,反序输出后变为4->3->2->1->NULL
看图说话,假如原单链表为a1->a2->a3->a4->NULL。下面的这个方法是定义三个指针,分别将后面的节点向前移动到头结点的后面。第一次交换就是把a2向前移动到a1前面,下图是第一次转换,转换后顺序就变成了a2->a1->a3->a4->NULL
第二次交换,更新current和Pnext指针,把a3向前移动到a2前面,如下图所示
void List_Reverse_Head(LinkList *L)
{
if((*L) == NULL){
exit(ERROR);
}
LinkList current, pnext,prev;
current = (*L)->next;
pnext = current->next;
current->next = NULL; // 第一个节点肯定是尾节点,尾节点的next为NULL
while(pnext){
prev = pnext->next;
pnext->next = current;
current = pnext;
pnext = prev;
}
(*L)->next = current; //表头指向current节点
}
上面代码是有头结点的单链表反序,如果是无头结点的如何实现呢?其实很简单,只需要修改几处即可。
void List_Reverse_noHead(LinkList *L)
{
if((*L) == NULL){
exit(ERROR);
}
LinkList current, pnext,prev;
current = (*L);
pnext = current->next;
current->next = NULL; // 第一个节点肯定是尾节点,尾节点的next为NULL
while(pnext){
prev = pnext->next;
pnext->next = current;
current = pnext;
pnext = prev;
}
(*L) = current;
}
下面是测试单链表反转的整体测试程序,包括创建链表,打印链表,在主函数里,先随机产生20个元素的单链表,然后打印出创建的单链表,接着先用带头结点的反转程序进行反转,打印输出,最后用不带头结点的反转程序再反转,这时又变成原来的单链表了,打印输出
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef struct Node{
int data;
struct Node *next;
}Node, *LinkList;
/*随机产生n个元素的带表头的单链表(头插法)*/
void CreatList_Head(LinkList *L, int n){
LinkList p;
int i;
srand(time(0));
(*L) = (LinkList)malloc(sizeof(Node));
if(!(*L)){
exit(ERROR);
}
(*L)->next = NULL;
for(i = 0; i < n; i++){
p = (LinkList)malloc(sizeof(Node));
if(!p){
exit(ERROR);
}
p->data = rand()%100 + 1;
p->next = (*L)->next;
(*L)->next = p;
}
}
/*随机产生n个元素的带表头的单链表(尾插法)*/
void CreatList_Tail(LinkList *L, int n){
LinkList p,r;
int i;
srand(time(0));
(*L) = (LinkList)malloc(sizeof(Node));
if(!(*L)){
exit(ERROR);
}
r = (*L);
for(i = 0; i < n; i++){
p = (LinkList)malloc(sizeof(Node));
if(!p){
exit(ERROR);
}
p->data = rand()%100 + 1;
r->next = p;
r = p;
}
r->next = NULL;
}
void Print_List(LinkList L){
LinkList p;
if(!L){
exit(ERROR);
}
p = L->next;
while(p){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
void Print_List_noHead(LinkList L){
LinkList p;
if(!L){
exit(ERROR);
}
p = L;
while(p){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
void List_Reverse_Head(LinkList *L)
{
if((*L) == NULL){
exit(ERROR);
}
LinkList current, pnext,prev;
current = (*L)->next;
pnext = current->next;
current->next = NULL; // 第一个节点肯定是尾节点,尾节点的next为NULL
while(pnext){
prev = pnext->next;
pnext->next = current;
current = pnext;
pnext = prev;
}
(*L)->next = current; //表头指向current节点
}
void List_Reverse_noHead(LinkList *L)
{
if((*L) == NULL){
exit(ERROR);
}
LinkList current, pnext,prev;
current = (*L);
pnext = current->next;
current->next = NULL; // 第一个节点肯定是尾节点,尾节点的next为NULL
while(pnext){
prev = pnext->next;
pnext->next = current;
current = pnext;
pnext = prev;
}
(*L) = current;
}
int main(int argc, char const *argv[])
{
LinkList L;
CreatList_Head(&L,20);
//CreatList_Tail(&L, 10);
Print_List(L);
List_Reverse_Head(&L);
Print_List(L);
List_Reverse_noHead(&(L->next));
Print_List_noHead(L->next);
return 0;
}
结果输出
8 48 77 76 14 76 2 81 46 63 53 27 61 21 5 62 43 5 55 93
93 55 5 43 62 5 21 61 27 53 63 46 81 2 76 14 76 77 48 8
8 48 77 76 14 76 2 81 46 63 53 27 61 21 5 62 43 5 55 93
[Finished in 0.1s]