#数据结构与算法学习笔记#剑指Offer14:反转链表+非递归思路与递归思路+PTA升级版+测试用例(Java、C/C++)

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一秒钟。留个言点个赞呗,谢谢你#

猜你喜欢

转载自blog.csdn.net/qq_20304723/article/details/81563777
今日推荐