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 ...
随机推荐
- eclipse安装genymotion插件
1.打开eclipse,在界面上点击"Help"按钮,在弹出来的下拉菜单中选择"Install New Software..."选项.系统弹出"Ins ...
- linux升级openssh
升级sshd到OpenSSH-6.7并删除老版本ssh 1)升级前准备 查看是否缺包 # rpm -qa | egrep "gcc|make|perl|pam|pam-devel" ...
- C的数值取反操作
今儿在代码中发现一句"return x? ~0 : 0;"对~0这个取反操作相关的知识又还给老师了.一查,查到下面一道题,弄过来贴上. //-------------------- ...
- sqlserver 行列转换
http://www.cnblogs.com/zhangzt/archive/2010/07/29/1787825.html PIVOT用于将列值旋转为列名(即行转列),在SQL Server 200 ...
- 【Java EE 学习 15】【自定义数据库连接池之动态代理的使用】
一.动态代理的作用 使用动态代理可以拦截一个对象某个方法的执行,并执行自定义的方法,其本质是反射 优点:灵活 缺点:由于其本质是反射,所以执行速度相对要慢一些 二.数据库连接池设计思想 1.为什么要使 ...
- UC浏览器 分享到朋友圈和微信好友 分类: JavaScript 2015-04-28 14:45 615人阅读 评论(1) 收藏
用手机UC浏览器访问新浪微博,会注意到有这样的两个分享按钮: 在手机端浏览器里,点击分享按钮,就可以启动微信客户端并分享到微信.研究了下其源代码,存在这样的一个js:http://mjs.sinaim ...
- wp8 入门到精通 仿美拍评论黑白列表思路
static bool isbool = false; private void BindGameDelete() { Tile tile = new Tile(); List<Color> ...
- 同步、更新、下载Android Source & SDK from 国内镜像站(转载)
同步.更新.下载Android Source & SDK from 国内镜像站 转自: 同步.更新.下载Android Source & SDK from 国内镜像站 Download ...
- 玩转GIT
远程代码覆盖本地 解决方法: 1.如果还没有 commit 的话,可以用 git checkout . 这样将使所有代码还原到最后一次 commit 的状态 2.如果已经 commit 了,最简单的方 ...
- jquery取值
1. 如何用jquery获取<input id="test" name="test" type="text"/>中输入的值?$( ...