Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第十二章 C++经验谈(二)

12.8.4 用partition()实现“重排数组,让奇数位于偶数前面”

std::partition()的作用是把符合条件的元素放到区间首部,不符合条件的元素放到区间后部,我们只需把“符合条件”定义为“元素是奇数”就能解决这道题。复杂度是O(N)时间和O(1)空间。为节省篇幅,isOdd()直接做成了函数,而不是函数对象,缺点是有可能阻止编译器实施inline(函数对象还可以有状态,即重载了operator()的类中可以有数据成员保存状态)。

// recipes/algorithm/partition.cc
bool isOdd(int x)
{
    return x % 2 != 0;    // x % 2 == 1 is WRONG
}

void moveOddsBeforeEvens()
{
    int oddeven[] = {1,2,3,4,5,6};
    std::partition(oddeven, oddeven + 6, &isOdd);
    std::copy(oddeven, oddeven + 6, std::ostream_iterator<int>(std::cout, ", "));
    std::cout << std::endl;
}

输出如下,注意确实满足“奇数位于偶数之前”,但奇数元素之间的相对位置有变化,偶数元素亦是如此。
在这里插入图片描述
如果题目要求改成“调整数组顺序使奇数位于偶数前面,并且保持奇数的先后顺序不变,偶数的先后顺序不变”,解决办法也一样简单,改用std::stable_partition()即可,代码及输出如下:

int oddeven[] = {1,2,3,4,5,6};
std::stable_partition(oddeven, oddeven + 6, &isOdd);
std::copy(oddeven, oddeven + 6, std::ostream_iterator<int>(std::cout, ", "));
std::cout << std::endl;
// 输出1, 3, 5, 2, 4, 6

注意,stable_partition()的复杂度较特殊:在内存充足的情况下,开辟与原数组一样大的空间,复杂度是O(N)时间和O(N)空间;在内存不足的情况下,要做in-place位置调换,复杂度是O(NlogN)时间和O(1)空间。

类似的题目还有“调整数组顺序使负数位于非负数前面”,读者应能举一反三。

12.8.5 用lower_bound()查找IP地址所属的城市

题目:已知N个IP地址和它们对应的城市名称,写一个程序,能从IP地址找到它所在的城市。注意这些IP地址区间互不重叠。

这道题目的naive解法是O(N),借助std::lower_bound()可以轻易做到O(logN)查找,代价是事先做一遍O(NlogN)的排序。如果区间相对固定而查找很频繁,这么做是值得的。

基本思路是按IP区间的首地址排好序,再进行二分查找。比如说有两个区间[300, 500]、[600, 750],分别对应北京和香港两个城市,那么std::lower_bound()查找299、300、301、499、500、599、600、601、749、750、751等“IP地址”返回的迭代器如图12-15所示。
在这里插入图片描述
我们需要对返回的结果微调(下面注释1所在行到注释2所在行),使得迭代器it所指的区间是唯一有可能包含该IP地址的区间,如图12-16所示。
在这里插入图片描述
最后判断一下IP地址是否位于这个区间就行了(注释3所在行)。完整代码如下,为了简化,“城市”用整数表示,-1表示未找到。另外,这个实现对于整个IP地址空间都是正确的,即便区间中包括[255.255.255.0, 255.255.255.255]这种边界条件。

// recipes/algorithm/iprange.cc
struct IPrange
{
    uint32_t startIp;  // inclusive
    uint32_t endIp;    // inclusive
    int value;         // >= 0

    bool operator<(const IPrange &rhs) const
    {
 		return startIp < rhs.startIp;
    }
};

// REQUIRE: ranges is sorted.
int findIpValue(const std::vector<IPrange> &ranges, uint32_t ip)
{
    int result = -1;
    
    if (!ranges.empty())
    {
        IPrange needle = {ip, 0, 0};
        std::vector<IPrange>::const_iterator it = std::lower_bound(ranges.begin(), ranges.end(), needle);
        if (it == ranges.end())
        {
            --it;
        }
        else if (it != ranges.begin() && it->startIp > ip)
        {
            --it;
        }
        
        if (it->startIp <= ip && it->endIp >= ip)
        {
            result = it->value;
        }
    }
    return result;
}

说明:如果IP地址区间有重复,那么我们通常要用线段树(http://en.wikipedia.org/wiki/Segment_tree)来实现高效的查询。另外,在真实的场景中,IP地址区间通常适用专门的longest prefix match算法,这会比本节的通用算法更快。

小结

想到正确的思路是一码事,写出正确的、经得起推敲的代码是另一码事。例如12.8.4用(x % 2 != 0)来判断int x是否为奇数,如果写成(x % 2 == 1)就是错的,因为x可能是负数,负数的取模运算的关窍见12.3。常见的错误还包括误用char的值作为数组下标(面试题目:统计文件中每个字符出现的次数),但是没有考虑char可能是负数,造成访问越界。有的人考虑到了char可能是负数,因此先强制转型为unsigned int再用作下标,这仍然是错的。正确的做法是强制转型为unsigned char再用作下标,这涉及C/C++整型提升的规则,就不详述了(如果是负数char转换成unsigned int,相当于把-1赋值给unsigned int,结果是最大的unsigned int值,太大了;而转换成unsigned char时,相当于把-1赋值给unsigned char,结果是最大的unsigned char值,即255)。这些细节往往是面试官的考察点(工作5年以来,作者面试过近百人,因此这番话是从面试官的角度说的)。本节给出的解法在正确性方面应该是没问题的;在效率方面,可以说在Big-O意义下是最优的,但不一定是运行最快的。

另外,面试题的目的可能就是让你动手实现一些STL算法,例如求两个有序集合的交集(set_intersection())、洗牌(random_shuffle())等等,这就不属于本节所讨论的范围了。从“算法”本身的难度上看,作者个人把STL algorithm分为三类,面试时要求手写的往往是第二类算法。
1.容易。即闭着眼睛一想就知道是如何实现的,自己手写一遍的难度跟strlen()和strcpy()差不多。这类算法基本上就是遍历一遍输入区间,对每个元素做些判断或操作,一个for循环就解决问题。一半左右的STL algorithm属于此类,例如for_each()、stransform()、accumulate()等等。

2.较难。知道思路,但是要写出正确的实现要考虑清楚各种边界条件。例如merge()(将两个已排序容器合并成一个有序的容器)、unique()、remove()、random_shuffle()(要考虑随机数生成器的状态空间,http://en.wikipedia.org/wiki/Fisher-Yates_shuffle#Potential_sources_of_bias)、lower_bound()、partition()等等,三成左右的STL algorithm属于此类。

3.难。要在一个小时内写出正确的、健壮的实现基本不现实,例如sort()(快速排序是本科生数据结构课上就有的内容,但是其工业强度的实现是足以在顶级期刊上发论文的)、nth_element()()、next_permutation(将容器中第N个元素放置在其正确的位置上,并保证该位置之前的元素都不大于它,该位置之后的元素都不小于它)、inplace_merge()等等,约有两成STL algorithm属于此类。

注意,“容易”级别的算法是指写出正确的实现很容易,但不一定意味着写出高效的实现也同样容易,例如std::copy()拷贝POD类型的效率可媲美memcpy(),这需要用一点模板技巧。

以上分类纯属个人主观看法,或许别人有不同的分类法,例如把remove()归入简单,把next_permutation()归入较难,把lower_bound()归入难等。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Web 3超入门—踏上Web 3.0的征程:超入门探索指南【文末送书-21】

文章目录 Web 3超入门—踏上Web 3.0的征程&#xff1a;超入门探索指南1. 什么是Web 3.0&#xff1f;2. 区块链技术3. 去中心化应用&#xff08;DApps&#xff09;4. 数字身份和隐私5. 通证经济6. Web 3.0的应用领域Web 3超入门【文末送书-21】 Web 3超入门—踏上Web 3.0的征程&…

TSINGSEE青犀AI智能分析网关V4初始配置与算法相关配置介绍

TSINGSEE青犀AI智能分析网关V4内置了近40种AI算法模型&#xff0c;支持对接入的视频图像进行人、车、物、行为等实时检测分析&#xff0c;上报识别结果&#xff0c;并能进行语音告警播放。硬件管理平台支持RTSP、GB28181协议、以及厂家私有协议接入&#xff0c;可兼容市面上常见…

OM6650AM 一款低功耗车规级蓝牙5.1SoC芯片

OM6650AM是一款超低功耗、同时支持蓝牙5.1协议栈与2.4GHz私有协议的双模无线连接SoC芯片&#xff0c;采用4.0 mm x 4.0 mm QFN32封装&#xff0c;具有丰富的资源&#xff0c;极低的功耗&#xff0c;优异的射频性能&#xff0c;可广泛应用于车载数字钥匙模组、胎压检测、PKE钥匙…

机器视觉技术的演进:YOLO系列与Halcon的深度对比

YOLO系列的发展历程 YOLO&#xff0c;作为一种流行的实时目标检测算法&#xff0c;自2015年首次被提出以来&#xff0c;经历了多个版本的迭代。最初的YOLOv1因其独特的单次检测框架而备受关注&#xff0c;它将图像分割成网格&#xff0c;并对每个网格预测多个边界框和类别概率&…

vue-利用属性(v-if)控制表单(el-form-item)显示/隐藏

表单控制属性 v-if 示例&#xff1a; 通过switch组件作为开关&#xff0c;控制表单的显示与隐藏 <el-form-item label"创建数据集"><el-switch v-model"selectFormVisible"></el-switch></el-form-item><el-form-item label&…

嵌入式Qt 计算器核心算法_2

一.中缀表达式转后缀表达式 中缀表达式是最常用的算术表达式形式——运算符在运算数中间。但运算时需要考虑运算符优先级。 ​后缀表达式是计算机容易运算的表达式&#xff0c;运算符在运算数后面&#xff0c;从左到右进行运算,无需考虑优先级,运算呈线性结构。 1 2 * 3// …

Redis突现拒绝连接问题处理总结

一、问题回顾 项目突然报异常 [INFO] 2024-02-20 10:09:43.116 i.l.core.protocol.ConnectionWatchdog [171]: Reconnecting, last destination was 192.168.0.231:6379 [WARN] 2024-02-20 10:09:43.120 i.l.core.protocol.ConnectionWatchdog [151]: Cannot reconnect…

数据库管理-第151期 Oracle Vector DB AI-03(20240218)

数据库管理151期 2024-02-18 数据库管理-第151期 Oracle Vector DB & AI-03&#xff08;20240218&#xff09;1 向量数据库应用场景2 Oracle Vector DB3 Vector数据类型4 Vector运算5 Vector DML插入向量获取向量 总结 数据库管理-第151期 Oracle Vector DB & AI-03&am…

【计算机网络】socket 网络套接字

网络套接字 一、端口号1. 认识端口号2. socket 二、认识TCP协议和UDP协议1. TCP协议2. UDP协议 三、网络字节序四、socket 编程1. socket 常见API2. sockaddr 结构3. 编写 UDP 服务器&#xff08;1&#xff09;socket()&#xff08;2&#xff09;bind()&#xff08;3&#xff0…

170基于matlab的DNCNN图像降噪

基于matlab的DNCNN图像降噪&#xff0c;网络分为三部分&#xff0c;第一部分为ConvRelu&#xff08;一层&#xff09;&#xff0c;第二部分为ConvBNRelu&#xff08;若干层&#xff09;&#xff0c;第三部分为Conv&#xff08;一层&#xff09;&#xff0c;网络层数为17或者20层…

平衡二叉树(AVL),“平衡”是指什么?为什么要“平衡”?

一、“平衡因子”是什么&#xff1f; 定义&#xff1a;某节点的左子树 与 右子树的高度(深度)差&#xff0c;即为该节点的平衡因子&#xff08;BF,Balance Factor&#xff09;。 二、 原文链接&#xff1a;https://blog.csdn.net/kexuanxiu1163/article/details/103080901 …

指针的进阶(C语言)(下)

目录 4、数组参数、指针参数传参 4.1一维数组传参 4.2二维数组传参 4.3 一级指针传参 4.4 二级指针传参 5、函数指针 6、函数指针数组 7、指向函数指针数组的指针 8、回调函数 总结 续上篇 4、数组参数、指针参数传参 在写代码的时候难免把【数组】或者【指针】传给…

MySQL 多表操作

一.多表关系 1.一对一关系 一个学生只有一张身份证&#xff1b;一张身份证只能对应一个学生。 在任一表中添加外键&#xff0c;指向另一方主键&#xff0c;确保一对一关系。 一般一对一关系很少见&#xff0c;遇到一对一关系的表最好合并。 2.一对多/多对一关系 一个部门…

ArcgisForJS如何访问Arcgis Server?

文章目录 0.引言1.准备ArcGIS相关工具2.创建含有ArcSDE地理数据库的MXD文件3.注册ArcSDE地理数据库4.发布数据到Arcgis Server5.ArcgisForJS访问ArcGIS Server数据 0.引言 ArcGIS API for JavaScript 是一个用于在Web和移动应用程序中创建交互式地图和地理空间分析应用的库。它…

抽象工厂模式 Abstract Factory

1.模式定义: 提供一个创建一系列相关或互相依赖对象的接口&#xff0c;而无需指定它们具体的类 2. 应用场景: 程序需要处理不同系列的相关产品&#xff0c;但是您不希望它依赖于这些产品的 具体类时&#xff0c; 可以使用抽象工厂 3.优点: 1.可以确信你从工厂得到的产品彼…

恒峰-智能高压森林应急消防泵:安全护林新利器

随着科技的发展&#xff0c;人类对自然资源的保护意识日益增强。森林作为地球上最重要的生态系统之一&#xff0c;对于维护生态平衡、净化空气、保持水源等方面发挥着举足轻重的作用。然而&#xff0c;森林火灾却时常威胁着这片绿色家园。为了更好地保护森林资源&#xff0c;智…

D5020——外围元件少,内含压缩器和扩展器静噪电路,可应用在1.5V立体声耳机上,响应时间可调

D5020是一块增益可调 的压缩、扩展电路。它有两个通道组成&#xff0c;一个通道作扩展用&#xff0c;另一个通道能作压缩或扩展用。电路内部含有小信号全波整流、检测信号的大小&#xff0c;用于调节输入或反馈通道的增益大小。含有温度特性较好的带隙精密基准源&#xff0c;静…

二.西瓜书——线性模型、决策树

第三章 线性模型 1.线性回归 “线性回归”(linear regression)试图学得一个线性模型以尽可能准确地预测实值输出标记. 2.对数几率回归 假设我们认为示例所对应的输出标记是在指数尺度上变化&#xff0c;那就可将输出标记的对数作为线性模型逼近的目标&#xff0c;即 由此&…

五种多目标优化算法(NSWOA、MOJS、MOAHA、MOPSO、NSGA2)性能对比(提供MATLAB代码)

一、5种多目标优化算法简介 1.1NSWOA 1.2MOJS 1.3MOAHA 1.4MOPSO 1.5NSGA2 二、5种多目标优化算法性能对比 为了测试5种算法的性能将其求解9个多目标测试函数&#xff08;zdt1、zdt2 、zdt3、 zdt4、 zdt6 、Schaffer、 Kursawe 、Viennet2、 Viennet3&#xff09;&#xff0…

上进计划 | Python爬虫经典实战项目——电商数据爬取!

电商数据采集之——电商数据爬虫|电商数据采集API接口 电商数据爬虫背景 在如今这个网购风云从不间歇的时代&#xff0c;购物狂欢持续不断&#xff0c;一年一度的“6.18年中大促”、“11.11购物节”等等成为了网购电商平台的盛宴。在买买买的同时&#xff0c;“如何省钱&#…