Hash表

#ifndef __HASH_TABLE_H__
#define __HASH_TABLE_H__
#include <afxtempl.h>ide

#define M 200    // 桶的容量。
#define MAX_NUM  32   // 目錄的深度。orm

typedef struct _head{
 int g;   //全局深度
 long number; //節點總數
}Head;it

template <class T>
class TreeNode{
public:
 int  n;   //節點個數
 int  g;   //局部深度
 T    key[M];
};io

//////////////////////////////////////////////////////////////////
// CHashTable 是M路Hash表class

template <class T>
class CHashTable{
public:
 CHashTable(){m_head.g = 1; m_head.number = 0;m_IsUsed = 0;};
 ~CHashTable(){};sed

public:
 BOOL Open(CString& FileName);
 void Close();
 BOOL InsertNode(T& x);
 T * SearchNode(CString& pName);
 T * SearchNode(long pID);
 CList<T, T&> * SearchNodeList(long pType);//with h_id
 CList<T, T&> * SearchNodeListEx(long pPrice);// with t_id
 BOOL ChangeNode(T& x);
 BOOL ChangeName(CString& pNewName, CString& pOldName);
 BOOL ChangeID(long pNewID, long pOldID);
 BOOL DeleteNode(CString& pName);
 BOOL DeleteNode(long pID);
 BOOL DeleteNode(T& x);
 long GetCount(){return m_head.number;};List

protected:
 long GetHashNum(CString pName);
 BOOL AddKeyAtNode(TreeNode<T>& pNode, T& pKey);
 BOOL ChangeKeyAtNode(TreeNode<T>& pNode, T& pKey);
 BOOL DeleteKeyAtNode(TreeNode<T>& pNode, T& pKey);
 BOOL DeleteKeyAtNode(TreeNode<T>& pNode, long pID);
 BOOL SearchKeyAtNode(TreeNode<T>& pNode, T& pKey);
 BOOL SearchKeyAtNode(TreeNode<T>& pNode, long pID);
 void GetListAtNode(TreeNode<T>& pNode, long pID);
 void GetListAtNodeEx(TreeNode<T>& pNode, long pID);
 long SearchDelete();file

private:
 CFile m_hFile, m_iFile;
 CList<T, T&> m_List;
 T textTEMP;
 Head m_head;
 int m_IsUsed;di

};while

template <class T>
BOOL CHashTable<T>::Open(CString& FileName)
{
 if(m_IsUsed++)return TRUE;
 int n;
 if((n = FileName.Find(".")) != -1)
  FileName = FileName.Left(n);
 CString pDataFile = FileName + ".pm";
 CString pIndexFile = FileName + ".idx";
 if(!m_hFile.Open(pDataFile, CFile::modeReadWrite))
 {
  m_head.g = 1;
  m_head.number = 0;
  if(!m_hFile.Open(pDataFile, CFile::modeCreate|CFile::modeReadWrite) ||
   !m_iFile.Open(pIndexFile, CFile::modeCreate|CFile::modeReadWrite))
       {
   AfxMessageBox("Cann't open the file.\n");
   return FALSE;
  }
  else
  {
   TreeNode<T> pNode;
   pNode.g = 1;
   pNode.n = 0;
   m_hFile.Write(&m_head,sizeof(Head));
   m_hFile.Write(&pNode, sizeof(TreeNode<T>));
   long p = sizeof(Head);
   m_iFile.Write(&p, sizeof(long));
   m_hFile.Write(&pNode, sizeof(TreeNode<T>));
   p += sizeof(TreeNode<T>);
   m_iFile.Write(&p, sizeof(long));

  }
 }
 else {
  if(!m_iFile.Open(pIndexFile, CFile::modeReadWrite))
  {
   AfxMessageBox("Cann't open the file.\n");
   return FALSE;
  }
  m_hFile.Read(&m_head,sizeof(Head));
 }
 return TRUE;
}

template <class T>
void CHashTable<T>::Close()
{
 if(--m_IsUsed)return;
 m_hFile.Close();
 m_iFile.Close();
}

template <class T>
long CHashTable<T>::GetHashNum(CString pName)
{
 if(pName == "")return 0;
 wchar_t buffer[100];
 CString pTempStr = "";
 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pName.LockBuffer(), -1, buffer, pName.GetLength());
 for(long i = 0; i < pName.GetLength(); i++)
 {
  CString temp;
  temp.Format("%d", buffer[i]);
  if(temp == "0")break;
  pTempStr += temp;
 }
 while(pTempStr.GetLength() < (pTempStr[0] > '4' ?9:10))
  pTempStr += "0";
 int n = pTempStr.GetLength();
 if(pTempStr[0] > '4')
 {
  if(n % 8 == 0)
   n--;
  n = n / 8;
  pTempStr.Format("%c%c%c%c%c%c%c%c%c", pTempStr[0], pTempStr[5 * n], pTempStr[1 * n], \
   pTempStr[6 * n], pTempStr[2 * n], pTempStr[7 * n], pTempStr[3 * n], \
   pTempStr[8 * n], pTempStr[4 * n]);
 }
 else
 {
  if(n % 9 == 0)
   n--;
  n = n / 9;
  pTempStr.Format("%c%c%c%c%c%c%c%c%c%c", pTempStr[0], pTempStr[5 * n], pTempStr[1 * n], \
   pTempStr[6 * n], pTempStr[2 * n], pTempStr[7 * n], pTempStr[3 * n], \
   pTempStr[8 * n], pTempStr[4 * n], pTempStr[9 * n]);
 }
 DWORD h = atol(pTempStr.LockBuffer());
 h>>=(MAX_NUM - m_head.g);
 return h;

}

template <class T>
BOOL CHashTable<T>::AddKeyAtNode(TreeNode<T>& pNode, T& pKey)
{
 if( pNode.n >= M)return FALSE;
 int n = pNode.n - 1;
 while((pKey < pNode.key[n])&&(n >= 0))
 {
  memcpy(&pNode.key[n + 1], &pNode.key[n], sizeof(T));
  n--;
 }
 memcpy(&pNode.key[n + 1], &pKey, sizeof(T));
 pNode.n++;
 return TRUE;
}

template <class T>
BOOL CHashTable<T>::ChangeKeyAtNode(TreeNode<T>& pNode, T& pKey)
{
 int n = 0;
 while(pKey > pNode.key[n])n++;
 if(pKey == pNode.key[n])
 {
  memcpy(&pNode.key[n], &pKey, sizeof(T));
  return TRUE;
 }
 return FALSE;
}

template <class T>
BOOL CHashTable<T>::DeleteKeyAtNode(TreeNode<T>& pNode, T& pKey)
{
 int n = 0;
 while(pKey > pNode.key[n])n++;
 if(n < pNode.n)
 {
  for(; n < pNode.n; n++)
   memcpy(&pNode.key[n], &pNode.key[n + 1], sizeof(T));
  pNode.n--;
  return TRUE;
 }
 return FALSE;
}

template <class T>
BOOL CHashTable<T>::DeleteKeyAtNode(TreeNode<T>& pNode, long pID)
{
 int n = 0;
 while((pID != pNode.key[n].id)&&(n < pNode.n))n++;
 if(pID == pNode.key[n].id)
 {
  for(; n < pNode.n; n++)
   memcpy(&pNode.key[n], &pNode.key[n + 1], sizeof(T));
  pNode.n--;
  return TRUE;
 }
 return FALSE;
}

template <class T>
BOOL CHashTable<T>::SearchKeyAtNode(TreeNode<T>& pNode, T& pKey)
{
 int n = 0;
 while(pKey > pNode.key[n])n++;
 if(pKey == pNode.key[n])
 {
  memcpy(&textTEMP, &pNode.key[n], sizeof(T));
  return TRUE;
 }
 return FALSE;
}

template <class T>
BOOL CHashTable<T>::SearchKeyAtNode(TreeNode<T>& pNode, long pID)
{
 int n = 0;
 while((pID != pNode.key[n].id)&&(n < pNode.n))n++;
 if(pID == pNode.key[n].id)
 {
  memcpy(&textTEMP, &pNode.key[n], sizeof(T));
  return TRUE;
 }
 return FALSE;
}

template <class T>
void CHashTable<T>::GetListAtNode(TreeNode<T>& pNode, long pID)
{
 for(int n = 0; n < pNode.n; n++)
  if(pID == pNode.key[n].h_id)
   m_List.AddTail(pNode.key[n]);
}

template <class T>
void CHashTable<T>::GetListAtNodeEx(TreeNode<T>& pNode, long pID)
{
 for(int n = 0; n < pNode.n; n++)
  if(pID == pNode.key[n].t_id)
   m_List.AddTail(pNode.key[n]);
}

template <class T>
long CHashTable<T>::SearchDelete()
{
/* long p=sizeof(Head);
 int q;
 while(p != (long)m_hFile.GetLength())
 {
  m_hFile.Seek(p, CFile::begin);
  m_hFile.Read(&q,sizeof(int));
  if(q==0)return(p);
  p+=sizeof(TreeNode<T>);
 }
*/ m_hFile.Seek(0L, CFile::end);
 
 return m_hFile.GetPosition();
}

template <class T>
BOOL CHashTable<T>::InsertNode(T& x)
{
 TreeNode<T> a, b;
 long p;
 long pHash = GetHashNum(CString(x.name));
 m_iFile.Seek(pHash * sizeof(long), CFile::begin);
 m_iFile.Read(&p, sizeof(long));
 m_hFile.Seek(p, CFile::begin);
 m_hFile.Read(&a, sizeof(TreeNode<T>));
 if(!AddKeyAtNode(a, x))
 {
  long qHash = (long)m_iFile.GetLength();
  a.g++;
  b.n = 0;
  b.g = a.g;
  if(a.g > m_head.g)
  {
   m_head.g++;
   long * buffer = (long *)malloc(qHash);
   m_iFile.Seek(0L, CFile::begin);
   m_iFile.Read(buffer, qHash);
   m_iFile.Seek(0L, CFile::end);
   m_iFile.Write(buffer, qHash);
   free(buffer);
  }
  for(int i = a.n - 1; i >= 0; i--)
  {
   qHash = GetHashNum(CString(a.key[i].name));
   if(qHash == pHash)
   {
    AddKeyAtNode(b, a.key[i]);
    DeleteKeyAtNode(a, a.key[i]);
   }
  }
  qHash = GetHashNum(CString(x.name));
  if(qHash == pHash)
   AddKeyAtNode(b, x);
  else
   AddKeyAtNode(a, x);
  p = SearchDelete();
  m_hFile.Seek(p, CFile::begin);
  m_hFile.Write(&b, sizeof(TreeNode<T>));
  m_iFile.Seek(pHash * sizeof(long), CFile::begin);
  m_iFile.Write(&p, sizeof(long));
 }
 else
 {
  m_hFile.Seek(p, CFile::begin);
  m_hFile.Write(&a, sizeof(TreeNode<T>));
 }
 m_head.number++;
 m_hFile.Seek(0L, CFile::begin);
 m_hFile.Write(&m_head,sizeof(Head));
 return TRUE;
}

template <class T>
BOOL CHashTable<T>::DeleteNode(T& x)
{
 TreeNode<T> a;
 long p;
 long pHash = GetHashNum(CString(x.name));
 m_iFile.Seek(pHash * sizeof(long), CFile::begin);
 m_iFile.Read(&p, sizeof(long));
 m_hFile.Seek(p, CFile::begin);
 m_hFile.Read(&a, sizeof(TreeNode<T>));
 if(DeleteKeyAtNode(a, x))
 {
  m_hFile.Seek(p, CFile::begin);
  m_hFile.Write(&a, sizeof(TreeNode<T>));
  return TRUE;
 }
 return FALSE;
}

template <class T>
BOOL CHashTable<T>::DeleteNode(CString& pName)
{
 TreeNode<T> a;
 long p;
 long pHash = GetHashNum(pName);
 m_iFile.Seek(pHash * sizeof(long), CFile::begin);
 m_iFile.Read(&p, sizeof(long));
 m_hFile.Seek(p, CFile::begin);
 m_hFile.Read(&a, sizeof(TreeNode<T>));
 T pKey;
 strcpy(pKey.name, pName.LockBuffer());
 if(DeleteKeyAtNode(a, pKey))
 {
  m_hFile.Seek(p, CFile::begin);
  m_hFile.Write(&a, sizeof(TreeNode<T>));
  return TRUE;
 }
 return FALSE;
}

template <class T>
BOOL CHashTable<T>::DeleteNode(long pID)
{
 TreeNode<T> a;
 long pHash = sizeof(Head);
 do{
  m_hFile.Seek(pHash, CFile::begin);
  m_hFile.Read(&a, sizeof(TreeNode<T>));
  if(DeleteKeyAtNode(a, pID))
  {
   m_hFile.Seek(pHash, CFile::begin);
   m_hFile.Write(&a, sizeof(TreeNode<T>));
   return TRUE;
  }
  pHash += sizeof(TreeNode<T>);
 }while(pHash < (long)m_hFile.GetLength());
 return FALSE;
}

template <class T>
T * CHashTable<T>::SearchNode(CString& pName)
{
 TreeNode<T> a;
 long p;
 long pHash = GetHashNum(pName);
 m_iFile.Seek(pHash * sizeof(long), CFile::begin);
 m_iFile.Read(&p, sizeof(long));
 m_hFile.Seek(p, CFile::begin);
 m_hFile.Read(&a, sizeof(TreeNode<T>));
 T pKey;
 strcpy(pKey.name, pName.LockBuffer());
 if(SearchKeyAtNode(a, pKey))
 {
  return &textTEMP;
 }
 return NULL;
}

template <class T>
T * CHashTable<T>::SearchNode(long pID)
{
 TreeNode<T> a;
 long pHash = sizeof(Head);
 do{
  m_hFile.Seek(pHash, CFile::begin);
  m_hFile.Read(&a, sizeof(TreeNode<T>));
  if(SearchKeyAtNode(a, pID))
  {
   return &textTEMP;
  }
  pHash += sizeof(TreeNode<T>);
 }while(pHash < (long)m_hFile.GetLength());
 return NULL;
}

template <class T>
CList<T, T&> * CHashTable<T>::SearchNodeList(long pType)//with h_id
{
 TreeNode<T> a;
 long pHash = sizeof(Head);
 m_List.RemoveAll();
 do{
  m_hFile.Seek(pHash, CFile::begin);
  m_hFile.Read(&a, sizeof(TreeNode<T>));
  GetListAtNode(a, pType);
  pHash += sizeof(TreeNode<T>);
 }while(pHash < (long)m_hFile.GetLength());
 return &m_List;
}

template <class T>
CList<T, T&> * CHashTable<T>::SearchNodeListEx(long pType)//with t_id
{
 TreeNode<T> a;
 long pHash = sizeof(Head);
 m_List.RemoveAll();
 do{
  m_hFile.Seek(pHash, CFile::begin);
  m_hFile.Read(&a, sizeof(TreeNode<T>));
  GetListAtNodeEx(a, pType);
  pHash += sizeof(TreeNode<T>);
 }while(pHash < (long)m_hFile.GetLength());
 return &m_List;
}

template <class T>
BOOL CHashTable<T>::ChangeNode(T& x)
{
 TreeNode<T> a;
 long p;
 long pHash = GetHashNum(CString(x.name));
 m_iFile.Seek(pHash * sizeof(long), CFile::begin);
 m_iFile.Read(&p, sizeof(long));
 m_hFile.Seek(p, CFile::begin);
 m_hFile.Read(&a, sizeof(TreeNode<T>));
 if(ChangeKeyAtNode(a, x))
 {
  m_hFile.Seek(p, CFile::begin);
  m_hFile.Write(&a, sizeof(TreeNode<T>));
  return TRUE;
 }
 return FALSE;
}

template <class T>
BOOL CHashTable<T>::ChangeName(CString& pNewName, CString& pOldName)
{
 T s_temp;
 T * p;
 p = SearchNode(pOldName);
 if(p == NULL)return FALSE;
 memcpy(&s_temp, p, sizeof(T));
 DeleteNode(pOldName);
 sprintf(s_temp.name,"%s",pNewName);
 InsertNode(s_temp);
 return TRUE;
}

template <class T>
BOOL CHashTable<T>::ChangeID(long pNewID, long pOldID)
{
 T temp, * p;
 if((p = SearchNode(pOldID)) != NULL)
 {
  memcpy(&temp, p, sizeof(T));
  DeleteNode(temp);
  temp.id = pNewID;
  InsertNode(temp);
  return TRUE;
 }
 else
  return FALSE;
}

#endif

相關文章
相關標籤/搜索