C++ 支持两种索引的排行榜模板
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++ 支持两种索引的排行榜模板的更多相关文章
- Spring WebFlux, 它是一种异步的, 非阻塞的, 支持背压(Back pressure)机制的Web 开发WebFlux 支持两种编程风(姿)格(势) 使用@Controller这种基于注解
概述 什么是 Spring WebFlux, 它是一种异步的, 非阻塞的, 支持背压(Back pressure)机制的Web 开发框架. 要深入了解 Spring WebFlux, 首先要了知道 R ...
- wdcp支持两种安装方式
v3.2版本已发布,支持多PHP版本共存共用,支持SSL证书,更多可看论坛 v3版讨论区 更多安装说明请看 http://www.wdlinux.cn/bbs/thread-57643-1-1.htm ...
- Springboot中IDE支持两种打包方式,即jar包和war包
Springboot中IDE支持两种打包方式,即jar包和war包 打包之前修改pom.xml中的packaging节点,改为jar或者war 在项目的根目录执行maven 命令clean pa ...
- Linux 下wdcp支持两种安装方式
wdcp支持两种安装方式1 源码编译 此安装比较麻烦和耗时,一般是20分钟至一个小时不等,具体视机器配置情况而定2 RPM包安装 简单快速,下载快的话,几分钟就可以完成源码安装(ssh登录服务器,执行 ...
- Neo4j 两种索引Legacy Index与Schema Index区别
Legacy Indexes 在Neo4j 2.0版本之前,Legacy index被称作indexes.这个索引是通过外部图存储在外的Lucene实现,允许“节点”和“联系”以key:value键值 ...
- kubernetes1.4新特性:支持两种新的卷插件
背景介绍 在Kubernetes中卷的作用在于提供给POD持久化存储,这些持久化存储可以挂载到POD中的容器上,进而给容器提供持久化存储. 从图中可以看到结构体PodSpec有个属性是Volumes, ...
- AQS 支持两种同步方式?
1.独占式 2.共享式 这样方便使用者实现不同类型的同步组件,独占式如 ReentrantLock,共享式如 Semaphore,CountDownLatch,组合式的如 ReentrantReadW ...
- k8s 创建资源的两种方式 - 每天5分钟玩转 Docker 容器技术(124)
命令 vs 配置文件 Kubernetes 支持两种方式创建资源: 1. 用 kubectl 命令直接创建,比如: kubectl run nginx-deployment --image=nginx ...
- WordPress引入css/js两种方法
WordPress引入css/js 是我们制作主题时首先面对的一个难点,任何一款主题都要加载自己的css,js,甚至很有可能还需要加载Jquery文件,网上方法特多,说法不一,我们今天借鉴wordpr ...
随机推荐
- .NET LINQ 限定符操作
限定符操作 限定符运算返回一个 Boolean 值,该值指示序列中是否有一些元素满足条件或是否所有元素都满足条件. 方法 方法名 说明 C# 查询表达式语法 Visual Basic 查询表 ...
- tp框架之查询
//数据访问 //造模型对象 $nation = D("Nation"); //查询 //$a = $nat ...
- 简单Java算法程序实现!斐波那契数列函数~
java编程基础--斐波那契数列 问题描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 思路:可能出现的情况:(1) n=1 ,一种方法 ;(2)n=2 ...
- 关联挖掘和Aprioir算法
Apriori算法 优点:易编码实现 缺点:在大数据集上可能较慢 适用数据类型:数值型或者标称型 算法过程: 关联分析是一种在大规模数据集中寻找有意思的关系的任务,这里的有意思的关系有两种:频繁项集( ...
- Build2016上值得一看的大数据相关Session
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:Build2016开完很久了,现在才来回顾下,就说说那些和大数据相关的Session, ...
- ASP.NET4.5Web API及非同步程序开发系列(3)
接着上一篇博客的内容做一个补充,正好是一个大哥提出来的,我们看看一个有趣的现象. 请求相关问题的补充: 我们先在Controller中的定义一个我们在前一篇博客中已经测试过的方法如下: public ...
- Python学习笔记(二)——HelloWorld
一.交互式化环境下书写代码 二.使用文本编辑器编辑.py文件 1.建议,使用Nodepad++,好看,免费,度娘直接搜素即可. 2.编写代码 3.保存为.py结尾的文件 4.使用cmd,打开到文件所在 ...
- 关于vector的内存释放问题
以前一直想当然的以为vector 的clear()函数会保证释放vector的内存,今天网上一查资料发现完全不是我想象的那样子. 比如有如下代码: tempObject obj1; tempObjec ...
- 比管理员(administrator)更高权限的TrustedInstaller
http://www.gezila.com/tutorials/9664.html 什么是TrustedInstaller管理权限 ?好多朋友都在使用Windows7系统.在使用过程中,有些朋友在删除 ...
- solr连接数据库配置
一般要搜索的信息都是被存储在数据库里面的,但是我们不能直接搜数据库,所以只有借助Solr将要搜索的信息在搜索服务器上进行索引,然后在客户端供客户使用. 一.链接数据库 1. SQL配置 拿SQL Se ...