version 1:

#ifndef RANK_TMPL_H_
#define RANK_TMPL_H_

#include <stdio.h>
#include <stdint.h>
#include <vector>
#include <algorithm>
#include <map>

// RECORD 需要实现小于号 和 .Key() 函数
template<typename RECORD,typename KEY,uint32_t MAX_SIZE>
class VectorBasedRank
{
    typedef std::vector<RECORD> RECORDS;
    typedef std::vector<RECORD*> RECORDS_PTR;
    typedef std::map<KEY, RECORD*> RECORDS_KEYMAP;
public:
    VectorBasedRank(){}
public:
    int32_t Load(const RECORDS &records);
    int32_t Insert(RECORD &record);
    RECORD *FindByIndex(uint32_t index);
    RECORD *FindByKey(uint32_t key);
    void ReSort();
private:
    int32_t InsertNew(RECORD &record);
    int32_t InsertReplace(RECORD &record);
public:
    void DisplaySortedRecords();
    void DisplayMapRecords();
private:
    RECORDS m_records;
    RECORDS_PTR m_sortedRecords;
    RECORDS_KEYMAP m_keyMapRecords;
};

template<typename RECORD, typename KEY, uint32_t MAX_SIZE>
RECORD * VectorBasedRank<RECORD, KEY, MAX_SIZE>::FindByKey(uint32_t key)
{
    RECORDS_KEYMAP::iterator it = m_keyMapRecords.find(key);
    if (it == m_keyMapRecords.end())
    {
        return NULL;
    }
    return it->second;
}

template<typename RECORD, typename KEY, uint32_t MAX_SIZE>
void VectorBasedRank<RECORD, KEY, MAX_SIZE>::ReSort()
{
    std::sort(m_sortedRecords.begin(), m_sortedRecords.end(), Less<RECORD>);
}

template<typename RECORD, typename KEY, uint32_t MAX_SIZE>
RECORD * VectorBasedRank<RECORD, KEY, MAX_SIZE>::FindByIndex(uint32_t index)
{
     && index < m_sortedRecords.size())
    {
        return m_sortedRecords[index];
    }
    return NULL;
}

template<typename RECORD, typename KEY, uint32_t MAX_SIZE>
int32_t VectorBasedRank<RECORD, KEY, MAX_SIZE>::InsertReplace(RECORD &record)
{
    uint32_t lastIndex = m_sortedRecords.size() - ;
    if (Less(m_sortedRecords[lastIndex], &record))
    {
        ;
    }
    m_keyMapRecords.erase(m_sortedRecords[lastIndex]->Key());
    *m_sortedRecords[lastIndex] = record;
    RECORD *ptr = m_sortedRecords[lastIndex];
    std::sort(m_sortedRecords.begin(), m_sortedRecords.end(), Less<RECORD>);
    m_keyMapRecords[m_sortedRecords[lastIndex]->Key()] = ptr;
    ;
}

template<typename RECORD, typename KEY, uint32_t MAX_SIZE>
int32_t VectorBasedRank<RECORD, KEY, MAX_SIZE>::InsertNew(RECORD &record)
{
    m_records.push_back(record);
    uint32_t i = m_records.size() - ;
    RECORD *ptr = &m_records[i];
    m_sortedRecords.push_back(ptr);
    std::sort(m_sortedRecords.begin(), m_sortedRecords.end(), Less<RECORD>);
    m_keyMapRecords[m_records[i].Key()] = ptr;
    ;
}

template<typename RECORD>
bool Less(const RECORD* left, const RECORD* right)
{
    return *left < *right;
}

template<typename RECORD, typename KEY, uint32_t MAX_SIZE>
int32_t VectorBasedRank<RECORD, KEY, MAX_SIZE>::Insert(RECORD &record)
{
    // 元素已满,跟最后一个比较,若新元素小于最后一名,则放弃插入,若大于最后一名,则替换掉最后一名,然后排序
    if (m_records.size() >= MAX_SIZE)
    {
        return InsertReplace(record);
    }
    // 元素未满,直接插入
    else
    {
        return InsertNew(record);
    }
}

template<typename RECORD, typename KEY, uint32_t MAX_SIZE>
int32_t VectorBasedRank<RECORD, KEY, MAX_SIZE>::Load(const RECORDS &records)
{
    m_records.reserve(MAX_SIZE);
    m_sortedRecords.reserve(MAX_SIZE);
    ; i < records.size() && i < MAX_SIZE; ++i)
    {
        m_records.push_back(records[i]);
        RECORD *ptr = &m_records[i];
        m_sortedRecords.push_back(ptr);
        m_keyMapRecords[m_records[i].Key()] = ptr;
    }
    std::sort(m_sortedRecords.begin(), m_sortedRecords.end(), Less<RECORD>);
    ;
}

template<typename RECORD, typename KEY, uint32_t MAX_SIZE>
void VectorBasedRank<RECORD, KEY, MAX_SIZE>::DisplayMapRecords()
{
    for (RECORDS_KEYMAP::const_iterator it = m_keyMapRecords.begin(); it != m_keyMapRecords.end(); ++it)
    {
        it->second->Display();
    }
}

template<typename RECORD, typename KEY, uint32_t MAX_SIZE>
void VectorBasedRank<RECORD, KEY, MAX_SIZE>::DisplaySortedRecords()
{
    ; i < m_sortedRecords.size(); ++i)
    {
        m_sortedRecords[i]->Display();
    }
}

#endif

测试代码:

#include <stdint.h>
#include <stdio.h>
#include "rank_tmpl.h"

struct StarInfo
{
    int32_t roleid, likes;
    StarInfo() :likes(), roleid(){}
    StarInfo(int32_t like) :likes(like),roleid( - like){}
    bool operator < (const StarInfo &info) const
    {
        return likes < info.likes;
    }
    int32_t Key()
    {
        return roleid;
    }
    void Display()
    {
        printf("roleid = %d,likes = %d\n", roleid, likes);
    }
};

int32_t main()
{
    StarInfo infos[] = { , , , ,  };
    std::vector<StarInfo> vecInfos(infos, infos + ]));
    VectorBasedRank<StarInfo, int32_t, > ranks;
    ranks.Load(vecInfos);
    ranks.DisplaySortedRecords();
    ranks.DisplayMapRecords();
    printf("------------\n");
    StarInfo *p = ranks.FindByKey();
    p->likes += ;
    ranks.DisplaySortedRecords();
    ranks.DisplayMapRecords();
    printf("------------\n");
    ranks.ReSort();
    ranks.DisplaySortedRecords();
    ranks.DisplayMapRecords();
    getchar();
    ;
}

version 2:

#ifndef RANK_TMPL_H_
#define RANK_TMPL_H_

#include <stdio.h>
#include <stdint.h>
#include <vector>
#include <algorithm>
#include <map>

// RECORD 需要实现小于号 和 .Key() 函数
template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC = true>
class VectorBasedRank
{
    typedef std::vector<RECORD> RECORDS;
    typedef std::vector<uint32_t> RECORDS_SORTED_INDEX;
    typedef std::map<KEY, uint32_t> RECORDS_KEY_MAP;
public:
    VectorBasedRank(){ m_capacity = INIT_SIZE; }
public:
    int32_t Load(const RECORDS &records);
    uint32_t Size(){ return m_records.size(); }
    uint32_t Capacity(){ return m_capacity; }
    void SetCapacity(uint32_t capacity){ m_capacity = capacity; }
    int32_t Insert(const RECORD &record);
    uint32_t AdjustIndex(uint32_t index);
    uint32_t Adjust();
    RECORD *RecordByIndex(uint32_t index);
    RECORD *RecordByKey(const KEY &key);
public:
    void DisplaySortedRecords();
    void DisplayMapRecords();
private:
    bool Less(const uint32_t left, const uint32_t right, const RECORDS &records);
    void QSort(int32_t start, int32_t end, RECORDS_SORTED_INDEX &recordIndexs, const RECORDS &records);
    uint32_t AdjustBack(uint32_t index);
    uint32_t AdjustFront(uint32_t index);
private:
    uint32_t m_capacity;
    RECORDS m_records;
    RECORDS_SORTED_INDEX m_sortedRecords;
    RECORDS_KEY_MAP m_keyMapRecords;
};

template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC /*= true*/>
RECORD * VectorBasedRank<RECORD, KEY, INIT_SIZE, ASC>::RecordByKey(const KEY &key)
{
    typename RECORDS_KEY_MAP::iterator it = m_keyMapRecords.find(key);
    if (it != m_keyMapRecords.end())
    {
        if (it->second < m_records.size())
        {
            return &m_records[it->second];
        }
    }
    return NULL;
}

template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC /*= true*/>
RECORD * VectorBasedRank<RECORD, KEY, INIT_SIZE, ASC>::RecordByIndex(uint32_t index)
{
    if (index < m_sortedRecords.size())
    {
        if (m_sortedRecords[index] < m_records.size())
        {
            return& m_records[m_sortedRecords[index]];
        }
    }
    return NULL;
}

template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC /*= true*/>
uint32_t VectorBasedRank<RECORD, KEY, INIT_SIZE, ASC>::Adjust()
{
    uint32_t index = ;
    )
    {
        ], m_sortedRecords[index], m_records))
        {
            AdjustIndex(index);
            AdjustIndex(index + );
        }
        ++index;
    }
    ;
}

template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC /*= true*/>
uint32_t VectorBasedRank<RECORD, KEY, INIT_SIZE, ASC>::AdjustIndex(uint32_t index)
{
    )
    {
        return AdjustFront(index);
    }
    )
    {
        return AdjustBack(index);
    }
    else
    {
        ], m_records))
        {
            return AdjustFront(index);
        }
        ], m_sortedRecords[index], m_records))
        {
            return AdjustBack(index);
        }
    }
    return index;
}

template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC /*= true*/>
uint32_t VectorBasedRank<RECORD, KEY, INIT_SIZE, ASC>::AdjustBack(uint32_t index)
{
     && Less(m_sortedRecords[index + ], m_sortedRecords[index], m_records))
    {
        uint32_t tmp = m_sortedRecords[index];
        m_sortedRecords[index] = m_sortedRecords[index + ];
        m_sortedRecords[index + ] = tmp;
        ++index;
    }
    return index;
}

template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC /*= true*/>
uint32_t VectorBasedRank<RECORD, KEY, INIT_SIZE, ASC>::AdjustFront(uint32_t index)
{
     && Less(m_sortedRecords[index], m_sortedRecords[index - ], m_records))
    {
        uint32_t tmp = m_sortedRecords[index];
        m_sortedRecords[index] = m_sortedRecords[index - ];
        m_sortedRecords[index - ] = tmp;
        --index;
    }
    return index;
}

// 返回值:
// -1        :    表示插入失败
// 非负数    :    表示新插入的元素的排名
template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC /*= true*/>
int32_t VectorBasedRank<RECORD, KEY, INIT_SIZE, ASC>::Insert(const RECORD &record)
{
    // 超出容量上限
    if (m_records.size() >= Capacity())
    {
        ;
    }
    // Key 重复
    if (m_keyMapRecords.find(record.Key()) != m_keyMapRecords.end())
    {
        ;
    }
    m_records.push_back(record);
    uint32_t index = m_records.size() - ;
    m_sortedRecords.push_back(index);
    m_keyMapRecords[record.Key()] = index;
    return AdjustIndex(index);
}

template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC /*= true*/>
void VectorBasedRank<RECORD, KEY, INIT_SIZE, ASC>::QSort(int32_t start, int32_t end, RECORDS_SORTED_INDEX &recordIndexs, const RECORDS &records)
{
    if (start >= end){ return; }
    uint32_t i = start, j = end;
    uint32_t tmp = recordIndexs[i];
    while (i < j)
    {
        while (i < j && Less(tmp, recordIndexs[j], records)){ --j; }
        if (i < j)
        {
            recordIndexs[i] = recordIndexs[j];
            ++i;
        }
        while (i < j && !Less(tmp, recordIndexs[i], records)){ ++i; }
        if (i < j)
        {
            recordIndexs[j] = recordIndexs[i];
            --j;
        }
    }
    recordIndexs[i] = tmp;
    QSort(start, i - , recordIndexs, records);
    QSort(i + , end, recordIndexs, records);
}

template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC /*= true*/>
bool VectorBasedRank<RECORD, KEY, INIT_SIZE, ASC>::Less(const uint32_t left, const uint32_t right,const RECORDS &records)
{
    if (left < records.size() && right < records.size())
    {
        if (ASC)
        {
            return records[left] < records[right];
        }
        else
        {
            return !(records[left] < records[right]);
        }
    }
    return false;
}

template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC /*= true*/>
int32_t VectorBasedRank<RECORD, KEY, INIT_SIZE, ASC>::Load(const RECORDS &records)
{
    m_records.clear();
    m_sortedRecords.clear();
    m_keyMapRecords.clear();
    m_records.reserve(INIT_SIZE);
    m_sortedRecords.reserve(INIT_SIZE);
    ; i < records.size(); ++i)
    {
        m_records.push_back(records[i]);
        m_sortedRecords.push_back(i);
        m_keyMapRecords[records[i].Key()] = i;
    }
    QSort(, m_sortedRecords.size() - , m_sortedRecords, m_records);
    ;
}

template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC /*= true*/>
void VectorBasedRank<RECORD, KEY, INIT_SIZE, ASC>::DisplayMapRecords()
{
    for (typename RECORDS_KEY_MAP::const_iterator it = m_keyMapRecords.begin(); it != m_keyMapRecords.end(); ++it)
    {
        m_records[it->second].Display();
    }
    printf("------\n");
}

template<typename RECORD, typename KEY, uint32_t INIT_SIZE, bool ASC /*= true*/>
void VectorBasedRank<RECORD, KEY, INIT_SIZE, ASC>::DisplaySortedRecords()
{
    ; i < m_sortedRecords.size(); ++i)
    {
        m_records[m_sortedRecords[i]].Display();
    }
    printf("------\n");
}

#endif
#include <stdint.h>
#include <stdio.h>
#include "rank.h"

struct StarInfo
{
    int32_t roleid, likes;
    StarInfo() :likes(), roleid(){}
    StarInfo(int32_t like) :likes(like), roleid( - like){}
    bool operator < (const StarInfo &info) const
    {
        return likes < info.likes;
    }
    int32_t Key() const
    {
        return roleid;
    }
    void Display()
    {
        printf("roleid = %d,likes = %d\n", roleid, likes);
    }
};

int32_t main()
{
    StarInfo infos[] = { , , , , , , , , , , , ,  };
    StarInfo infos2[] = { , ,  };
    std::vector<StarInfo> vecInfos(infos, infos + ]));
    std::vector<StarInfo> vecInfos2(infos2, infos2 + ]));
    VectorBasedRank<StarInfo, int32_t, , true> ranks;
    ranks.Load(vecInfos);
    ranks.DisplaySortedRecords();
    // ranks.DisplayMapRecords();
    ; i < ]); ++i)
    {
        StarInfo *pInfo = ranks.RecordByKey(infos[i].Key());
        if (pInfo)
        pInfo->likes *= ;
        pInfo->Display();
        printf("------\n");
        ranks.Adjust();
        ranks.DisplaySortedRecords();
        // ranks.DisplayMapRecords();
    }
    getchar();
    ;
}

C++ 支持两种索引的排行榜模板的更多相关文章

  1. Spring WebFlux, 它是一种异步的, 非阻塞的, 支持背压(Back pressure)机制的Web 开发WebFlux 支持两种编程风(姿)格(势) 使用@Controller这种基于注解

    概述 什么是 Spring WebFlux, 它是一种异步的, 非阻塞的, 支持背压(Back pressure)机制的Web 开发框架. 要深入了解 Spring WebFlux, 首先要了知道 R ...

  2. wdcp支持两种安装方式

    v3.2版本已发布,支持多PHP版本共存共用,支持SSL证书,更多可看论坛 v3版讨论区 更多安装说明请看 http://www.wdlinux.cn/bbs/thread-57643-1-1.htm ...

  3. Springboot中IDE支持两种打包方式,即jar包和war包

    Springboot中IDE支持两种打包方式,即jar包和war包 打包之前修改pom.xml中的packaging节点,改为jar或者war    在项目的根目录执行maven 命令clean pa ...

  4. Linux 下wdcp支持两种安装方式

    wdcp支持两种安装方式1 源码编译 此安装比较麻烦和耗时,一般是20分钟至一个小时不等,具体视机器配置情况而定2 RPM包安装 简单快速,下载快的话,几分钟就可以完成源码安装(ssh登录服务器,执行 ...

  5. Neo4j 两种索引Legacy Index与Schema Index区别

    Legacy Indexes 在Neo4j 2.0版本之前,Legacy index被称作indexes.这个索引是通过外部图存储在外的Lucene实现,允许“节点”和“联系”以key:value键值 ...

  6. kubernetes1.4新特性:支持两种新的卷插件

    背景介绍 在Kubernetes中卷的作用在于提供给POD持久化存储,这些持久化存储可以挂载到POD中的容器上,进而给容器提供持久化存储. 从图中可以看到结构体PodSpec有个属性是Volumes, ...

  7. AQS 支持两种同步方式?

    1.独占式 2.共享式 这样方便使用者实现不同类型的同步组件,独占式如 ReentrantLock,共享式如 Semaphore,CountDownLatch,组合式的如 ReentrantReadW ...

  8. k8s 创建资源的两种方式 - 每天5分钟玩转 Docker 容器技术(124)

    命令 vs 配置文件 Kubernetes 支持两种方式创建资源: 1. 用 kubectl 命令直接创建,比如: kubectl run nginx-deployment --image=nginx ...

  9. WordPress引入css/js两种方法

    WordPress引入css/js 是我们制作主题时首先面对的一个难点,任何一款主题都要加载自己的css,js,甚至很有可能还需要加载Jquery文件,网上方法特多,说法不一,我们今天借鉴wordpr ...

随机推荐

  1. php上传图片文件常用的几个方法

    1. 前台 <form class="add-form" method="post" action="/person/save" en ...

  2. WINFORM中的COMBOX模糊查询

    有的时候下拉框中的元素过多不好查询,可以考虑进行模糊过滤查询. 在类文件的designer.cs中找到定义combox的模块,加入以下两行代码即可: this.combox.AutoCompleteM ...

  3. iOS中滤镜处理及相关内存泄漏问题的解决

    最近工作之余在做一个美图秀秀的仿品 做到滤镜这块的时候  自己就参考了网上几位博主(名字忘了记,非常抱歉)的博客,但是发现跟着他们的demo做的滤镜处理,都会有很严重的内存泄漏,于是就自己按照大体的思 ...

  4. VR系统的组成

    转载请声明转载地址:http://www.cnblogs.com/Rodolfo/,违者必究. 一个典型的虚拟现实系统主要由计算机.输入/输出设备.应用软件和数据库等部分组成. 1.计算机 在虚拟现实 ...

  5. 哈,我自己翻译的小书,马上就完成了,是讲用python处理大数据框架hadoop,spark的

    花了一些时间, 但感觉很值得. Big Data, MapReduce, Hadoop, and Spark with Python Master Big Data Analytics and Dat ...

  6. 在IntelliJ IDEA中添加框架支持时找不到Hibernate的解决办法

    问题描述 第一次在Add Frameworks support界面中添加hibernate支持的时候,异常中断,导致没有成功添加. 第二次进入Add Frameworks support窗口时,发现找 ...

  7. js调试--查找dom对象绑定的函数

    点击最右侧的js文件. 选中函数upload_pic_box,右击,选择在控制台中调试,或者在控制台直接输入该函数 点击最后一行代码会打开该函数所在的js文件

  8. IDF实验室:牛刀小试

    被改错的密码[从格式和长度来推测出是MD5] 迷醉..人生第一道ctf题?据说是因为看起来像是MD5加密的格式,但是数了一下发现有33个字符,就推测???熊孩子多敲了一位进去.从32个变33个了,然后 ...

  9. sql 动态行转列

    create table u01 (医案编号 varchar(5),药物编号 varchar(5)) insert into u01 select '01','01' union all select ...

  10. linux(centos)搭建SVN服务器

    安装步骤如下: 1.yum install subversion   2.输入rpm -ql subversion查看安装位置,如下图:   我们知道svn在bin目录下生成了几个二进制文件. 输入 ...