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 粘贴字符串自动添加转义符
eclipse -> Window -> Preferences -> Java -> Editor -> Typing -> 勾选{Escape text whe ...
- listView当中有嵌套了有onClickListener的控件时ListView自身的onItemClick无响应的解决方案
Ref:http://www.cnblogs.com/bluestorm/archive/2013/03/24/2979557.html android:descendantFocusability ...
- hive数据操作
mdl是数据操作类的语言,包括向数据表加载文件,写查询结果等操作 hive有四种导入数据的方式 >从本地加载数据 LOAD DATA LOCAL INPATH './examples/files ...
- Spring事务管理
Spring是SSH中的管理员,负责管理其它框架,协调各个部分的工作.今天一起学习一下Spring的事务管理.Spring的事务管理分为声明式跟编程式.声明式就是在Spring的配置文件中进行相关配置 ...
- 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 ...
- [CSS]Input标签与图片按钮对齐
页面直接摆放一个input文本框与ImageButton图片按钮,但是发现没有对齐: <input type="text" id="txtQty" /&g ...
- opencv2 使用鼠标绘制矩形并截取和保存矩形区域图像
前言 好长时间没写博文了,今天偷偷懒写篇关于opencv2中鼠标响应操作的文章. 鼠标操作属于用户接口设计,以前一直使用Qt来做,但是如果只需要简单的鼠标,键盘操作,直接调用opencv库的函数也未尝 ...
- poj 3253 Fence Repair
Fence Repair Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 42979 Accepted: 13999 De ...
- 首师大附中互测题:99999999海岛帝国后传:算法大会【D001】
[D001]99999999海岛帝国后传:算法大会[难度:D] ———————————————————————————————————————————————————————————————————— ...
- 探索摸寻之XCode 快捷键
注释/反注释 Command+/ 模拟器没有Home键 在模拟器的应用界面 Command+Shift+h 返回上一级 (1920,24寸显示器,因此不是分辨率问题)