哈希表學習總結

  1. 什麼是哈希表, 哈希函數, 關鍵字?
    關鍵字: 用戶數據
    哈希表(Hash Table): 也叫散列表, 是根據關鍵碼值(Key Value) 直接進行數據訪問的數據結構.
    哈希函數: 也叫散列函數, 是key和[結果]的一種關係. k = f(k);

  2. 哈希表有什麼用途?

    1. 用於加密算法;
    2. 用於數字簽名;
    3. 用於文件校驗.
      在實際應用中, 哈希表的查找性能是極好的.
      在合理的假設下, 它查找一個元素的平均時間是O(1);
  3. 哈希函數的構造方法之除留餘數法.
    在此方法中, 表長代表所有元素個數, 並不是數組長度.

除留餘數法此方法爲最常用的構造散列函數方法。
對於散列表長爲m的散列函數公式爲:
f( key ) = key mod p ( p ≤ m ) (p一般取第一個比m小的質數)
代碼如下:

/*======================================================================\
* Author (作者): i.sshe
* Date (日期): 2016/03/26
* Others (其他): 尋找<num的最大質數
\*=======================================================================*/
int generate_mod_value(int num)
{
     int i = 0;
     int j = 0;
     int temp = 0;
     int flag = 0;

     for (i = num; i > 2; i--)
     {
         flag = 1;
         for (j = 2; j <= i/2; j++)
         {
              if(i % j == 0) //不是質數
              {
                  flag = 0;
                  break;
              }
         }

         if (flag == 1)
         {
              temp = i;
              break;
         }
     }
 // temp = i;
     if (num < 4)
     {
          temp = num;
     }

     printf("除留餘數法取得的mod值爲:%d\n", temp);

     return temp;
}
  1. 哈希表解決衝突方法之 拉鍊法(鏈接法/鏈地址法)
    可以使用單鏈表或雙鏈表, 雙鏈表更方便刪除.
    代碼如下:
    相關結構:
/*=========================================================================*\
 * #struct# *
\*=========================================================================*/
typedef struct HASH_NODE_S_
{
    int data;
    struct HASH_NODE_S_ *prev;
    struct HASH_NODE_S_ *next;
}HASH_NODE_S;

typedef struct HASH_TABLE_S_
{
     HASH_NODE_S *hash_node;
}HASH_TABLE_S;

創建hash-table操作(create):

HASH_TABLE_S *create_hash_table(int len, int num)
{
    HASH_TABLE_S *hash_table = NULL;
    int i = 0;
    int tempvalue = 0;

    hash_table = (HASH_TABLE_S *)malloc(len * sizeof(HASH_TABLE_S));
    if (hash_table == NULL)
    {
         printf("hash table malloc error!\n");
         exit(1);
    }
    memset(hash_table, 0, len * sizeof(HASH_TABLE_S));

    //還要增加用戶輸入數據, 重複的需要鏈接到後面
    printf("請輸入數據:\n");
    for (i = 0; i < num; i++)
    {
        scanf("%d", &tempvalue);
        insert_element(hash_table, len, tempvalue);
    }

    return hash_table;
}

插入操作:
先查看錶中是否已經存在此元素, 不存在 插入.

int insert_element(HASH_TABLE_S *hash_table, int hash_len, int value)
{
    int position_num = value % hash_len;
    HASH_NODE_S *node ;

    if (search_element(hash_table, hash_len, value))
    {
        return 0;
    }

    node = (HASH_NODE_S *)malloc(sizeof(HASH_NODE_S));
    if (node == NULL)
    {
        printf("insert element malloc error!\n");
        exit(1);
    }

    node->data = value;

    if (hash_table[position_num].hash_node != NULL) //衝突了
    {
         node->next = hash_table[position_num].hash_node;
         hash_table[position_num].hash_node->prev = node;
         hash_table[position_num].hash_node = node;
         node->prev = NULL;
    }
    else
    {
        hash_table[position_num].hash_node = node;
    }

    return 1;
}

刪除操作(delete):
刪除操作要注意刪除元素在對應的key下的鏈表中的位置.(分首個/中間/最後一個三種)

int delete_element(HASH_TABLE_S *hash_table, int mod_value, int value)
{
     HASH_NODE_S *current_node = NULL;
     int position_key = value % mod_value;

     current_node = hash_table[position_key].hash_node;
     while (current_node != NULL)
     {
          if (current_node->data == value)
          {
              //此元素的第一個元素
              if (current_node->prev == NULL && current_node->next != NULL)
              {
                   hash_table[position_key].hash_node = current_node->next;
                   current_node->next->prev = NULL;
              }
              else if (current_node->prev != NULL && current_node->next == NULL)
              {
                   // 此元素是最後一個元素
                   current_node->prev->next = NULL;
              }
              else if(current_node->prev != NULL && current_node->next != NULL)
              {
                  //此元素是中間的元素
                  current_node->prev->next = current_node->next;
                  current_node->next->prev = current_node->prev;
              }
              else
              {
                   //只剩一個元素
                   hash_table[position_key].hash_node = NULL;
              }

              free(current_node);
              printf("刪除成功!\n");
              return 1;
          }
          current_node = current_node->next;
     }

     printf("沒有此元素!\n");
     return 0;

}

勿在浮沙築高臺.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章