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. eclipse 粘贴字符串自动添加转义符

    eclipse -> Window -> Preferences -> Java -> Editor -> Typing -> 勾选{Escape text whe ...

  2. listView当中有嵌套了有onClickListener的控件时ListView自身的onItemClick无响应的解决方案

    Ref:http://www.cnblogs.com/bluestorm/archive/2013/03/24/2979557.html android:descendantFocusability ...

  3. hive数据操作

    mdl是数据操作类的语言,包括向数据表加载文件,写查询结果等操作 hive有四种导入数据的方式 >从本地加载数据 LOAD DATA LOCAL INPATH './examples/files ...

  4. Spring事务管理

    Spring是SSH中的管理员,负责管理其它框架,协调各个部分的工作.今天一起学习一下Spring的事务管理.Spring的事务管理分为声明式跟编程式.声明式就是在Spring的配置文件中进行相关配置 ...

  5. RHCS 6.5 由于resource-agents-3.9.2-40.el6版本过低导致rgmanager[61164]: [fs] umount failed - REBOOTING问题的解决

    問題描述: RHEL 6.5版本RHCS在disable或者relocate service的時候,會導致節點重啟,查看日誌顯示umount掛载點失敗,日誌如下: Nov 29 16:03:50 ph ...

  6. [CSS]Input标签与图片按钮对齐

    页面直接摆放一个input文本框与ImageButton图片按钮,但是发现没有对齐: <input type="text" id="txtQty" /&g ...

  7. opencv2 使用鼠标绘制矩形并截取和保存矩形区域图像

    前言 好长时间没写博文了,今天偷偷懒写篇关于opencv2中鼠标响应操作的文章. 鼠标操作属于用户接口设计,以前一直使用Qt来做,但是如果只需要简单的鼠标,键盘操作,直接调用opencv库的函数也未尝 ...

  8. poj 3253 Fence Repair

    Fence Repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 42979   Accepted: 13999 De ...

  9. 首师大附中互测题:99999999海岛帝国后传:算法大会【D001】

    [D001]99999999海岛帝国后传:算法大会[难度:D] ———————————————————————————————————————————————————————————————————— ...

  10. 探索摸寻之XCode 快捷键

    注释/反注释 Command+/ 模拟器没有Home键 在模拟器的应用界面 Command+Shift+h 返回上一级 (1920,24寸显示器,因此不是分辨率问题)