C++ 数据结构实战:快速查找

最近线上开发C++时,遇到一个性能问题,业务场景简单描述为:

   给定m个商品ID, 4个特征(特征数量可增可减),已知商品对应的每个特征的值,如何快速获取某个商品的某个特征值?

当时我采取的是stl嵌套的数据结构,由于时间复杂度较高,且vector的值是随着map的rehash阶段不断进行内存拷贝的, 在全量计算特征的时候会给性能造成很大的压力,当时与base的性能对比如下:

性能不达标,无法上线,经过一番思考,最终采取了如下数据结构:

std::unordered_map<int64_t, float> FeatureKeyV;
std::vector<FeatureKeyV*> FeatureKeyValueVec;

其中,FeatureKeyV负责存储商品ID与特征值的对应关系,FeatureKeyValue每行代表一个特征,负责存储每个商品在该特征上的取值。在获取商品特征值时,首先获取该特征的行数i,得到FeatureKeyValue第i行的FeatureKeyV指针,最后根据商品id即可得到对应的特征值。整个检索过程的时间复杂度仅来源于哈希表的查找,众所周知,哈希表的特点就是查找效率高,时间复杂度为常数级别O(1)。

源码如下:

/**
 * 给定m个商品ID, 4个特征(特征数量可增可减),已知商品对应的每个特征的值,如何快速获取某个商品的某个特征值?
 */
#include <iostream>
#include<unordered_map>

enum {
    FEATURE_IREM_NUM_1=0,
    FEATURE_IREM_NUM_2,
    FEATURE_IREM_NUM_3,
    FEATURE_IREM_NUM_4,
    FEATURE_TOTAL_NUM
};
typedef std::unordered_map<int64_t, float> FeatureKeyV;
typedef std::vector<FeatureKeyV*> FeatureKeyValueVec;
FeatureKeyValueVec features;

static const size_t NUM_DOC_ROW_NUM = 750;

void Init()
{
    features.resize(FEATURE_TOTAL_NUM);
    for(size_t i = 0; i < features.size(); i++) {
        FeatureKeyV* &f = features[i];
        f = new FeatureKeyV(NUM_DOC_ROW_NUM);
    }
}
void SetFeature(int64_t sku, int fid, float value)
{
    if(fid > FEATURE_IREM_NUM_4 or fid < FEATURE_IREM_NUM_1)
        return;
    int i = fid - FEATURE_IREM_NUM_1;
    if(features[i])
        (*(features[i]))[sku] = value;
}
int GetFeature(int64_t sku, int fid, float &value)
{
    if(fid > FEATURE_IREM_NUM_4 or fid < FEATURE_IREM_NUM_1)
        return -1;
    int i = fid - FEATURE_IREM_NUM_1;
    if(features[i])
    {
        FeatureKeyV::iterator it = features[i]->find(sku);
        if (it == features[i]->end())
            return -1;
        value = it->second;
        return 0;
    }
    return -1;
}
void Reset()
{
    for(size_t i = 0; i < features.size(); i++)
    {
        if(features[i])
        {
            features[i]->clear();
            delete features[i];
        }
    }
}
int main()
{
    Init();

    int64_t sku1 = 10000;
    SetFeature(sku1,FEATURE_IREM_NUM_1,20);
    SetFeature(sku1,FEATURE_IREM_NUM_2,30);
    SetFeature(sku1,FEATURE_IREM_NUM_3,40);
    SetFeature(sku1,FEATURE_IREM_NUM_4,50);
    int64_t sku2 = 10001;
    SetFeature(sku2,FEATURE_IREM_NUM_1,22);
    SetFeature(sku2,FEATURE_IREM_NUM_2,33);
    SetFeature(sku2,FEATURE_IREM_NUM_3,44);
    SetFeature(sku2,FEATURE_IREM_NUM_4,55);

    float value;
    if (!GetFeature(sku2, FEATURE_IREM_NUM_1, value))
    {
        cout << "feature:" << value << endl;
    }

    Reset();
}

优化后的性能对比如下:

性能达到上线标准,可见学好数据结构的重要性,有人曾经说过,一个优秀的算法,往往是利用最简单的数据结构解决最复杂的问题,如果数据结构设计比较复杂,那么一定是设计不合理。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值