您的位置:首页 > 其它

《算法导论》第11章 散列表 (1)直接寻址表

2012-03-07 22:54 239 查看
(一)直接寻址表

关键字集合U = { 0, 1, ..., m - 1 },实际的关键字集合K。
用一个数组T[0..m - 1],其中每个位置对应U中的一个关键字。



直接寻址表的问题:

(1)如果U很大,要保存|U|大小的一张表T有点不实际。
(2)实际存储的关键字集合K相对U来说可能很小,因而分配给T的大部分空间都要浪费掉。

(二)位向量

位向量 (bit vector)是一种仅包含0和1的数组,所占空间比包含指针的数组少得多。
一个32位的整型,每一位用0和1表示key是否存在,这样一个整数就可以表示32个key。

key / 32表示key应保持在数组哪个下标的整数中,而key % 32则表示key应该用
该整数中的第几位置1来表示存在。
#include <stdio.h>
#include <stdlib.h>
#define INT_BIT 32

typedef struct {
unsigned int *table;
int size;
} BitMap;

BitMap * bitmap_create(int max)
{
BitMap *bitmap = malloc(sizeof(BitMap));
bitmap->size = max / INT_BIT + 1;
bitmap->table = calloc(sizeof(int), bitmap->size);
return bitmap;
}

void bitmap_insert(BitMap *bitmap, int key)
{
bitmap->table[key / INT_BIT] |= (1 << (key % INT_BIT));
}

void bitmap_delete(BitMap *bitmap, int key)
{
bitmap->table[key / INT_BIT] &= ~(1 << (key % INT_BIT));
}

int bitmap_search(BitMap *bitmap, int key)
{
return bitmap->table[key / INT_BIT] & (1 << (key % INT_BIT));
}

void bitmap_print(BitMap *bitmap)
{
printf("-----\n");
int i;
for (i = 0; i < bitmap->size; i++)
if (bitmap->table[i] != 0)
printf("%d: %d\n ", i, bitmap->table[i]);
printf("-----\n");
}

int main(void)
{
BitMap *bitmap = bitmap_create(1024);
bitmap_insert(bitmap, 15);
bitmap_insert(bitmap, 520);
bitmap_insert(bitmap, 900);
bitmap_print(bitmap);

printf("%d\n", bitmap_search(bitmap, 68));
printf("%d\n", bitmap_search(bitmap, 520));

return 1;
}


更快速、简洁的表示方法是用位运算来表示除法和求余。

key >> 5表示key / 32
key & 0x1F表示key % 32

#define SHIFT 5
#define MASK 0x1F
#define INT_BIT 32

void bitmap_insert(BitMap *bitmap, int key)
{
bitmap->table[key >> SHIFT] |= (1 << (key & MASK));
}

void bitmap_delete(BitMap *bitmap, int key)
{
bitmap->table[key >> SHIFT] &= ~(1 << (key & MASK));
}

int bitmap_search(BitMap *bitmap, int key)
{
return bitmap->table[key >> SHIFT] & (1 << (key & MASK));
}


一道笔试题:

腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: