QT/C++面试题记录(1)链表倒序

前言

本系列本意是基于面试而记录的一些有复习意义的题目,算是个人向的一个错题集。

问题

上周面试遇到链表类的题目,出了两个函数题,分别是链表节点删除和链表倒序。

我链表倒序死活没想出来,因为确实有点绕,故这篇文章重点记录一下链表倒序。

一、链表倒序算法

先定义链表节点结构体:

cpp 复制代码
// 链表节点
struct ListNode{
    int data;
    ListNode * next;
    ListNode(int val) : data(val), next(nullptr) {}
};

链表倒序算法:

cpp 复制代码
// 链表倒转
ListNode* reverseList(ListNode* head) {
    ListNode* prev = nullptr;
    ListNode* curr = head;

    while (curr != nullptr) {
        ListNode* nextTemp = curr->next; // 1. 暂存下一个节点,防止断链
        curr->next = prev;               // 2. 反转当前节点的指针方向
        prev = curr;                     // 3. 整体向前推进指针
        curr = nextTemp;
    }
    return prev; // 循环结束后,prev 就是新的头节点
}

二、链表常见操作的完整测试代码

以下测试代码中,包含了链表遍历、插入、删除、倒序等常见的操作。

cpp 复制代码
#include "mainwindow.h"

#include <QApplication>
#include <QDebug>

// 链表节点
struct ListNode{
    int data;
    ListNode * next;
    ListNode(int val) : data(val), next(nullptr) {}
};

// 遍历
void fun_1(ListNode * head)
{
    ListNode * cur = head;

    while(cur){
        qDebug()<< "cur" << cur->data;
        cur = cur->next;
    }
    qDebug()<<"fun_1 finish ... ";
}

// 插入(在某个特定数据节点后插入)
ListNode * insertNode(ListNode * head, int data_after, int data_new){
    ListNode * newNode = new ListNode(data_new);

    ListNode * cur = head;

    if(!cur){
        head = newNode;
        return head;
    }

    if(cur->data == data_after){
        newNode->next = cur->next;
        cur->next = newNode;
        return head;
    }

    while(cur->next){

        if(cur->next->data == data_after){
            newNode->next = cur->next->next;
            cur->next->next = newNode;

            return head;
            break;
        }

        cur= cur->next;
    }

    // not found
//    cur->next = newNode;
    delete newNode;
    return head;
}

// 删除节点
ListNode * deleteNode(ListNode * head, int key){

    if(!head) {
        return nullptr;
    }

    if(head->data  == key){
        ListNode * tempNode = head;
        head = head->next;
        delete tempNode;
        return head;
    }

    ListNode* prev = nullptr;
    ListNode* curr = head;
    while (curr != nullptr && curr->data != key) {
        prev = curr;
        curr = curr->next;
    }

    if(!curr){
        //not found
        return head;
    }

    prev->next = curr->next;
    delete curr;
    return head;
}

// 链表倒转
ListNode* reverseList(ListNode* head) {
    ListNode* prev = nullptr;
    ListNode* curr = head;

    while (curr != nullptr) {
        ListNode* nextTemp = curr->next; // 1. 暂存下一个节点,防止断链
        curr->next = prev;               // 2. 反转当前节点的指针方向
        prev = curr;                     // 3. 整体向前推进指针
        curr = nextTemp;
    }
    return prev; // 循环结束后,prev 就是新的头节点
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    ListNode* head = new ListNode(1);
    head->next = new ListNode(2);
    head->next->next = new ListNode(3);
    head->next->next->next = new ListNode(4);
    head->next->next->next->next = new ListNode(5);

    fun_1(head);

    head = insertNode(head, 2, 8);
    fun_1(head);

    head = deleteNode(head, 4);
    fun_1(head);

    head = reverseList(head);
    fun_1(head);

    return a.exec();
}

运行结果: