快速查询大量数据的hash_table

原创 2007年09月14日 15:16:00

      记得有一次面试题目:求一图片中RGB值最多的那个值,当时我将RGB作为索引,将这个RGB值出现的次数作为值放到std::map中,百万级的数据插入显得有些慢,感觉不好,前些日子我要处理100W条数据,使用的hash_table,对hash_table有所研究,今天针对这个题目花了1个多小时又写了一个hash_table,将一图片中的所有RGB中插到hash_table,查询速度在毫秒级,很适合处理百万组的数据

头文件:

struct hashFun
{
 size_t operator()(int nVal) const
 {
  char szVal[64] = {0};
  _itoa(nVal, szVal, 10);
  
  const char* psz = szVal;
  
  unsigned long _hash = 0;
  for (; *psz != 0; ++psz)
  {
   _hash *= 16777619;
   _hash ^= (unsigned long) (unsigned short&)*psz;
  }
  return _hash;
 }
};

struct tableNode
{
 int    nValue;
 DWORD    nKey;
 int    nCount;            //这个元素的个数
 tableNode*  pNext;
};
struct BoxVec
{
 int     nCount;        //这个桶下的元素的类型的个数,可能不同的数在同一个桶下
 int     nMaxNum;       //这个桶下这个元素出现的次数
 int     nVal;
 tableNode*  pHead;
};

class CMyHasTable 
{
public:
 CMyHasTable(const int* pBoxSize, int nBoxCount, int nLevel);
 ~CMyHasTable();
private:
 int        m_nBoxCount;        //桶增长级数个数
 const int*       m_pBoxSize;         //桶级数的值
 
 int        m_nBox;           //桶的大小
 int        m_nLow;           //桶个数的最小值
 int        m_nHight;         //桶个数的最大值
 int        m_nLevel;         //当前桶级数的索引
 
 BoxVec*    m_pBoxs;
 int        m_nSize;         //元素的个数
public:
 void  Insert(int nVale);
 int   FindMaxCount();
private:
 inline DWORD GetBoxIndex(DWORD key) const
 {
  return key & (m_nBox - 1);
 }

 inline DWORD GetBoxIndex(DWORD key, int nNewBox) const
 {
  return key & (nNewBox - 1);
 }
private:
 tableNode* Find(tableNode node);
 void IncreaseLevel();
 void SwitchLevel(int nNewLevel);
 void UpBoxMaxCount(int nIndex);
};

.cpp文件

CMyHasTable::CMyHasTable(const int* pBoxSize, int nBoxCount, int nLevel)
{
   m_pBoxSize = pBoxSize;
   m_nBoxCount = nBoxCount;
   m_nLevel = nLevel;

   m_nHight = m_nBox = m_pBoxSize[m_nLevel];
   m_nLow = m_nLevel > 0 ? m_pBoxSize[m_nLevel - 1]/2 : 0;

   m_pBoxs = new BoxVec[m_nBox];
   memset(m_pBoxs, 0, sizeof(BoxVec) * m_nBox);

   m_nSize = 0;
}

CMyHasTable::~CMyHasTable()
{
  for (int i = 0; i < m_nBox; ++i)
 {
  tableNode* p = m_pBoxs[i].pHead;
  while (p != NULL)
  {
   tableNode* q = p->pNext;
   delete p;
   p = q;
  }
 }
 delete[] m_pBoxs;
}

void CMyHasTable::Insert(int nVale)
{
 tableNode valNode;
 valNode.nValue = nVale;
 valNode.nKey = hashFun()(nVale);
 valNode.pNext = NULL;

 tableNode* pNode = Find(valNode);
 if (pNode == NULL)
 {
   m_nSize ++;

         tableNode* pNew = new tableNode;
   *pNew = valNode;

   pNew->nCount = 1;
  
   DWORD dwBoxIndex = GetBoxIndex(valNode.nKey);
   pNew->pNext = m_pBoxs[dwBoxIndex].pHead;
   m_pBoxs[dwBoxIndex].pHead = pNew;

   m_pBoxs[dwBoxIndex].nCount++;
   m_pBoxs[dwBoxIndex].nMaxNum = 1;
   m_pBoxs[dwBoxIndex].nVal = nVale;

   if (m_nSize >= m_nHight)
   IncreaseLevel();

 }
 else
 {
  pNode->nCount++;
  DWORD dwBoxIndex = GetBoxIndex(pNode->nKey);
  UpBoxMaxCount(dwBoxIndex);  
 }

}

int CMyHasTable::FindMaxCount()
{
   int nMaxCount = m_pBoxs[0].nMaxNum;
   int nIndex = 0;
   for (int i = 1; i < m_nBox; i++)
   {
    if (nMaxCount < m_pBoxs[i].nMaxNum)
    {
     nMaxCount = m_pBoxs[i].nMaxNum;
     nIndex = i;
    }
   }
   return m_pBoxs[nIndex].nVal;
}


void CMyHasTable::UpBoxMaxCount(int nIndex)
{
    tableNode* p = m_pBoxs[nIndex].pHead;
 tableNode* q = p;
    int nMax = p->nCount;
 while(p->pNext)
 {
  if (nMax < p->nCount)
  {
   nMax = p->nCount;
   q = p;
  }
  p = p->pNext;
 }
 m_pBoxs[nIndex].nMaxNum = nMax;
 m_pBoxs[nIndex].nVal = q->nValue;
}

tableNode* CMyHasTable::Find(tableNode node)
{
 DWORD short_key = GetBoxIndex(node.nKey);
 tableNode* p = m_pBoxs[short_key].pHead;

 while (p != NULL)
 {
  if (p->nKey == node.nKey)
  {
   if (p->nValue == node.nValue)
    return p;
  }
  p = p->pNext;
 }
 return NULL;
}


void CMyHasTable::IncreaseLevel()
{
  if (m_nLevel < m_nBoxCount - 1)
   SwitchLevel(m_nLevel + 1);
  else
   m_nHight = 0x20000000;
}

void CMyHasTable::SwitchLevel(int nNewLevel)
{
    m_nLevel = nNewLevel;
 int nNewBox = m_pBoxSize[m_nLevel];
 BoxVec* pNewBoxs = new BoxVec[nNewBox]; 
 memset(pNewBoxs, 0, sizeof(BoxVec) * nNewBox);


    for (int i = 0; i < m_nBox; ++i)
 {
  tableNode* p = m_pBoxs[i].pHead;
  tableNode*  q = NULL;;
        int nCout = m_pBoxs[i].nCount;
  int nMax = m_pBoxs[i].nMaxNum;
  while (p != NULL)
  {
   q = p->pNext;
   DWORD sht_key = GetBoxIndex(p->nKey, nNewBox);
   p->pNext = pNewBoxs[sht_key].pHead;
   pNewBoxs[sht_key].pHead = p;
   p = q;

   pNewBoxs[sht_key].nCount = nCout;
   pNewBoxs[sht_key].nMaxNum = nMax;

  }
 }
 
 m_nHight = m_nBox = m_pBoxSize[m_nLevel];
 m_nLow = m_nLevel > 0 ? m_pBoxSize[m_nLevel - 1]/2 : 0;
 
 delete m_pBoxs;
 m_pBoxs = pNewBoxs;
}

sqlit大量数据快速查询(1)

最近做一个关于骗子,骚扰电话号码查询。有大约30万条数据,由于没有服务器支持只好,从网上下载下来做成一个tel.db3用于识别骗子号码。 实现功能如下: 1.一键查通话记录中的电话 2.一键...
  • geek87
  • geek87
  • 2012年02月28日 19:21
  • 645

如何在1000万条记录中快速检索? 数据追踪

一些大规模的系统,如人口系统的数据甚至超过了1000万条,可谓海量。那么,如何实现快速地从这些超大容量的数据库中提取数据(查询)、分析、统计以及提取数据后进行数据分页已成为各地系统管理员和数据库管理员...
  • chenghaibing2008
  • chenghaibing2008
  • 2013年01月14日 14:41
  • 9082

Hash_table 的简单使用说明

  Hash_table 的简单使用说明                                                                               ...
  • ruliang
  • ruliang
  • 2007年04月17日 14:56
  • 1095

C++ STL源码学习(之hash_table篇)

这是SGI STL哈希表的实现,由于平时见到较少,因此在源代码中注释做的较为详细...
  • u011907342
  • u011907342
  • 2014年10月11日 22:39
  • 1092

数据快速查询的新方法

/**//* * Main.java * * Created on 2006年11月20日, 下午4:29 * * To change this template, choose Tools | Te...
  • longronglin
  • longronglin
  • 2006年11月26日 16:27
  • 897

没有索引也可以快速查询

仓储系统有张表,4000万数据,按照创建时间清理。创建时间上没有索引,不过数据是按照创建时间一条条的insert的。这样就写了个脚本按照id升序每次处理2000个,然后删除掉。这样只要扫描到的数据满足...
  • ylqmf
  • ylqmf
  • 2014年04月18日 15:59
  • 13724

jQuery 数据列表快速查询

本文章摘编、转载需要注明来源 http://blog.csdn.net/shadowsick/article/details/8881892 我们的table列表一般有多条数据,如何让用户快...
  • shadowsick
  • shadowsick
  • 2013年05月03日 21:02
  • 6310

hash_table

Hash解决冲突的方法 总体有三种方法: 1.    开放地址法 使用地址长度为x 则为arr[i]%x找到位置 2.    随机探测法,使用地址长度为x生成一个随机数链r,(arr[i]+r[...
  • hardwork_zx
  • hardwork_zx
  • 2016年10月14日 19:39
  • 65

hash_table和STL map

SOLUTION Compare and contrast Hash Table vs. STL map 在hash_table中value通过使用哈希函数产生的关键字来存储。因此在hash ta...
  • f81892461
  • f81892461
  • 2013年02月12日 19:23
  • 1269

几十上百万行,如何快速查询出表数据

/* 函数名称: sp_GetRecordFromPage 函数功能: 获取指定页的数据 参数说明:@tblName 包含数据的表名 @fldNam...
  • zfanlong1314
  • zfanlong1314
  • 2011年12月29日 22:32
  • 847
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:快速查询大量数据的hash_table
举报原因:
原因补充:

(最多只允许输入30个字)