剑指offer-05:从尾到头打印链表

来源:互联网 发布:西安长臂猿网络 编辑:程序博客网 时间:2024/06/17 17:28

输入一个链表的头结点,从尾到头反过来打印每个结点的值

首先复习下链表的基础:

struct ListNode{    int m_value;    ListNode * p_next;};

《数据结构》书上搞了头结点,即new了一个数值为空的结点,指向首结点。

而下面代码直接从首结点(左)开始。

开始还有些纠结,后来想明白了无论哪种都是可以的,只要搞清楚道理,操作正确即可。实践发现,搞个头结点还是好些:有些操作就是统一的,否则要考虑首结点和后面结点分开处理。

这里写图片描述

// 插入结点void AddToTail(ListNode ** pHead, int value){    ListNode * pNew = new ListNode();    pNew->m_value = value;    pNew->p_next = nullptr;    if (*pHead == nullptr)        *pHead = pNew;    else    {        ListNode * pNode = *pHead;        while (pNode->p_next != nullptr)        {            pNode = pNode->p_next;        }        pNode->p_next = pNew;    }}

插入时,先申请空间搞个新结点。然后看如果表还未建,则该结点为首结点,p指向首结点。若已建,则找到尾部,修改null指向新结点。

void Delete(ListNode ** pHead, int value){    if (pHead == nullptr || *pHead == nullptr)        return;    // 如果是第一个结点,*pHead指向第二结点    ListNode * pToDelete = *pHead;    if (pToDelete->m_value == value)    {        *pHead = (*pHead)->p_next;    }    // 不是第一个则迭代往后找    else     {        while (pToDelete->p_next != nullptr && pToDelete->p_next->m_value != value)        {            pToDelete = pToDelete->p_next;        }        // 找到了该结点        if (pToDelete->p_next != nullptr && pToDelete->p_next->m_value == value)        {            ListNode * ptmp = pToDelete;            pToDelete = pToDelete->p_next;            ptmp->p_next = ptmp->p_next->p_next;        }        // 没找到返回        else        {            cout << "no this value" << endl;            return;        }    }    // 此处肯定是找到可删    delete pToDelete;    pToDelete = nullptr;}// 测试输出int main(){    ListNode * List = nullptr;    AddToTail(&List, 3); // 3    AddToTail(&List, 4); // 3 -> 4    AddToTail(&List, 5); // 3 -> 4 -> 5    ListNode * pNode = List;    while (pNode != nullptr)    {        cout << pNode->m_value;        pNode = pNode->p_next;    }    Delete(&List, 5);    pNode = List;    while (pNode != nullptr)    {        cout << pNode->m_value;        pNode = pNode->p_next;    }    return 0;}

再来看本题目:实现结点逆序输出。

  • 思路1:遍历结点压栈,栈输出
  • 思路2:递归输出后面结点,再输出该结点本身
// 遍历结点压栈void printReverseStack(ListNode * p){    stack<ListNode *> nodes; // #include <stack>    while (p != nullptr)    {        nodes.push(p);        p = p->p_next;    }    while (!nodes.empty())    {        p = nodes.top();        cout << p->m_value << "->";        nodes.pop();    }}
// 递归打印输出void printReverseRecursive(ListNode * p){    if (p != nullptr)    {        // 当尾结点时返回        if (p->p_next != nullptr)            printReverseRecursive(p->p_next);        // 打印子序列的第一个结点        cout << p->m_value << "->";    }}// 测试输出ListNode * pNode = List;printReverseStack(pNode);printReverseRecursive(pNode);
原创粉丝点击