使用 boost::multi_index 封装用于匹配的容器

本文介绍如何使用C++和Boost.MultiIndex库实现一个多功能容器,该容器支持按特定字段自动排序插入元素、快速访问元素及遍历指定区域内元素。通过实例展示了Boost.MultiIndex的强大功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

需要 1 个容器,容器需要具备以下功能:

  • 能按某字段(如积分)插入元素自动排序
  • 能按某字段(如ID)快速访问元素
  • 能快速遍历以某元素为中心的某区域元素
  • 使用 C++ 语言

实现思路

这里涉及多个基础容器的功能的一个组合:

  • map,按 id 快速访问元素
  • priority_queue,大、小堆,按值自动排序
  • list,前后遍历

通常,我们可能自己手动组合上面的容器,来实现背景中提到的功能

这里介绍下 boost::multi_index 可以很简单的实现之

boost::multi_index

官方文档:
https://www.boost.org/doc/libs/1_68_0/libs/multi_index/doc/index.html

官方例子:
https://www.boost.org/doc/libs/1_68_0/libs/multi_index/doc/examples.html

实现例子

可以参见本人实现的:

https://github.com/fananchong/multi_index_example

这里摘录下使用代码:

#include <multi_index.hpp>
#include <time.h>
#include <stdlib.h>

struct MyData
{
	int aaa;

	friend std::ostream& operator<<(std::ostream& os, const MyData& e)
	{
		os << e.aaa;
		return os;
	}
};

using MyContainer = Container<MyData>;
using MyScore = Score<MyData>;

float myrand()
{
	return rand() / (RAND_MAX + 1.0);
}

int main()
{
	srand(time(0));

	MyContainer c;
	c.insert(MyScore{ 1, 1000, MyData{1} });
	c.insert(MyScore{ 3, 500, MyData{2} });
	c.insert(MyScore{ 4, 600, MyData{3} });
	c.insert(MyScore{ 5, 700, MyData{4} });
	c.insert(MyScore{ 0, 550, MyData{5} });
	c.insert(MyScore{ 2, 1500, MyData{6} });

	for (int i = 0; i < 10; i++)
	{
		auto item = c.get_one(3, 500, myrand);
		printf("%lu %lu %lu\n", item->id, item->score, item->data.aaa);
	}

	for (int i = 0; i <= 5; ++i)
	{
		c.erase(i);
	}
	printf("c size: %d\n", c.size());
}

封装代码:

#pragma once

#if !defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <functional>
#include <vector>

using boost::multi_index_container;
using namespace boost::multi_index;

template<class T>
struct Score
{
	uint64_t id;
	int64_t score;
	T data;

	Score(uint64_t id_, int score_, const T& data_)
		: id(id_)
		, score(score_)
		, data(data_)
	{}

	friend std::ostream& operator<<(std::ostream& os, const Score& e)
	{
		os << e.id << " " << e.score << " " << e.data << std::endl;
		return os;
	}
};

struct id {};
struct score {};

template<class T>
class Container : public multi_index_container <Score<T>, indexed_by <
	ordered_unique <tag<id>, BOOST_MULTI_INDEX_MEMBER(Score<T>, uint64_t, id)>,
	ordered_non_unique <tag<score>, BOOST_MULTI_INDEX_MEMBER(Score<T>, int64_t, score)>>
	>
{
public:
	const Score<T>* get_one(uint64_t id_, int64_t range, std::function<float()> random_func)
	{
		auto it = this->get<id>().find(id_);
		if (it == this->get<id>().end())
		{
			return nullptr;
		}
		auto s = it->score;
		auto it_upper = this->get<score>().upper_bound(s - range);
		auto it_lower = this->get<score>().lower_bound(s + range);

		std::vector<const Score<T>*> temps;
		for (auto it = it_upper; it != it_lower; ++it)
		{
			temps.push_back(&(*it));
		}

		if (temps.size() > 0)
		{
			int index = int(random_func() * temps.size());
			return temps[index];
		}
		return nullptr;
	}
};

template<typename Tag, typename MultiIndexContainer>
void print_out_by(const MultiIndexContainer& s)
{
	const typename boost::multi_index::index<MultiIndexContainer, Tag>::type& i = get<Tag>(s);
	typedef typename MultiIndexContainer::value_type value_type;
	std::copy(i.begin(), i.end(), std::ostream_iterator<value_type>(std::cout));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fananchong2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值