• 散列表


    散列表的思想就是把关键值送给一个散列函数,产生出一个散列值,这个值平均分布在一个整数区域中

    =>散列表的实现的细节

    1 当数组足够大时可以直接寻址不需要散列函数,常数操作时间O(1)

       但数据规模远大于散列表大小时,考虑到空间的局限性,需要散列函数使关键值均匀的分开

    2 散列表的装载因子,也就是实际决定散列表运算时间的参数, 数据规模n 除与  散列表数组大小mα = n/m

    3 散列函数核心是采取一些措施尽可能地使关键字均地分开

       确保关键字的独立性 => 构造一个良好的散列函数

    4 当关键值均匀地存储在散列链表里,花费常数操作时间+链表长度(数据规模n 除与 散列表数组大小m )=  O(1)+n/m

        如果散列函数弱爆了,几乎所有值都在一个链表里,那么花费线性时间(根据数据规模n)O(n)

    5 散列表的大小为1001(选取素数,有助于更加均匀的分开关键值)

    6 散列函数通过一系列相乘相加(基数为31),获取散列值(获取方式请看代码),最终值根据数组大小求模返回

    7 通过链表解决碰撞(散列值相同情况),即散列表相当于一个数组,每个元素有一个链表

    8 通过键 获取值的 一种散列表(键值对,使用动态分配内存)

      1 #include <iostream>
      2 #include <crtdbg.h>
      3 using namespace std;
      4 
      5 typedef int DataType;
      6 
      7 struct Node
      8 {
      9     DataType data;
     10     char *str;
     11     Node * next;
     12 };
     13 //可以直接使用一个结构体Node实现
     14 //之所以分开是为了增加灵活性
     15 struct hashNode
     16 {
     17     Node *node;
     18     //hashNode *next;
     19 };
     20 
     21 class Hash
     22 {
     23 private:
     24     enum 
     25     {
     26         MULTIPLIER = 31,  //乘法散列基数(根据书里的经验 37 也可)
     27         SIZE = 1001   //使用素数确定散列表大小,尽可能把关键吗均匀地分开
     28     };
     29     hashNode *hashTable[SIZE];//散列表
     30     int hashFn(const char* key);//散列函数
     31 public:
     32     Hash()
     33     {
     34         Init();
     35     }
     36     ~Hash()
     37     {
     38         Delete();
     39     }
     40     void Init();
     41     void Delete();
     42     bool Insert(const char* key, const DataType &data);
     43     bool ExtractData(const char* key);//通过键删除该值
     44     bool Find(const char* key, DataType &outData);
     45     void Print()const;
     46 
     47 };
     48 int Hash::hashFn(const char* key)
     49 {
     50     int hashVal = 0;
     51     for (const char *p = key; *p != ''; ++p)
     52     {
     53         hashVal = MULTIPLIER*hashVal+ *p;
     54     }
     55     return hashVal%SIZE;
     56 }
     57 void Hash::Init()
     58 {
     59     for (int i=0; i<SIZE; ++i )
     60     {
     61         hashTable[i] = NULL;  
     62     }
     63 }
     64 //释放内存 str、碰撞的node以及hashTable表头
     65 void Hash::Delete()
     66 {
     67     for (int i=0; i<SIZE; ++i)
     68     {
     69         if (hashTable[i] !=NULL)
     70         {
     71             for (Node *p = hashTable[i]->node; p != NULL;)
     72             {
     73                 Node *pTemp = p->next;
     74                 delete [] p->str;  
     75                 delete p;
     76                 p = pTemp;
     77             }
     78             hashTable[i]->node = NULL;
     79             delete hashTable[i];
     80             hashTable[i] = NULL;
     81         }
     82     }
     83 }
     84 //添加元素
     85 bool Hash::Insert(const char* key, const DataType &data)
     86 {
     87     int index = hashFn(key);
     88     if (hashTable[index] == NULL)
     89     {
     90         hashTable[index] = new hashNode;
     91         hashTable[index]->node = new Node;
     92         hashTable[index]->node->data = data;
     93         hashTable[index]->node->str = new char[sizeof(key)+1];
     94         strcpy(hashTable[index]->node->str, key);
     95         hashTable[index]->node->next = NULL;
     96     }
     97     else
     98     {
     99         Node* p = new Node;
    100         p->data = data;
    101         p->str = new char[sizeof(key)+1];
    102         strcpy(p->str, key);
    103         p->next = hashTable[index]->node->next;
    104         hashTable[index]->node->next = p;
    105     }
    106     return true;
    107 }
    108 //删除元素
    109 bool Hash::ExtractData(const char* key)
    110 {
    111     int index = hashFn(key);
    112     if (hashTable[index] == NULL)
    113     {
    114         return false;
    115     }
    116     else
    117     {  //考虑两种情况,hashTable表头 与 链表
    118         if (strcmp(hashTable[index]->node->str, key) == 0)
    119         {
    120             Node *p = hashTable[index]->node->next;
    121             Node *pTemp = hashTable[index]->node;
    122             delete [] pTemp->str;
    123             delete pTemp;
    124             hashTable[index]->node = p;
    125 
    126             return true;
    127         }
    128         else
    129         {
    130             Node *pPreNode = hashTable[index]->node;
    131             for (Node *p=pPreNode->next; p !=NULL; )
    132             {    
    133                 if (strcmp(p->str, key) == 0)
    134                 {
    135                      pPreNode->next = p->next;
    136                      delete [] p->str;
    137                      delete p;
    138                      p = NULL;
    139 
    140                      return true;
    141                 }
    142                 pPreNode = p;
    143                 p=p->next;
    144             }
    145         }
    146         return false;
    147     }
    148 }
    149 //通过键查找值,如果找到通过outData返回
    150 bool Hash::Find(const char* key, DataType &outData)
    151 {
    152     int index = hashFn(key);
    153     if (hashTable[index] == NULL)
    154     {
    155         return false;
    156     }
    157     else
    158     {
    159         for(Node *p = hashTable[index]->node;p !=NULL; p = p->next )
    160         {
    161             if (strcmp(p->str, key) == 0)
    162             {
    163                 outData = p->data;
    164                 return true;
    165             }
    166         }
    167     }
    168     return false;
    169 }
    170 void Hash::Print()const
    171 {
    172     for (int i=0; i<SIZE; ++i)
    173     {
    174         if (hashTable[i] != NULL)
    175         {
    176             for (Node *p = hashTable[i]->node; p!=NULL; p = p->next)
    177             {
    178                 cout << p->str << "	" << p->data << endl;
    179             }
    180         }
    181     }
    182 }
    183 void main()
    184 {
    185     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    186 
    187     Hash hash;
    188     hash.Insert("tom", 15);
    189     hash.Insert("bart", 17);
    190     hash.Insert("shan", 17);
    191     hash.Insert("eve", 16);
    192     hash.Insert("jack", 21);
    193     hash.Print();
    194     hash.ExtractData("jack");
    195     cout << endl;
    196     hash.Print();
    197 
    198     cout << endl;
    199     DataType data=0;
    200     if (hash.Find("shan",data))
    201     {
    202         cout << "shan:   " << data << endl; 
    203     }
    204 
    205     system("pause");
    206 }
  • 相关阅读:
    PostgreSQL恢复误操作
    PostgreSQL修改表空间
    vim技巧记录
    postgresql recovery.conf文件内容说明
    转一篇pgpool配置
    由PostgreSQL的区域与字符集说起(转)
    PostgreSQL老司机博客 经常翻翻收获不小
    两位数相乘的口算方法
    五线谱升调与降调
    js中的封装、继承、多态
  • 原文地址:https://www.cnblogs.com/sevenPP/p/3684414.html
Copyright © 2020-2023  润新知