哈希链表实现的LRU缓存算法
来源:互联网 发布:苏州加工中心编程招聘 编辑:程序博客网 时间:2024/05/17 21:39
在做三角网格文件转换的时候需要对从文件中读取的顶点坐标进行缓存,于是索性做了一个哈希缓存以提高访问效率,同时以LRU原则在缓存满的情况下清楚缓存中的单元。在hash表中我用了最简单的取摸的方法,由于原顶点有一个索引而且这种索引连续,所以取摸的方法已经可以达到平均散列。在处理碰撞的时候我使用了链表,而所有在缓存中的单元都按放入缓存的时间串成一个链表,这样在清除单元的时候选择队尾的元素进行清除即可。
/* manipulations for the vertex binary file there is a least recent used hash cache for reading vertices the hash bucket with lru list is like this _____________ _____ _____ |bucket_head| ----> | | -> .. -> | | -> Null _____________ _____ _____ |bucket_head| ----> | | -> .. -> | | -> Null _____________ |bucket_head| ----> Null ... _____________ _____ _____ |bucket_head| ----> | | -> .. -> | | -> Null while all the nodes in the buckets are linked based on the time they are accessed, thus the newly accessed node are inserted into the head of the lru list, if it has already existed in the list, it will be deleted from the list first author: waytofall*/#include <fstream>#include <iostream>using namespace std;class VertexBinary{ typedef struct __Vertex { float x, y, z; } __Vertex; typedef struct __CacheUnit { struct __CacheUnit *bucket_prev; // bucket pointer struct __CacheUnit *bucket_next; struct __CacheUnit *use_prev; // lru pointer struct __CacheUnit *use_next; __Vertex vert; unsigned int index; } __CacheUnit;public: VertexBinary(); ~VertexBinary(); /* write */ int openForWrite(const char* filename); int closeWriteFile(); int writeVertexFloat(float x, float y, float z); /* read */ int initCache(unsigned int size); int openForRead(const char* filename); int indexedRead(unsigned int index); int closeReadFile(); float getXFloat(); float getYFloat(); float getZFloat(); void writeCacheDebug();private: void insertBucketList(__CacheUnit **head, __CacheUnit *new_unit); void deleteBucketList(__CacheUnit **head, __CacheUnit *unit); void insertLruList(__CacheUnit *new_unit); void deleteLruList(__CacheUnit *unit); int indexedReadFromFile(unsigned int index, float &x, float &y, float &z);private: ifstream fin; ofstream fout; unsigned int cache_size; unsigned int cache_count; __CacheUnit **cache_bucket; __CacheUnit *lru_head; __CacheUnit *lru_tail; __CacheUnit *current_unit;public: unsigned int read_count; unsigned int hit_count;};
/* manipulations for the vertex binary file author: waytofall*/#include "vert_bin.h"#include <fstream>#include <iostream>// if dump the cache to the file//#define _WRITE_CACHE_DEBUGVertexBinary::VertexBinary(){ cache_bucket = NULL; cache_size = 0; cache_count = 0;}VertexBinary::~VertexBinary(){ if (cache_bucket) { delete[] cache_bucket; }}int VertexBinary::openForWrite(const char *filename){ fout.open(filename, ios::out | ios::binary); if(fout.good()) return 1; else return 0;}int VertexBinary::writeVertexFloat(float x, float y, float z){ if (!fout.good()) { return 0; } fout.write((char*)&x, sizeof(float)); fout.write((char*)&y, sizeof(float)); fout.write((char*)&z, sizeof(float)); return 1;}int VertexBinary::openForRead(const char* filename){ fin.open(filename, ios::binary | ios::in); if (fin.good()) return 1; else return 0;}int VertexBinary::indexedRead(unsigned int index){ if (cache_size <= 0) { cerr << "#error : no cache while indexed reading" << endl; return 0; } read_count ++; int hash_index = index % cache_size; __CacheUnit *hit_unit = NULL; // check if the cache hit if(cache_bucket[hash_index]) { __CacheUnit *bucket_head; for(bucket_head = cache_bucket[hash_index]; bucket_head; bucket_head = bucket_head->bucket_next) { if (bucket_head->index == index) { hit_unit = bucket_head; break; } } } // the the cache has the queried unit if (hit_unit) { deleteLruList(hit_unit); insertLruList(hit_unit); current_unit = hit_unit; hit_count ++; return 1; } // the cache doesn't store the queried unit // check if needed to delete the least recent used unit if (cache_count == cache_size) { // delete the tail unit from the two lists hit_unit = lru_tail; deleteBucketList(&cache_bucket[hit_unit->index % cache_size], hit_unit); deleteLruList(hit_unit); } else { hit_unit = new __CacheUnit(); cache_count ++; } hit_unit->index = index; indexedReadFromFile(index, hit_unit->vert.x, hit_unit->vert.y, hit_unit->vert.z); insertBucketList(&cache_bucket[hash_index], hit_unit); insertLruList(hit_unit); current_unit = hit_unit; #ifdef _WRITE_CACHE_DEBUG writeCacheDebug(); #endif return 1;}int VertexBinary::initCache(unsigned int size){ if(size <= 0) return 0; cache_size = size; cache_bucket = new __CacheUnit*[cache_size]; for(unsigned int i = 0; i < cache_size; i ++) { cache_bucket[i] = NULL; } cache_count = 0; lru_head = NULL; lru_tail = NULL; read_count = 0; hit_count = 0; return 1;}// insert from headvoid VertexBinary::insertBucketList(__CacheUnit **head, __CacheUnit *new_unit){ new_unit->bucket_prev = NULL; new_unit->bucket_next = *head; if (*head) { (*head)->bucket_prev = new_unit; } (*head) = new_unit;}// delete from any placevoid VertexBinary::deleteBucketList(__CacheUnit **head, __CacheUnit *unit){ if(*head == NULL) return; if(*head == unit) { *head = unit->bucket_next; } if (unit->bucket_prev) { unit->bucket_prev->bucket_next = unit->bucket_next; } if (unit->bucket_next) { unit->bucket_next->bucket_prev = unit->bucket_prev; }}void VertexBinary::insertLruList(__CacheUnit *new_unit){ new_unit->use_prev = NULL; new_unit->use_next = lru_head; if (lru_head) { lru_head->use_prev = new_unit; } if (lru_head == NULL) { lru_tail = new_unit; } lru_head = new_unit;}// delete the lru list from the tailvoid VertexBinary::deleteLruList(__CacheUnit *unit){ if (lru_head == NULL) return; if (unit->use_next) { unit->use_next->use_prev = unit->use_prev; } if (unit->use_prev) { unit->use_prev->use_next = unit->use_next; } if (lru_head == unit) { lru_head = unit->use_next; } if (lru_tail == unit) { lru_tail = unit->use_prev; }}int VertexBinary::indexedReadFromFile(unsigned int index, float &x, float &y, float &z){ if (!fin.good()) { return 0; } fin.seekg(index * 3 * sizeof(float)); fin.read((char*)&x, sizeof(float)); fin.read((char*)&y, sizeof(float)); fin.read((char*)&z, sizeof(float)); return 1;}int VertexBinary::closeWriteFile(){ fout.close(); return 1;}int VertexBinary::closeReadFile(){ fin.close(); return 1;}float VertexBinary::getXFloat(){ return current_unit->vert.x;}float VertexBinary::getYFloat(){ return current_unit->vert.y;}float VertexBinary::getZFloat(){ return current_unit->vert.z;}void VertexBinary::writeCacheDebug(){ int i, c1, c2; using namespace std; ofstream fout ("cache_dump.txt", ios::out | ios::app); __CacheUnit *pUnit; for(i = 0, c1 = 0; i < cache_size; i ++) { if (cache_bucket[i] == NULL) continue; fout << "bucket #" << i << ": "; for(pUnit = cache_bucket[i], c2 = 0; pUnit; pUnit = pUnit->bucket_next, c2 ++) { fout << pUnit->index << " "; } fout << "count: " << c2 << " " << endl; c1 += c2; } fout << "total count: " << c1 << endl << "lru list: "; for(c1 = 0, pUnit = lru_head; pUnit; pUnit = pUnit->use_next, c1 ++) { fout << pUnit->index << " "; } fout << endl << "lru count: " << c1 << endl << endl; fout.close();}
- 哈希链表实现的LRU缓存算法
- LRU缓存算法实现
- LRU缓存的实现算法讨论
- 基于LRU算法的缓存实现
- LinkedList实现基于LRU算法的缓存
- 简单LRU算法实现缓存
- 简单LRU算法实现缓存
- 简单LRU算法实现缓存
- 简单LRU算法实现缓存
- 缓存中实现LRU算法
- LRU缓存算法Java实现
- Android LRU缓存算法实现
- LinkedHashMap实现LRU缓存算法
- LRU算法的小型缓存
- 蛙蛙推荐: LRU缓存的实现算法讨论
- 缓存算法及LRU的实现(Java)
- 简单LRU算法实现缓存大小的限制策略
- Android使用LinkedHashMap实现一个LRU算法的内存缓存
- 使用Mutex对象
- 给你讲讲硬件协议栈的那些事儿—WIZnet 员工Christina培训笔记(一)
- devExpress之GridView小技巧(二):点击空白处清空选择
- 枚举 Enum
- 如何把excel数据导入到mysql数据库中
- 哈希链表实现的LRU缓存算法
- struts2中的自动、手动验证框架
- 无语啦!!!!
- struts框架-实现文件上传
- CentOS 为普通用户增加sudo权限
- 【android】使用CursorAdapter注意事项
- 圆角框的实现
- Linux 下rm + grep 命令删除除去指定文件的剩余所有文件
- Build type choices are: release | debug