C++面试宝典第4题:合并链表

news2024/11/25 15:19:40

题目

        有一个链表,其节点声明如下:

struct TNode
{
    int nData;
    struct TNode *pNext;
    TNode(int x) : nData(x), pNext(NULL) {}
};

        现给定两个按升序排列的单链表pA和pB,请编写一个函数,实现这两个单链表的合并。合并后,仍然按升序进行排列。比如:单链表pA为1->3->5->6->8,单链表pB为2->3->7,则合并后返回的链表为1->2->3->3->5->6->7->8。函数的声明如下:

          TNode *MergeList(TNode *pA, TNode *pB);

解析

        这道题主要考察应聘者对链表等数据结构的理解能力,在面试中比较常见。一般有两种解法:一种是使用递归函数来实现,另一种是使用链表遍历来实现。

        先来看第一种解法,使用递归函数来实现。当链表pA为NULL时,直接返回链表pB即可。当链表pB为NULL时,直接返回链表pA即可。当链表pA和pB均不为NULL时,则比较链表首部的元素,若pA->nData小于pB->nData,则返回pA,并让pA->pNext指向递归函数MergeList(pA->pNext, pB)的返回值。下面,我们给出了这道题的示例代码。

#include<iostream>
using namespace std;

struct TNode
{
    int nData;
    struct TNode *pNext;
    TNode(int x) : nData(x), pNext(NULL) {}
};

// 插入新节点到链表尾部
TNode *AppendNode(TNode *pTail, int nData)
{  
    TNode *pNodeNew = new TNode(nData);
    pTail->pNext = pNodeNew;
    return pNodeNew;
}

// 打印链表
void PrintList(TNode *pNode)
{
    while (pNode != NULL)
    {
        cout << pNode->nData;
        pNode = pNode->pNext;
        if (pNode != NULL)
        {
            cout << "->";
        }
        else
        {
            cout << endl;
        }
    }
}

// 合并两个链表
TNode *MergeList(TNode *pA, TNode *pB)
{  
    if (pA == NULL)
    {
        return pB;
    }

    if (pB == NULL)
    {
        return pA;
    }

    if (pA->nData < pB->nData)
    {
        pA->pNext = MergeList(pA->pNext, pB);
        return pA;
    }
    else
    {
        pB->pNext = MergeList(pA, pB->pNext);
        return pB;
    }
}  

int main()
{
    TNode *pA = new TNode(1);
    TNode *pTail = AppendNode(pA, 3);
    pTail = AppendNode(pTail, 5);
    pTail = AppendNode(pTail, 6);
    pTail = AppendNode(pTail, 8);
    // 输出:1->3->5->6->8
    PrintList(pA);

    TNode *pB = new TNode(2);
    pTail = AppendNode(pB, 3);
    pTail = AppendNode(pTail, 7);
    // 输出:2->3->7
    PrintList(pB);

    TNode *pResult = MergeList(pA, pB);
    // 输出:1->2->3->3->5->6->7->8
    PrintList(pResult);
    return 0;
}

        当然,递归函数也有其缺点:当链表中的元素较多,递归的层级较多时,可能会导致堆栈溢出。

        接下来,我们来看第二种解法,使用链表遍历来实现。首先,当链表pA和pB其中一个为NULL时,直接返回另一个链表即可。接下来,我们创建了一个新的临时节点,作为新链表的头和尾,并遍历链表pA和pB。在遍历过程中,如果pA->nData小于pB->nData,则将pA作为新链表尾部的下一个节点,并遍历新链表尾部和pA的下一个节点;如果pA->nData不小于pB->nData,则将pB作为新链表尾部的下一个节点,并遍历新链表尾部和pB的下一个节点。循环遍历完成后,由于链表pA和pB不一样长,因此,需要检查链表pA和pB是否为NULL。若不为NULL,则将对应链表放到新链表尾部。最后,我们返回了新建节点的下一个节点作为合并后的链表首节点,并删除了新建的临时节点。具体实现,可参考如下的示例代码。

#include<iostream>
using namespace std;

struct TNode
{
    int nData;
    struct TNode *pNext;
    TNode(int x) : nData(x), pNext(NULL) {}
};

// 插入新节点到链表尾部
TNode *AppendNode(TNode *pTail, int nData)
{  
    TNode *pNodeNew = new TNode(nData);
    pTail->pNext = pNodeNew;
    return pNodeNew;
}

// 打印链表
void PrintList(TNode *pNode)
{
    while (pNode != NULL)
    {
        cout << pNode->nData;
        pNode = pNode->pNext;
        if (pNode != NULL)
        {
            cout << "->";
        }
        else
        {
            cout << endl;
        }
    }
}

// 合并两个链表
TNode *MergeList(TNode *pA, TNode *pB)
{
    if (pA == NULL)
    {
        return pB;
    }

    if (pB == NULL)
    {
        return pA;
    }

    TNode *pResult = new TNode(-1);
    TNode *pTail = pResult;
    while (pA && pB)
    {
        if (pA->nData < pB->nData)
        {
            pTail->pNext = pA;
            pTail = pTail->pNext;
            pA = pA->pNext;
        } 
        else
        {
            pTail->pNext = pB;
            pTail = pTail->pNext;
            pB = pB->pNext;
        }
    }

    if (pA)
    {
        pTail->pNext = pA;
    }

    if (pB)
    {
        pTail->pNext = pB;
    }

    TNode *pTemp = pResult;
    pResult = pResult->pNext;
    delete pTemp;
    return pResult;
}

int main()
{
    TNode *pA = new TNode(1);
    TNode *pTail = AppendNode(pA, 3);
    pTail = AppendNode(pTail, 5);
    pTail = AppendNode(pTail, 6);
    pTail = AppendNode(pTail, 8);
    // 输出:1->3->5->6->8
    PrintList(pA);

    TNode *pB = new TNode(2);
    pTail = AppendNode(pB, 3);
    pTail = AppendNode(pTail, 7);
    // 输出:2->3->7
    PrintList(pB);

    TNode *pResult = MergeList(pA, pB);
    // 输出:1->2->3->3->5->6->7->8
    PrintList(pResult);
    return 0;
}

总结

        链表是一种常见的数据结构,它通过指针链接一系列的节点。通过这道题,我们学习了链表的数据结构,以及链表合并的操作。

        另外,我们还为你留了一些课后的拓展作业,快来试一试吧!

        1、给定一个单向链表,判断链表中是否有环。

        2、给定一个单向链表的头节点,写一个函数将其反转。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1301388.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

架构设计系列之基础:初探软件架构设计

11 月开始突发奇想&#xff0c;想把自己在公司内部做的技术培训、平时的技术总结等等的内容分享出来&#xff0c;于是就开通了一个 Wechat 订阅号&#xff08;灸哥漫谈&#xff09;&#xff0c;开始同步发送内容。 今天&#xff08;12 月 10 日&#xff09;也同步在 CSDN 上开通…

银行数字化转型导师坚鹏:兴业生活APP运营之道

基于招商银行案例研究的兴业生活APP运营之道培训圆满结束 ——线上引流平台流量经营与变现 兴业银行股份有限公司&#xff08;简称“兴业银行”&#xff09;成立于1988年8月&#xff0c;2022年总资产9.27万亿元&#xff0c;是经国务院、中国人民银行批准成立的首批股份制商业银…

Truffle的基础语法与js测试语法

truffle编译 truffle compiletruffle部署 truffle migratetruffle测试 使用test文件夹下的所有文件测试 truffle test使用单个文件 测试 truffle test 文件所在位置

实现Django Models的数据mock

目录 一、创建测试数据 二、使用随机数据 三、使用第三方库生成数据 四、编写测试用例 五、总结 在 Django 中&#xff0c;Model 是用于定义数据库表的结构的类。有时候&#xff0c;我们需要在测试或者开发过程中&#xff0c;模拟 Model 的数据&#xff0c;而不是直接从数…

Python 数据库操作SQL基础

文章目录 SQL 基础数据库和表的创建数据的插入、查询、更新和删除索引、连接和子查询 Python 中的数据库操作关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Pytho…

Bluejay--控制多旋翼无刷电机的数字 ESC 固件

前言 Bluejay中文意思是冠蓝鸦&#xff0c;一种雀形目鸦科冠蓝鸦属的鸟类。在这里是用于控制多旋翼无刷电机的数字 ESC 固件。 基于BLHeli_S修订版 16.7 Bluejay 的目标是成为 BLHeli_S 的开源继承者&#xff0c;通过 Busy Bee MCU 对 ESC 进行多项改进。 特点 数字信号协议&…

YOLOv7独家原创改进:轻量化自研设计双卷积,重新设计backbone和neck卷积结构,完成涨点且计算量和参数量显著下降

💡💡💡本文自研创新改进:双卷积由组卷积和异构卷积组成,执行 33 和 11 卷积运算代替其他卷积核仅执行 11 卷积,YOLOv7 Conv,从而轻量化YOLOv7-tiny 收录YOLOv7原创自研 https://blog.csdn.net/m0_63774211/category_12511937.html 💡💡💡全网独家首发创新(原…

ubuntu-更改镜像源-系统初始化-安装Clion-C++编译环境-Java安装

文章目录 1.镜像配置文件及更新2.安装java sdk并配置环境变量3.安装Clion4.总结 1.镜像配置文件及更新 将sources.list备份保存为sources.list.backup,以防止有需要的时候更换回来。 sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup sudo gedit /etc/apt/source…

Nacos源码解读12——Nacos中长连接的实现

短连接 VS 长连接 什么是短连接 客户端和服务器每进行一次HTTP操作&#xff0c;就建立一次连接&#xff0c;任务结束就中断连接。 长连接 客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭&#xff0c;客户端再次访问这个服务器时&#xff0c;会继续使用这一条已经建立…

2023年国赛高教杯数学建模A题定日镜场的优化设计解题全过程文档及程序

2023年国赛高教杯数学建模 A题 定日镜场的优化设计 原题再现 构建以新能源为主体的新型电力系统&#xff0c;是我国实现“碳达峰”“碳中和”目标的一项重要措施。塔式太阳能光热发电是一种低碳环保的新型清洁能源技术[1]。   定日镜是塔式太阳能光热发电站&#xff08;以下…

【学习笔记】LLM for Education

ChatGPT has entered the classroom: how LLMs could transform education 前言IntroductionThe risks are realEmbracing LLMsIntroducing the AI tutorAugmenting retrievalWill it catch on?总结 前言 一篇来自Nature的文章&#xff0c;探讨了教育行业的不同参与者&#x…

基于以太坊的智能合约开发Solidity(基础篇)

参考教程&#xff1a;基于以太坊的智能合约开发教程【Solidity】_哔哩哔哩_bilibili 1、第一个程序——Helloworld&#xff1a; //声明版本号&#xff08;程序中的版本号要和编译器版本号一致&#xff09; pragma solidity ^0.5.17; //合约 contract HelloWorld {//合约属性变…

详解—[Linux 文件描述符]

一、文件描述符的概念 文件描述符是Linux系统中用于访问文件的一种机制&#xff0c;它是一个非负整数&#xff0c;用于指代被打开的文件。 在Linux中&#xff0c;所有执行I/O操作的系统调用都是通过文件描述符完成的。 文件描述符是一个简单的非负整数&#xff0c;用来表明每一…

告别 Navicat!一款能支持几乎所有数据库的开源工具!

数据库连接工具&#xff0c;后端程序员必须要用到工具&#xff0c;常用的是 Navicat&#xff0c;Navicat是收费工具&#xff0c;今天给大家推荐一款开源免费的数据库连接工具 -- dbeaver。 功能特性 1、几乎支持所有数据库产品&#xff0c;包括&#xff1a;MySQL、SQL Server…

文档或书籍扫描为 PDF:ScanPapyrus Crack

ScanPapyrus 可让您快速轻松地将文档或书籍扫描为 PDF&#xff0c;批处理模式使扫描过程快速高效&#xff0c;自动处理书籍并将其拆分为单独的页面 用于快速扫描文档、书籍或打印照片的扫描仪软件 快速扫描文档 使用此扫描仪软件&#xff0c;您无需在扫描仪和计算机之间来回移动…

如何实现远程公共网络下访问Windows Node.js服务端

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…

【Python必做100题】之第二题(找出100以内的偶数并打印)

思路&#xff1a; 1、定义一个空列表来存储取到的偶数 2、每次取到偶数追加到列表的末尾 3、打印的列表即为100以内所有的偶数 重点&#xff1a; 列表追加元素的语法&#xff1a; list.append(i) 代码如下&#xff1a; list [ ] #定义一个空列表来存储偶数 for i in rang…

新公众号没有留言功能怎么办?

为什么公众号没有留言功能&#xff1f;从2018年2月开始&#xff0c;新注册的微信公众号取消了留言功能&#xff0c;原因是为了规避一些营销号通过虚假留言骗取读者信任。不过大部分公众号运营者对TX此举感到失望&#xff0c;一方面大片的留言就像店前排队的顾客&#xff0c;能体…

TeeChart.NET 2023.11.17 Crack

.NET 的 TeeChart 图表控件提供了一个出色的通用组件套件&#xff0c;可满足无数的图表需求&#xff0c;也针对重要的垂直领域&#xff0c;例如金融、科学和统计领域。 数据可视化 数十种完全可定制的交互式图表类型、地图和仪表指示器&#xff0c;以及完整的功能集&#xff0c…

Spring日志完结篇,MyBatis操作数据库(入门)

目录 Spring可以对日志进行分目录打印 日志持久化&#xff08;让日志进行长期的保存&#xff09; MyBatis操作数据库(优秀的持久层框架) MyBatis的写法 开发规范&#xff1a; 单元测试的写法 传递参数 Spring可以对日志进行分目录打印 他的意思是说spring相关只打印INFO…