2018.8.10
这道题用非递归方法需要3个指针做,一个指向后一个结点(later),一个指向中间结点(temp),一个指向前一个结点(front)。每次反转前front记录下一结点位置,temp与later进行反转(此时temp与front之间的指针会断开),然后later前移至temp位置,temp前移至front位置。循环进行之后的反转。反转结束后将最后两个结点反向,并去掉最开始两个结点的自循环。
代码实现过程的注意点:1.输入head==null,2.输入链表只有一个结点,3.最后两个结点忘记操作,4.头两个结点未去除自循环
另外还有一种递归思路可以从链表尾部不断向前翻转,以此解决链表不能回溯的缺点。
链表反转题还有一道升级版,要求每隔k个元素进行一次反转,比这个要复杂得多。很早之前做过,可以参考之前的文章:
#数据结构与算法学习笔记#PTA6:链表翻转升级版(C/C++)
题目描述
输入一个链表,反转链表后,输出新链表的表头。
Java实现代码:
/**
*
* @author ChopinXBP
* 输入一个链表,反转链表后,输出新链表的表头。
*
*
*/
public class ReverseList_15 {
public static class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ListNode head = new ListNode(0);
ListNode p = head;
for (int i = 0; i < 5; i++) {
ListNode newnode = new ListNode(i + 1);
p.next = newnode;
p = p.next;
}
p = head;
System.out.print("原序列: ");
for (int i = 0; i < 6; i++) {
System.out.print(p.val);
p = p.next;
}
p = Solution(head);
System.out.print("\n翻转序列: ");
for (int i = 0; i < 6; i++) {
System.out.print(p.val);
p = p.next;
}
}
public static ListNode Solution(ListNode head) {
if (head == null)
return null;
else if (head.next == null)
return head;
ListNode temp = head.next; //指向前一个结点
ListNode later = head; //指向后一个结点
//每次循环先定义一个former指向下一个结点,将temp与later所指结点反向,并依次前进later与temp
while (temp.next != null) {
ListNode former = temp.next; //指向下一个结点
temp.next = later;
later = temp;
temp = former;
}
temp.next = later; //将最后两个结点反向
head.next = null; //去掉头两个结点的自循环
return temp;
}
}
C++实现示例:
//第一种方法是:非递归方法
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead==NULL) return NULL;//注意程序鲁棒性
ListNode* pNode=pHead;//当前指针
ListNode* pReverseHead=NULL;//新链表的头指针
ListNode* pPrev=NULL;//当前指针的前一个结点
while(pNode!=NULL){//当前结点不为空时才执行
ListNode* pNext=pNode->next;//链断开之前一定要保存断开位置后边的结点
if(pNext==NULL)//当pNext为空时,说明当前结点为尾节点
pReverseHead=pNode;
pNode->next=pPrev;//指针反转
pPrev=pNode;
pNode=pNext;
}
return pReverseHead;
}
}
//第二种方法是:递归方法
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
//如果链表为空或者链表中只有一个元素
if(pHead==NULL||pHead->next==NULL) return pHead;
//先反转后面的链表,走到链表的末端结点
ListNode* pReverseNode=ReverseList(pHead->next);
//再将当前节点设置为后面节点的后续节点
pHead->next->next=pHead;
pHead->next=NULL;
return pReverseNode;
}
};
测试代码:
// ====================测试代码====================
ListNode* Test(ListNode* pHead)
{
printf("The original list is: \n");
PrintList(pHead);
ListNode* pReversedHead = ReverseList(pHead);
printf("The reversed list is: \n");
PrintList(pReversedHead);
return pReversedHead;
}
// 输入的链表有多个结点
void Test1()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
ListNode* pReversedHead = Test(pNode1);
DestroyList(pReversedHead);
}
// 输入的链表只有一个结点
void Test2()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pReversedHead = Test(pNode1);
DestroyList(pReversedHead);
}
// 输入空链表
void Test3()
{
Test(NULL);
}
int _tmain(int argc, _TCHAR* argv[])
{
Test1();
Test2();
Test3();
return 0;
}
#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#