面试-反转链表

面试-反转链表

面试题目

经典算法题目 : 反转单链表 reverse list

对于一个普通的单链表,可以定义成结构体形式:

// 定义链表节点
struct ListNode
{
  int val;
  ListNode * next;
}

请写一个函数实现单链表的翻转

题目解析

一般来说,单链表的反转有递归和非递归的方式来进行实现, 此处的反转实现 参考反转链表图示 其中递归方式的实现比较难以理解, 进攻参考

递归方式
// 递归方式
ListNode * ReverseList_re(ListNode * head)
{
    // 如果空链表或者 单节点链表
    if(head ==nullptr || head->next == nullptr)
        return head;

    // 依次进行每个节点的执行
    ListNode * new_head = ReverseList_re(head->next);

    // 对于每一个节点 反转前后实现
    head->next->next = head;
    head->next = nullptr;

    return new_head;
}
非递归方式
  1.  
  2. // ref:[链表反转图文讲解](https://blog.csdn.net/FX677588/article/details/72357389) 
  3. // 非递归方式 
  4. ListNode * ReverseList(ListNode *head) 
  5. { 
  6. // 如果空链表或者 单节点链表 
  7. if(head == nullptr || head->next == nullptr) 
  8. return head; 
  9.  
  10. // 新建两个节点 P用来遍历head, new_head 为新链表的头 
  11. ListNode *p = head, *new_head = nullptr; 
  12.  
  13. while(p != nullptr) 
  14. { 
  15. ListNode * tmp = p->next; // 存储当前节点的指针位置 
  16. p->next = new_head; // 将当前节点指向新节点的头 
  17. new_head = p; // 新链表 移动头 
  18. p = tmp; // 旧链表指针移动 
  19. } 
  20.  
  21. // 返回新的节点值 
  22. return new_head; 
  23. } 
  24.  
  25. // 不返回操作 非递归 反转链表 
  26. void ReverseList2(ListNode * &head) 
  27. { 
  28. // 如果空链表或者 单节点链表 
  29. if(head == nullptr || head->next == nullptr) 
  30. return ; 
  31.  
  32. // 新建两个节点 P用来遍历head, new_head 为新链表的头 
  33. ListNode *p = head, *new_head = nullptr; 
  34.  
  35. while(p != nullptr) 
  36. { 
  37. ListNode * tmp = p->next; // 存储当前节点的指针位置 
  38. p->next = new_head; // 将当前节点指向新节点的头 
  39. new_head = p; // 新链表 移动头 
  40. p = tmp; // 旧链表指针移动 
  41. } 
  42.  
  43. // 复用 head 指针 
  44. head = new_head; 
  45. } 
  46.  

附加内容

测试工程 实现

// 链表操作类的 测试
#include <iostream>

using namespace std;

// 定义链表节点 值和指针
struct ListNode
{
    int val;
    ListNode *next;
};

// 定义链表的 增 删 查 改
// CRUD

// 创建链表 // 根据首指针 创建首指针节点
void CreateHead(ListNode *head, int data)
{

}

// 在链表尾头部添加新节点
void AddNode(ListNode * & head,int data)
{
    // 创建 新节点 //申请空间
    ListNode *p = (ListNode*) malloc(sizeof(ListNode));
    p->val = data;
    p->next = nullptr;

    // 如果是一个空链表 直接赋值到head 然后返回

    if(head == nullptr)
    {
        head = p;
        return ;
    }

    // 指向新节点 返回新节点
    p->next = head;
    head = p;
}

// 删除节点

// 查找节点

// 更新节点值

// 打印List 所有节点值
void PrintList(ListNode *head)
{
    // 从某个节点开始 打印所有节点的值
    ListNode *p = head; // 临时节点 便于输出 避免 改变 head 值
    while(p != nullptr)
    {
        // cout<<(long)p%65536<<":";        // 输出指针的一个 数字表示
        cout<<p->val<<"->";
        p = p->next;
    }
    cout<<"NULL"<<endl;
}


// 反转链表
// ref:[链表反转图文讲解](https://blog.csdn.net/FX677588/article/details/72357389)
// 非递归方式
ListNode * ReverseList(ListNode *head)
{
    // 如果空链表或者 单节点链表
    if(head == nullptr || head->next == nullptr)
        return head;

    // 新建两个节点 P用来遍历head, new_head 为新链表的头
    ListNode *p = head, *new_head = nullptr;

    while(p != nullptr)
    {
        ListNode * tmp = p->next;   // 存储当前节点的指针位置
        p->next = new_head;         // 将当前节点指向新节点的头
        new_head = p;               // 新链表 移动头
        p = tmp;                    // 旧链表指针移动
    }

    // 返回新的节点值
    return new_head;
}

// 不返回操作  非递归 反转链表
void ReverseList2(ListNode * &head)
{
    // 如果空链表或者 单节点链表
    if(head == nullptr || head->next == nullptr)
        return ;

    // 新建两个节点 P用来遍历head, new_head 为新链表的头
    ListNode *p = head, *new_head = nullptr;

    while(p != nullptr)
    {
        ListNode * tmp = p->next;   // 存储当前节点的指针位置
        p->next = new_head;         // 将当前节点指向新节点的头
        new_head = p;               // 新链表 移动头
        p = tmp;                    // 旧链表指针移动
    }

    // 复用 head  指针
    head = new_head;
}

// 递归方式
ListNode * ReverseList_re(ListNode * head)
{
    // 如果空链表或者 单节点链表
    if(head ==nullptr || head->next == nullptr)
        return head;

    // 依次进行每个节点的执行
    ListNode * new_head = ReverseList_re(head->next);

    // 对于每一个节点 反转前后实现
    head->next->next = head;
    head->next = nullptr;

    return new_head;
}


// 主函数 测试 demo 
#define LENGTH 20 
int main(void)
{
    ListNode *head  = nullptr;

    // 生成随机链表
    for(int i=0;i<LENGTH;++i)
        AddNode(head,rand()%LENGTH);
    PrintList(head);

    // 反转链表 并输出
    head = ReverseList(head);
    PrintList(head);

    // 反转链表 并输出
    ReverseList2(head);
    PrintList(head);

    // 反转链表 并输出 递归实现
    head = ReverseList_re(head);
    PrintList(head);

    // system("pause");
    return 0;
}

posted @ 2020-03-25 21:31  SChen1024  阅读(112)  评论(0编辑  收藏  举报