【209】VS2022 C++对排好序的vector使用二分查找算法的例子

本文介绍了如何对已经排序的 vector 进行二分法查找。

首先,我们先看一下存储数据的类,我们假设所有数据的 id 是唯一的:

DataItem.h

#pragma once
#include<string>namespace zc {class DataItem{public:int m_id;std::string m_name;std::string m_data;DataItem(int id, std::string name, std::string data);~DataItem();};
}

DataItem.cpp

#include "DataItem.h"using namespace zc;DataItem::DataItem(int id, std::string name, std::string data):m_id(id), m_name(name), m_data(data)
{
}DataItem::~DataItem(){}

存储在 vector 中的元素,都是 DataItem 类实例化的对象。这些对象在 vector 中按照 id 从低到高排列。如果我们要提高按照 id 查找的效率,可以使用二分法查找(也叫折半查找)。

算法实现的思路如下:

  1. 假设 vector 的长度是 N,循环次数是以 2 为底 N 的对数。程序先强制转换为 int,然后给整型变量 times 赋值循环次数。

  2. 循环开始前,设置 begin 是 0,代表第一个元素的下标。end 是最后一个元素的下标。

  3. 开启循环,循环次数就是 times。只要循环次数达到 times 就停止循环。

  4. 在循环中,计算中间元素的下标,取出中间元素。

  5. 如果输入 id 小于中间元素的下标,给 end 赋值中间元素坐标减一。反之,给 begin 赋值中间元素坐标。通过循环不断缩小 begin 和 end 之间的范围。因为 vector 的长度不可能总是等于 2 整数次方,再加上循环次数强制转换为整型,所以 begin 和 end之间要么相等,要么 end 比 begin 大一。

  6. 上一个循环结束后,开启从 begin 到 end 的循环,如果能找到 id 相同的元素并返回下标,如果没找到就返回 -1.

下面是具体实现的 C++ 代码:

#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <cmath>
#include "DataItem.h"
#include <chrono>// 向 vector 中添加元素
void addItem(std::vector<zc::DataItem> &vector) {for (int i = 1; i < 100000; i++) {std::string no = std::to_string(i);vector.push_back(zc::DataItem(i, "name_" + no, "data_" + no));}}// 使用二分法查找算法,从 vector 中查找指定 id 的对象的序号.
// vector: 已经排好序的列表
// id:  要查找的指定ID
int findIndexByBinary(const std::vector<zc::DataItem> vector, const int id) {int result = -1;int size = vector.size();if (0 == size) {return -1;}// 只有一条数据就直接判断然后返回。if (1 == size) {if (vector[0].m_id == id) {result = 0;}return result;}int begin = 0;int end = size - 1;// 计算以2为底的对数,进而确定要循环多少次找到目标数据double log2Result = log2((double)size);int times = (int)log2Result;// 不断缩小begin和end的范围。有可能 begin 等于 end,也有可能 end 比 begin 大一。for (int i = 0; i < times; i++) {int tmpLen = end - begin + 1;int halfIndex = begin + (tmpLen / 2);zc::DataItem item = vector[halfIndex];if (id < item.m_id) {end = halfIndex - 1;}else {begin = halfIndex;}}//printf("begin=%d,  end=%d\n", begin, end);for (int i = begin; i <= end; i++) {zc::DataItem tmp = vector[i];if (id == tmp.m_id) {result = i;break;}}return result;
}// 遍历vector,从 vector 中查找指定 id 的对象的序号.
int findIndex(const std::vector<zc::DataItem> vector, const int id) {int result = -1;int size = vector.size();if (0 == size) {return -1;}for (int i = 0; i < size; i++) {zc::DataItem tmp = vector[i];if (id == tmp.m_id) {result = i;break;}}return result;
}long long nowMS()
{long long result =std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();return result;
}int main(int argc, char** argv) {system("color 02");printf("hello argc=%d  argv[0]=%s\n\n", argc, argv[0]);long long t1 = 0, t2 = 0;int index = -1;std::vector<zc::DataItem> vector;addItem(vector);t1 = nowMS();const int id = 95001;index = findIndexByBinary(vector, id);t2 = nowMS();if (index < 0) {return -1;}zc::DataItem item = vector[index];printf("index=%d,  id=%d,  name=%s,  data=%s,  time=%lld\n", index, item.m_id, item.m_name.c_str(), item.m_data.c_str(), (t2 - t1));t1 = nowMS();index = findIndex(vector, id);t2 = nowMS();zc::DataItem item2 = vector[index];printf("index=%d,  id=%d,  name=%s,  data=%s,  time=%lld\n", index, item2.m_id, item2.m_name.c_str(), item2.m_data.c_str(), (t2 - t1));printf("\n\n");
}

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

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

相关文章

ABAP 上传 excel 报表

&#xff08;1&#xff09;先在屏幕上增加上传文件的按钮 "屏幕选择条件" SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001. PARAMETERS : p_source LIKE rlgrap-filename . SELECTION-SCREEN END OF BLOCK b1. 你会发现&#xff0c;上面的代码只…

Compose与View系统互操作方案

本文将全面解析 Android 现代 UI 框架 Jetpack Compose 与传统 View 系统的互操作方案&#xff0c;涵盖基础原理、实战技巧、性能优化和高级应用&#xff0c;助你实现渐进式迁移和混合开发。 一、互操作的必要性与整体架构 1.1 为什么需要互操作性 渐进式迁移&#xff1a;大型…

HNCTF 2025 Just Ping Write-up

part 1 路由部分主逻辑逆向 package mainimport ("net/http" )func main() {// 注册路由和处理函数// 当访问 "/api/ping" 路径时&#xff0c;调用 pingHandler 函数处理请求http.HandleFunc("/api/ping", pingHandler)// 注册开发测试API路由//…

OpenCV CUDA模块中用于稠密光流计算的 TV-L1(Dual TV-L1)算法类cv::cuda::OpticalFlowDual_TVL1

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::cuda::OpticalFlowDual_TVL1类是基于变分优化方法的稠密光流算法实现&#xff08;Dual TV-L1 光流模型&#xff09;&#xff0c;在 GPU 上加…

ThreadPoolTaskExecutor+CompletableFuture实现多线程异步数据同步和自定义线程池监控和动态调整实现

前言 ThreadPoolTaskExecutor是Spring框架提供的一个线程池实现&#xff0c;它是对Java标准库中ThreadPoolExecutor的封装&#xff0c;提供了更便捷的配置和集成方式&#xff0c;特别适合在Spring环境中使用。相关线程池概念见线程&线程池相关 CompletableFuture 是 Java…

一篇文章理解js闭包和作用于原理

一、js闭包的作用原理 JS闭包是指内部函数访问外部函数变量的机制&#xff0c;常用于数据封装和模块化。典型应用包括创建私有变量、解决循环中的异步问题、实现函数柯里化等。案例分析展示了闭包在计数器、防抖函数等场景的使用&#xff0c;同时揭示了可能的内存泄漏风险。正…

GUI丝滑教程-python tinker

在 Tkinter GUI 应用中&#xff0c;线程可以帮助你在后台执行长时间运行的任务&#xff0c;而不阻塞界面响应。下面是一些技巧&#xff0c;帮助你在使用线程时避免 Tkinter 界面卡顿的问题。 为什么 Tkinter 界面会卡顿&#xff1f; Tkinter 使用 主线程 来处理 UI 更新&…

第一部分-数据通信网络基础

目录 一、什么是网络通信&#xff1f; 二、网络通信设备的基本识别 1.双绞线 2.集线器&#xff08;物理层设备&#xff09; 3.中继器&#xff08;物理层设备&#xff09; 4.接入交换机 5.汇聚交换机 6.核心交换机 7.路由器 8.无线路由器 9.光猫 一、什么是网络通信&#xff1f;…

windows电脑解决笔记本搜索不到wifi问题

windows笔记本电脑明明打开了wifi功能&#xff0c;却搜索不到wifi&#xff0c;此问题可能是网络适配器被禁用的原因导致&#xff0c;通过以下方法也许能解决&#xff0c;无需重启电脑 1、右键点击网络或wifi图标&#xff0c;打开界面”网络和internet“ 2、选择”高级网络设置…

C# 界面检测显示器移除并在可用显示器上显示

C# 检测显示器被移除&#xff0c;将界面在当前可用的显示器上显示&#xff0c;避免程序在任务栏点击无响应。 using System; using System.Linq; using System.Windows.Forms;public class MonitorWatcher : IDisposable {private readonly Form _targetForm;private Screen …

JAVA实战开源项目:青年公寓服务平台 (Vue+SpringBoot) 附源码

本文项目编号 T 233 &#xff0c;文末自助获取源码 \color{red}{T233&#xff0c;文末自助获取源码} T233&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

阿里云服务状态监控:实时掌握云服务健康状况

前言 在云计算时代,企业和开发者越来越依赖云服务提供商的基础设施和服务。当我们的应用部署在云上,服务的可用性和稳定性就与云服务提供商息息相关。一旦云服务出现故障或维护,可能会对我们的业务造成直接影响。因此,实时了解云服务的运行状态变得尤为重要。阿里云作为国…

使用VSCode开发FastAPI指南

1概述 FastAPI 是一个现代的高性能 Web 框架&#xff0c;用于使用 Python 构建 API。它旨在让开发者轻松快速高效地构建 API&#xff0c;同时提供 API 的自动验证、序列化和文档记录等功能&#xff0c;使其成为构建 Web 服务和微服务的热门选择。 在这个 FastAPI 教程中&#…

2025年硬件实习/秋招面试准备

前言 暑期即将到来&#xff0c;有很多研一研二以及大三大四的同学准备硬件类&#xff08;硬件研发、嵌入式硬件、layout、电源设计、射频、硬件测试、工艺、FAE&#xff09;的实习或秋招。鉴于此&#xff0c;总结一下网友们秋招、实习中的硬件高频考点&#xff0c;并分析他们是…

VSCode - Trae 插件关闭弹出框代码补全

Trae 插件关闭弹出框代码补全 弹出框代码补全与非弹出框代码补全 如下是弹出框代码补全 如下是非弹出框代码补全 关闭 / 启用弹出框代码补全 点击 【管理】&#xff08;小齿轮&#xff09; -> 点击 【设置】 取消勾选&#xff08;如果需要启用&#xff0c;则勾选即可&…

Elasticsearch从安装到实战、kibana安装以及自定义IK分词器/集成整合SpringBoot详细的教程ES(三)

DSL官方地址&#xff1a; DSL查询分类 Elasticsearch提供了基于JSON的DSL&#xff08;https://www.elastic.co/docs/explore-analyze/query-filter/languages/querydsl&#xff09;来定义查询。常见的查询类型包括&#xff1a; 查询所有&#xff1a;查询出所有数据&#xff0…

我们来学mysql -- keepalive主从高可用

keepalive主从高可用 简明扼要安装KP场景“高可用”配置主keepalived.conf从keepalived.confmysql_check.sh 高可用验证KP运行情况通过vip连接mysqlvip连接上创建数据库关闭主库所在服务器的KPvip连接上再次创建数据库 结尾 简明扼要 搭建mysql的主从八股文如是&#xff1a;主…

Compose笔记(二十六)--DatePicker

这一节主要了解一下Compose中的DatePicker,DatePicker是一个用于选择日期的组件&#xff0c;它提供了直观的界面让用户可以通过日历视图或直接输入来选择年、月、日。我们在开发中时常会用到日期选择器&#xff0c;简单总结如下: API: DatePickerDialog onDismissRequest&…

【靶场】upload-labs-文件上传漏洞闯关

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言1.第一关1.保存html页面2.修改页面html3.访问修改后的本地html文件4.上传php文件5.访问上传的php2.第二关1.抓上传包修改文件类型2.上传成功3.第三关1.phtml php3会被解析为php原理2.上传成功4…

基于 Transformer RoBERTa的情感分类任务实践总结之四——PGM、EMA

整合了以下五大核心技术&#xff1a;R-Drop、PGM 对抗训练、EMA、标签平滑、CosineAnnealing 学习率调度。 1. R-Drop&#xff08;Regularized Dropout&#xff09; 原理&#xff1a;同一个样本做两次前向传播&#xff08;同 dropout mask&#xff09;&#xff0c;计算两次输…