
第一次交换

第二次交换

第三次交换
步骤:
- 定义当前结点 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;
函数设计如下:
/* 单链表反转/逆序 */
Status ListReverse(LinkList L)
{
LinkList current,pnext,prev;
if(L == NULL || L->next == NULL)
return L;
current = L->next; /* p1指向链表头节点的下一个节点 */
pnext = current->next;
current->next = NULL;
while(pnext)
{
prev = pnext->next;
pnext->next = current;
current = pnext;
pnext = prev;
printf("交换后:current = %d,next = %d
",current->data,current->next->data);
}
//printf("current = %d,next = %d
",current->data,current->next->data);
L->next = current; /* 将链表头节点指向p1 */
return L;
}
Status ListReverse2(LinkList L)
{
LinkList current, p;
if (L == NULL)
{
return NULL;
}
current = L->next;
while (current->next != NULL)
{
p = current->next;
current->next = p->next;
p->next = L->next;
L->next = p;
}
return L;
}
- p = current->next; p 就相当于前面的 pnext。(图1中a2即为p)
- current->next = p->next; p->next 就相当于 prev的角色,这句代码意思是 current 的后继指向 prev.(相当于图1中a1->next = a3(a2->next))
- p->next = L->next; 这句就是 p 的后继直接指向首元节点。(相当于图1中a2->next = a1)
- L->next = p; 然后再将头结点指向 p。(相当于图1中L->next = a2
这个是程序运行的结果。
整体创建L的元素(头插法): // 原链表,current = 68, pnext = 55,68指向18,55指向18,头结点指向55 -> 68 -> 55 -> 18 -> 45 -> 41 -> 43 -> 5 -> 28 -> 80 -> 67 // 第一次交换后,原链表变成这样 -> 55 -> 68 -> 18 -> 45 -> 41 -> 43 -> 5 -> 28 -> 80 -> 67 // 进行第二次交换,pnext = 18,68指向45,18变成头结点 -> 18 -> 55 -> 68 -> 45 -> 41 -> 43 -> 5 -> 28 -> 80 -> 67 // 进行第三次交换,pnext = current->next = 45,68指向41,45变成头结点 -> 45 -> 18 -> 55 -> 68 -> 41 -> 43 -> 5 -> 28 -> 80 -> 67 // …… -> 41 -> 45 -> 18 -> 55 -> 68 -> 43 -> 5 -> 28 -> 80 -> 67 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68 -> 5 -> 28 -> 80 -> 67 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68 -> 28 -> 80 -> 67 -> 28 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68 -> 80 -> 67 -> 80 -> 28 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68 -> 67 // current 68 没有后继,反转结束 -> 67 -> 80 -> 28 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68 反转L后 -> 67 -> 80 -> 28 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68
最后附上完整代码,反转有两个函数。
- 方法1,current始终保持在第一位,pnext与prev遍历并完成交换。
- 方法2,current始终是原链表的第一个数,然后把pnext不断移动到首位。
有两个方法可以实现单链表的反转:
方法一:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node *next;
}Node;
Node *head,*p;
Node * ReverseLink(Node *head)
{
Node *p1, *p2, *p3;
if(head==NULL || head->next==NULL)
return head;
p1=head, p2=p1->next;
while(p2)
{
p3=p2->next;
p2->next=p1;
p1=p2;
p2=p3;
}
head->next=NULL;
head=p1;
return head;
}
void CreateList(int n)
{
Node *q;
int i;
printf("Input %2d data: ",n);
head=(Node *)malloc(sizeof(Node));
q=head;
scanf("%d",&q->data);
for(i=2;i<=n;i++)
{
q->next=(Node *)malloc(sizeof(Node));
q=q->next;
scanf("%d",&q->data);
}
q->next=NULL;
}
void PrintList()
{
Node *q;
q=head;
while (q!=NULL)
{
printf("%-8d",q->data);
q=q->next;
}
printf("
");
}
void main()
{
CreateList(5);
PrintList();
head=ReverseLink(head);
PrintList();
}
方法二:
#include <iostream>
#include <assert.h>
using namespace std;
struct LNode{
char data;
LNode * next;
};
LNode * initList()
{
LNode *head=new LNode;
LNode *curPtr, *newPtr;
curPtr=head;
int i=0;
char ch='A';
while(i++<10)
{
newPtr=new LNode;
newPtr->data=ch++;
curPtr->next=newPtr;
curPtr=newPtr;
}
newPtr->next=NULL;
return head;
}
void print(LNode *head)
{
LNode *ptr=head->next;
while(ptr != NULL)
{
cout << ptr->data << " ";
ptr=ptr->next;
}
cout << endl;
}
void reverse(LNode *head)
{
assert(head != NULL && head->next != NULL);
LNode *ptr=head->next->next;
head->next->next=NULL;
while(ptr != NULL)
{
LNode *tmp=ptr->next;
ptr->next=head->next;
head->next=ptr;
ptr=tmp;
}
}
int main()
{
LNode *head=initList();
print(head);
cout << "After reverse: " << endl;
reverse(head);
print(head);
system("PAUSE");
return 0;
}