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    }

posted on 2008-03-08 17:56  EricYou  阅读(8357)  评论(5编辑  收藏  举报

导航