跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++AI算法

C++ 轻量级搜索引擎实战:构造正/倒排索引

综述由AI生成轻量级搜索引擎核心模块基于 C++ 实现,涵盖 Jieba 分词工具集成、正排与倒排索引的数据结构设计及关键函数实现。内容包括文档内容的解析存储、关键字映射逻辑、权重计算以及单例模式在索引管理中的应用。通过构建正倒排索引关系,实现了从文档 ID 检索内容及从关键词检索文档 ID 的基础功能,为搜索引擎底层原理提供工程实践参考。

宁静发布于 2026/3/24更新于 2026/5/89 浏览
C++ 轻量级搜索引擎实战:构造正/倒排索引

【一】Jieba 分词工具

在使用倒排索引时需要用到关键词,这些关键词由每个 HTML 文档的标题和内容生成,因此涉及分词处理。本项目使用 cppjieba 分词工具完成该功能。

若需使用 cppjieba 分词工具,可通过 Git 命令上传至本地服务器,并建立软链接指向头文件和词库目录。

【二】正/倒排索引结构设计

//正排结构
typedef struct Forward_index {
    //文档内容
    std::string title;
    std::string source;
    std::string chain;
    //对应正排 ID
    uint64_t doc_id;
} Forwardindex;

//倒排结构
typedef struct Inverted_index {
    //对应正排 ID
    int doc_id;
    //涉及到的关键字
    std::string word;
    //权重
    int weight;
} Invertedindex;

正排:根据 ID 映射对应的文档(标题、内容、URL),ID 利用 vector 下标存储。

倒排:根据关键字映射对应的 ID,利用 unordered_map 的快速搜索特性。

//正排存储
std::vector<Forwardindex> Forward;
typedef std::vector<Invertedindex> Stock_Inverted;

//倒排存储
std::unordered_map<std::string,Stock_Inverted> Inverted;

【三】关键函数设计

(1)由文档 ID 返回文档内容

含义:正排外部实现,根据 ID 返回 vector 中对应的具体内容。

//根据 ID 返回文档内容
Forwardindex* GetForward_index(const long long& id) {
    if(id >= Forward.size()) {
        std::cerr << "GetForward_index is errno" << std::endl;
        return nullptr;
    }
    return &Forward[id];
}
(2)由关键字返回倒排拉链

含义:倒排外部实现,根据关键字返回对应的 ID 列表,即返回 vector 成员。

解释:每个关键词涉及的 ID 不止一个,所以需要 vector 代表一个关键字涉及的所有文档。

//根据关键字返回倒排拉链
Stock_Inverted* GetInverted_index(const std::string word) {
    auto it = Inverted.find(word);
    if(it == Inverted.end()) {
        std::cerr << "GetInverted_index is errno" << std::endl;
        return nullptr;
    }
    return &it->second;
}
(3)说明

现在已具备给外部的接口:由 ID 返回文档内容、由关键词返回文档 ID。接下来是填变量、建立索引关系。

//正排存储
std::vector<Forwardindex> Forward;
typedef std::vector<Invertedindex> Stock_Inverted;

//倒排存储
std::unordered_map<std::string,Stock_Inverted> Inverted;
(4)建立索引

原理:利用数据清洗后的 data_clean.txt 文件,每行代表一个文档。通过 getline 按行读取,构建正排和倒排内容。

//建立索引
bool BuildIndex(const std::string &input) {
    std::ifstream in(input, std::ios::in | std::ios::binary);
    if(!in.is_open()) {
        std::cerr << "BuildIndex is errno" << std::endl;
        return false;
    }
    
    std::string line;
    while(std::getline(in, line)) {
        Forwardindex *doc = Build_Forward_Index(line);
        printf("正在建立索引:%lld\ntitle:%s\nchain:%s\n", doc->doc_id, doc->title.c_str(), doc->chain.c_str());
        if(doc == nullptr) continue;
        Build_Inverted_Index(*doc);
    }
    return true;
}
(5)建立正排索引

思路:解析单个文档内容 line(格式为:标题 | 内容 | URL),提取后填入 vector,文档 ID 即为 vector 下标。

//建立正排索引
Forwardindex* Build_Forward_Index(const std::string& line) {
    Forwardindex* index = new Forwardindex();
    
    //截取 title
    size_t set_pos1 = line.find('\3');
    if(set_pos1 == std::string::npos) {
        delete index;
        return nullptr;
    }
    index->title = line.substr(0, set_pos1);
    if (index->title.empty()) index->title = "空";
    
    //截取 source
    size_t set_pos2 = line.find('\3', set_pos1+1);
    if(set_pos2 == std::string::npos) {
        delete index;
        return nullptr;
    }
    index->source = line.substr(set_pos1+1, set_pos2 - (set_pos1+1));
    if (index->source.empty()) index->source = "空";
    
    //截取 URL(chain)
    index->chain = line.substr(set_pos2+1);
    if (index->chain.empty()) index->chain = "空";
    
    index->doc_id = Forward.size();
    Forward.push_back(*index);
    return index;
}
(6)建立倒排索引
//建立倒排索引
bool Build_Inverted_Index(const Forwardindex& doc) {
    JiebaUtil jieba;
    std::vector<std::string> S;
    
    //对标题统计
    S = jieba.Tokenize(doc.title);
    struct calculate {
        int title_size = 0;
        int source_size = 0;
    };
    std::unordered_map<std::string, calculate> V;
    
    for(auto e : S) {
        (V[e].title_size)++;
    }
    
    //统计内容出现次数
    S.clear();
    S = jieba.Tokenize(doc.source);
    for(auto e : S) {
        (V[e].source_size)++;
    }
    
    //遍历 V 的结果写入到 Inverted
    for(auto it : V) {
        Invertedindex index_t;
        index_t.word = it.first;
        index_t.doc_id = doc.doc_id;
        index_t.weight = ((it.second.title_size)*2 + (it.second.source_size)*1);
        Inverted[it.first].push_back(std::move(index_t));
    }
    return true;
}

【四】单例模式

单例模式:只允许创建一个 Index 对象,后续由 index 指针调用该对象。

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
class Index {
public:
    typedef std::vector<Invertedindex> Stock_Inverted;
    
    //禁止拷贝构造和赋值重载
    Index(const Index&) = delete;
    Index& operator=(const Index&) = delete;
    
    static Index* handle() {
        if(instance == nullptr) {
            pthread_mutex_lock(&mutex);
            if (instance == nullptr) {
                instance = new Index;
            }
            pthread_mutex_unlock(&mutex);
        }
        return instance;
    }
    
private:
    static Index* instance;
};

//静态成员初始化
Index* Index::instance = nullptr;

目录

  1. 【一】Jieba 分词工具
  2. 【二】正/倒排索引结构设计
  3. 【三】关键函数设计
  4. (1)由文档 ID 返回文档内容
  5. (2)由关键字返回倒排拉链
  6. (3)说明
  7. (4)建立索引
  8. (5)建立正排索引
  9. (6)建立倒排索引
  10. 【四】单例模式
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • AIGC 产品经理从 0 到 1 核心能力与面试考点解析
  • AI 编程工具选型:Copilot、Cursor、Codex 核心差异
  • 前端Canvas:让你的网站更具视觉冲击力
  • 使用 Text Generation WebUI 进行大模型 LoRA 微调指南
  • Python 基础语法与数学建模应用指南
  • 动态规划基础概念及第 N 个泰波那契数题解 (1)
  • 手势控制电脑方案分析与 Python 实现示例
  • 单向链表六大核心操作详解:销毁、查找、倒置与排序
  • 人工智能与机器学习在软件工程中的应用
  • Android System WebView 版本对照与内核更新指南
  • 内网渗透基础:域环境权限获取与维持
  • FPGA 深入解析 M25P16 SPI-FLASH 读写操作与 Verilog 实现
  • CCF-CSP 40-3 图片解码题解:矩阵翻转与旋转
  • Git 版本控制详细使用教程
  • 阿里开源纯前端浏览器自动化 PageAgent 技术解析
  • 前端程序员转行大模型开发指南
  • Python 语言概述:核心特性、应用场景与学习价值
  • GitHub 私有仓库服务器 SSH 密钥部署指南
  • VS Code 远程连接服务器后 GitHub Copilot 无法使用
  • Qwen-Image-2512 V2 整合包:ComfyUI 与 WebUI 部署实战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online