C递归实现单向链表的反转
C递归实现单向链表的反转
众所周知,链表作为线性表的一种实现方式,有插入删除方便的优点,但不能对节点进行随机访问.同时,要想知道某一节点的前驱节点,必须从头节点开始遍历才能找到,这体现了单链表的方向性.由于单链表方向性的存在,使得链表的反转变得复杂起来.
在这里,采用递归的算法,可以使反转过程看起来更容易理解,代码如下:
在这里,采用递归的算法,可以使反转过程看起来更容易理解,代码如下:
1 /* 2 Code by : EricYou 3 http://www.cnblogs.com/yxin1322 4 Date: 2006.1.14 5 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <conio.h> 11 12 /*链表节点存储的数据*/ 13 typedef char ElemType; 14 15 16 /*链表节点结构*/ 17 typedef struct LinkListNode 18 { 19 ElemType data; 20 struct LinkListNode * next; 21 } *LinkList,*pNode,LinkListNode; 22 23 24 /*递归实现反转不带头节点的单向链表 25 26 pNode:PerNode 前一节点指针 27 pNode:CurrentNode 后一节点指针 28 visit 自定义节点访问函数 29 */ 30 LinkList ReverseLinkList( pNode PreNode, pNode CurrentNode, void(*visit)(ElemType e) ) 31 { 32 if(!CurrentNode) /*如果当前节点指针为空,则返回NULL,此种情况只有在*/ 33 return NULL; /*链表头指针为空时才可能执行到*/ 34 35 if(!CurrentNode->next) /*如果下一节点指针为空,则将当前节点next指针指向上一节点,并*/ 36 { /*返回当前节点指针,次种情况只有在当前节点为尾节点时才能执行到*/ 37 visit(CurrentNode->data); 38 CurrentNode->next=PreNode; 39 return CurrentNode; 40 } 41 else /*其他节点的情况,先调用递归函数反转后续节点,再反转当前节点*/ 42 { /*并将递归函数返回来的尾节点指针向上层函数返回*/ 43 LinkList FirstNode; 44 45 FirstNode=ReverseLinkList(CurrentNode,CurrentNode->next,visit); 46 47 visit(CurrentNode->data); 48 CurrentNode->next=PreNode; 49 return FirstNode; /*返回的是尾节点的指针,即反转后新链表的头指针*/ 50 } 51 } 52 53 /*自定义链表节点访问函数*/ 54 void visit(ElemType e) 55 { 56 printf("process node %c\n",e); 57 } 58 59 60 /*打印链表*/ 61 void PrintLinkList(LinkList PL) 62 { 63 printf("\n--------------------------\n"); 64 while(PL) 65 { 66 printf("%c ",PL->data); 67 PL=PL->next; 68 } 69 printf("\n--------------------------\n"); 70 } 71 72 /*用键盘输入初始化一个链表,参数为链表头指针地址*/ 73 void InitializeLinkList(LinkList * Head) 74 { 75 pNode EndNode=*Head; /*总是指向链表最后一个节点*/ 76 77 pNode TempNode=NULL; /*临时节点,存放当前输入的链表节点*/ 78 int i=1; /*节点记数*/ 79 char getEnter; 80 81 printf("please input characters of the linklist(end with Enter):\n"); 82 83 /*开始构造不带头节点的单向链表*/ 84 while(1)/*不停地循环接受字符*/ 85 { 86 TempNode=(pNode)malloc(sizeof(LinkListNode)); /*为当前输入的链表节点分配空间*/ 87 TempNode->next=NULL; 88 89 printf("Node[%d]:",i); 90 TempNode->data=getchar(); /*接受字符*/ 91 92 93 if(TempNode->data== ' \n ' ) /*如果直接回车,则结束链表的输入*/ 94 { 95 TempNode=NULL; 96 break; 97 } 98 getEnter=getchar(); /*接受输完字符后的回车*/ 99 100 if(i==1) /*如果当前输入的是第一个节点,则让头指针指向它*/ 101 { 102 *Head=TempNode; 103 EndNode=*Head; 104 } 105 106 EndNode->next=TempNode; /*将当前输入的节点接到链表尾端*/ 107 EndNode=TempNode; 108 109 i++; 110 } 111 } 112 113 int main() 114 { 115 LinkList head=NULL; /*声明头指针*/ 116 117 InitializeLinkList(&head); /*初始化链表*/ 118 119 PrintLinkList(head); /*打印原链表*/ 120 121 head=ReverseLinkList(NULL,head,visit); /*调用反转函数*/ 122 123 PrintLinkList(head); /*打印反转后的链表*/ 124 125 return 1; 126 }