单链表的翻转是一道很基本的算法题。
typedef struct LNode
{
int data;
struct LNode *next;
}LNode, *LinkedList;
方法1:将单链表储存为数组,然后按照数组的索引逆序进行反转。
方法2:重新建立一个单链表newList,每次将list中的第一个结点放到newList(头结点)后面
方法3:使用三个指针遍历单链表,逐个链接点进行反转。
方法1和方法2的问题是浪费空间。一般方法3较为常用,时间复杂度为0(n)。
方法1:比较简单可以参考C字符串数组的反转 http://blog.csdn.net/acpchenpeng/article/details/50162359
方法2:此方法注意新链表的头结点初始化。
LinkedList ReverseSinglyLinkedList(LinkedList list)
{
LinkedList newList; //新链表的头结点
LNode *tmp; //指向list的第一个结点,也就是要摘除的结点
//参数为空或者内存分配失败则返回NULL
if (list == NULL || (newList = (LinkedList)malloc(sizeof(LNode))) == NULL)
{
return NULL;
}
//初始化newList(头结点)
newList->data = list->data;
newList->next = NULL;
//依次将list的第一个结点放到newList的第一个结点位置
while (list->next != NULL)
{
tmp = newList->next; //保存newList中的后续结点
newList->next = list->next; //将list的第一个结点放到newList中
list->next = list->next->next; //从list中摘除这个结点
newList->next->next = tmp; //恢复newList中后续结点的指针
}
//原头结点应该释放掉,并返回新头结点的指针
free(list);
return newList;
}
方法3:
Node * ReverseList(Node *head)
{
Node *p1,*p2,*p3;
if(head==NULL||*head==NULL)
return head;
p1=head;
p2=p1->next;
while(p2) //注意条件
{
p3=p2->next; //每次交换两个结点(要改变p2->next的指针,所以必须先保留p2->next)
p2->next=p1;
p1=p2; //循环往后
p2=p3;
}
head->next=NULL; //原先的head已经变成tail,别忘了置空,只有到这步才能置空
head=p1; //p1变成头结点
return head;
}