究竟要如何反转呢?我们不妨拿一个例子来说明一下算法。
我先画一个单链表,这个单链表有4个元素。我的思路就是,每次把第二个元素提到最前面来。比如下面是第一次交换,我们先让头结点的next域指向结点a2,再让结点a1的next域指向结点a3,最后将结点a2的next域指向结点a1,就完成了第一次交换。
步骤:
- 定义当前结点 current,初始值为首元结点,current = L->next;
- 定义当前结点的后继结点 pnext, pnext = current->next;
- 只要 pnext 存在,就执行以下循环:
- 定义新节点 prev,它是 pnext的后继结点,prev = pnext->next;
- 把pnext的后继指向current, pnext->next = current;
- 此时,pnext 实际上已经到了 current 前一位成为新的current,所以这个时候 current 结点实际上成为新的 pnext,current = pnext;
- 此时,新的 current 就是 pnext,current = pnext;
- 而新的 pnext 就是 prev,pnext = prev;
- 最后将头结点与 current 重新连上即可,L->next = current;
函数设计如下:
/*单链表反转/逆序 */
02StatusListReverse(LinkList L)
03{
04 LinkList current,pnext,prev;
05 if(L == NULL || L->next == NULL)
06 return L;
07 current = L->next; /* p1指向链表头节点的下一个节点 */
08 pnext = current->next;
09 current->next = NULL;
10 while(pnext)
11 {
12 prev = pnext->next;
13 pnext->next = current;
14 current = pnext;
15 pnext = prev;
16 printf("交换后:current = %d,next = %d\n",current->data,current->next->data);
17 }
18 L->next = current; /* 将链表头节点指向p1 */
19 return L;
20}
理解要点:
1、 current->next = NULL; 先断开,然后再连;
2、每次循环的时候,把下一个节点(Pnext)移动到最前面,然后将Pnext指向下一个即将移动的节点。
参考:http://www.nowamagic.net/librarys/veda/detail/2241