[算法练习] 反转链表

题目说明:

输入一个链表的头结点,反转该链表,并返回反转后链表的头结点。链表结点定义如下:
struct ListNode
{
     int m_nKey;
     ListNode* m_pNext;
};

程序代码:

#include <gtest/gtest.h>
#include <vector>
using namespace std;

struct ListNode
{
    int m_nKey;
    ListNode* m_pNext;
};

ListNode* ReverseLinkedList(ListNode* pHead)
{
    ListNode* pNext = pHead;
    ListNode* pPrev = NULL;

    while (pNext)
    {
        ListNode* pTemp = pNext->m_pNext;
        pNext->m_pNext = pPrev;
        pPrev = pNext;
        pNext = pTemp;
    }

    return pPrev;
}

// 递归方式实现
ListNode* ReverseLinkedList2(ListNode* pHead, ListNode* pPrev = NULL)
{
    ListNode* pReversedHead = pHead;
    if (pHead)
    {
        if (pHead->m_pNext)
        {
            pReversedHead = ReverseLinkedList2(pHead->m_pNext, pHead);
        }

        pHead->m_pNext = pPrev;
    }

    return pReversedHead;
}

ListNode* CreateLinkedList(const string& data)
{
    ListNode* pHead = NULL;
    ListNode* pLast = NULL;
    for (int i=0; i<data.size(); ++i)
    {
        ListNode* pNext = new ListNode();
        pNext->m_nKey = data[i];
        pNext->m_pNext = NULL;

        if (!pHead)
        {
            pHead = pLast = pNext;
        }
        else
        {
            pLast->m_pNext = pNext;
            pLast = pNext;
        }
    }

    return pHead;
}

void ReleaseLinkedList(ListNode* pHead)
{
    ListNode* pTemp = NULL;
    while (pHead)
    {
        pTemp = pHead;
        pHead = pHead->m_pNext;
        delete pTemp;
    }
}

string ConvertLinkedList(ListNode* pHead)
{
    string strValue;
    while (pHead)
    {
        strValue+= (char)pHead->m_nKey;
        pHead = pHead->m_pNext;
    }

    return strValue;
}

TEST(Pratices, tReverseLinkedList)
{
    // NULL
    ListNode* pHead = NULL;
    pHead = ReverseLinkedList(pHead);
    ASSERT_TRUE(!pHead);

    // a -> a
    pHead = CreateLinkedList("a");
    pHead = ReverseLinkedList(pHead);
    ASSERT_EQ(ConvertLinkedList(pHead),"a");
    ReleaseLinkedList(pHead);

    // ab -> ba
    pHead = CreateLinkedList("ab");
    pHead = ReverseLinkedList(pHead);
    ASSERT_EQ(ConvertLinkedList(pHead),"ba");
    ReleaseLinkedList(pHead);

    // abcedfg -> gfdecba
    pHead = CreateLinkedList("abcedfg");
    pHead = ReverseLinkedList(pHead);
    ASSERT_EQ(ConvertLinkedList(pHead),"gfdecba");
    ReleaseLinkedList(pHead);

    /// 递归逆序测试
    pHead = NULL;
    pHead = ReverseLinkedList2(pHead);
    ASSERT_TRUE(!pHead);

    // a -> a
    pHead = CreateLinkedList("a");
    pHead = ReverseLinkedList2(pHead);
    ASSERT_EQ(ConvertLinkedList(pHead),"a");
    ReleaseLinkedList(pHead);

    // ab -> ba
    pHead = CreateLinkedList("ab");
    pHead = ReverseLinkedList2(pHead);
    ASSERT_EQ(ConvertLinkedList(pHead),"ba");
    ReleaseLinkedList(pHead);

    // abcedfg -> gfdecba
    pHead = CreateLinkedList("abcedfg");
    pHead = ReverseLinkedList2(pHead);
    ASSERT_EQ(ConvertLinkedList(pHead),"gfdecba");
    ReleaseLinkedList(pHead);
}
时间: 2024-12-21 15:17:06

[算法练习] 反转链表的相关文章

数据结构与算法(c++)——反转链表

算法概述:要求实现将一条单向链表反转并考虑时间复杂度. 算法分析: 数组法(略): 将列表元素逐个保存进数组,之后再逆向重建列表 点评:实现逻辑最简单,需要额外的内存开销. 移动指针: 通过三个指针逐个从链表头开始逐一反转链表元素的指针 点评:不需要额外的内存开销,会改变原始链表. 递归: 以递归的方式首先找到链表尾部,再逐一反转指针 点评:不需要额外的内存开销,不会改变原始链表. 算法实现: 构建链表结构 /* 节点结构 */ struct NODE { int data; struct NO

算法:反转链表。

题目描述 输入一个链表,反转链表后,输出新链表的表头. 思路 定义当前head,前序节点pre,后续节点next:依次遍历所有节点,将所有节点的next指向前一个节点. package LG.nowcoder; /** * @Author liguo * @Description 输入一个链表,反转链表后,输出新链表的表头. * 思路:定义当前head,前序节点pre,后续节点next: * 依次遍历所有节点,将所有节点的next指向前一个节点 * @Data 2018-08-13 23:24

算法-leetcode-206.反转链表

题目链接:反转链表 主要是弄清楚几个变量该怎么交换值即可: c语言版本: /** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* reverseList(struct ListNode* head){ //可以在开始的时候处理下空链表和只有一个元素的情况,直接返回就行,循环也能处理这两种情况,所以就省掉了对应的

链表面试题(一):反转链表的算法实现

关于链表的考察 链表是面试里面经常涉及到的考点,因为链表的结构相比于Hashmap.Hashtable.Concurrenthashmap或者图等数据结构简单许多,对于后者更多面试的侧重点在于其底层实现.比如Hashmap中Entry<k,v>等操作.如何扩容.容量的设定等.链表的考察更侧重于代码的书写和思路的形成.虽然说,链表的结构简单,但是涉及到指针的操作,容易引申出一些挑战性的考题,其中也牵涉到诸多小的细节的考虑,更能看出代码书写的能力和功底. 面试题:反转链表 题目:定义一个函数,输入

笔试算法题(13):反转链表 &amp; 左旋转字符串

出题:反转链表(递归和非递归解法): 分析:有递归跟非递归实现,注意对原始链表头节点的处理,因为其他节点都指向下一个节点,其需要指向NULL: 解题: 1 struct Node { 2 int v; 3 Node *next; 4 }; 5 Node* NonRecursiveListReverse(Node *head) { 6 if(head == NULL) return NULL; 7 Node *previous=NULL, *current=head, *temp=NULL; 8

C++算法之 反转单链表

题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点,链表节点定义为: struct ListNode { int    m_nValue; ListNode* m_pNext; }; 算法思路: 链表  1-->2-->3-->4-->5 建立一个 pPrev节点,而且为空节点:  pPrev = NULL:再建立一个节点pNode = pHead; 再建立第三个节点pNext = pNode->m_pNext; pNext的作用:用来保存pNode

反转链表算法Java实现

之前遇到反转链表的算法,比较晦涩难解,但其实挺简单的. 目标:将一个顺序链表反转. 思路:用三个辅助节点,每次实现一个节点的指向反转,即他的后继变为他的前驱. 三个辅助节点: p  q  r  按顺序分别指向 节点0,1,2, 然后一次次移动,指向1,2,3 : 2,3,4...... 算法分为三部分: 第一部分:初始化部分: q是中心节点,是每次反转的节点,于是q是由函数参数传入的,前面的节点p一个是null,后面的节点r是q的后继节点q.next 第二部分:循环部分 分为两个操作: 1.反转

反转链表算法题

反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶:你可以迭代或递归地反转链表.你能否用两种方法解决这道题? 解决方案 方法一:迭代 假设存在链表 1 → 2 → 3 → Ø,我们想要把它改成 Ø ← 1 ← 2 ← 3. 在遍历列表时,将当前节点的 next 指针改为指向前一个元素.由于节点没有引用其上一个节点,因此必须事先存储其前一个元素.在更改引用之前,还需要另一个

一步一步写算法(之链表逆转)

原文:一步一步写算法(之链表逆转) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 链表逆转是面试环境中经常遇到的一道题目,也是我们在实际开发中可能会遇到的开发需求.和线性逆转不一样,单向链表的节点需要一个一个进行处理.为了显示两者之间的区别,我们分别对线性内存和链表进行逆转: (1)普通连续内存数据的反转分析 STATUS normal_revert(int array[], int length) { int* pData ; int