11.1直接寻址表
struct Hash* direct_address_search(struct Hash *T[], int key)
{
int Max=0;
while (key!=MAX)//MAX表示散列表容量最大值
{
if (T[key]!=NULL&&Maxkey)
{
Max=T[key]->key;
}
key++;//key既可以表示直接寻址表T的下标,也可以表示关键字
}
}
#include
#include
#define INT_BIT 32
typedef struct {
unsigned int *table;
int size;
} BitMap;
BitMap * bitmap_create(int max)
{
BitMap *bitmap = (BitMap *)malloc(sizeof(BitMap));
bitmap->size = max / INT_BIT + 1;
bitmap->table =(unsigned int *) calloc(sizeof(int), bitmap->size);
return bitmap;
}
void bitmap_insert(BitMap *bitmap, int key)
{
bitmap->table[key / INT_BIT] = 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, 10);
bitmap_insert(bitmap, 520);
bitmap_insert(bitmap, 900);
bitmap_delete(bitmap, 10);
bitmap_print(bitmap);
printf("%d\n", bitmap_search(bitmap, 68));
printf("%d\n", bitmap_search(bitmap, 520));
return 1;
}
#include
#include
#define LEN sizeof(struct Hash)
#define MAX 6
struct Hash{
int key;
int satellite;
}Data; //元素结构体,有关键字和卫星数据
struct Hash* direct_address_search(struct Hash *T[], int key); //散列表查找操作
void direct_address_insert(struct Hash *T[], struct Hash *x); //散列表插入操作
void direct_address_delete(struct Hash *T[], struct Hash *x); //散列表删除操作
void print_table(struct Hash *T[]); //打印散列表(为了方便查看删除操作后,散列表的变化)
int main(){
int i, key, satellite;
struct Hash *data[MAX];
struct Hash *d;
for(i = 0; i < MAX; i++){
data[i] =new struct Hash [LEN];
data[i] = NULL;
}
for(i = 0; i <= 3; i++){
d = new struct Hash[LEN];
printf("Input the key_value:\n");
scanf("%d", &key);
printf("Input the satellite:\n");
scanf("%d", &satellite);
d->key = key;
d->satellite = satellite;
direct_address_insert(data, d);
}
print_table(data);
printf("请输入待查找的元素\n");
scanf("%d", &key);
d = direct_address_search(data, key);
if (d)
{
printf("the key is %d, and its satellite is %d\n", d->key, d->satellite);
}
else
{
printf("没有找到\n");
}
if (d)
{
direct_address_delete(data, d);
}
print_table(data);
delete d;
for(i = 0; i < MAX; i++)
delete data[i];
print_table(data);
return 0;
}
//直接返回下标为key的元素
struct Hash* direct_address_search(struct Hash *T[], int key){
return T[key];
}
//直接将元素插入下标key的位置里
void direct_address_insert(struct Hash *T[], struct Hash *x){
T[x->key] = x;
}
// 将要删除的元素所在的位置指向空指针
void direct_address_delete(struct Hash *T[], struct Hash *x){
T[x->key] = NULL;
}
//打印直接寻址表
void print_table(struct Hash *T[]){
int i;
for(i = 0; i < MAX; i++){
if(T[i] != NULL){
printf("key is %d, and its satellite is %d\n", T[i]->key, T[i]->satellite);
}
}
}
#include
using namespace std;
#define MAX 100
#define LEN sizeof(struct hash)
struct hash{
int key;
};
struct Stack
{
int STack[MAX];
int top;
};
void Init(struct Stack&s)
{
s.top=-1;
}
struct hash * search(struct hash Hash[],struct Stack&s,int k)
{
if (Hash[k].key>=0&&Hash[k].key<=s.top&&s.STack[Hash[k].key]==k)
{
cout<<"已经找到"<key;
if (search(Hash,s,k))
{
cout<<"待插入的数据已经在散列表中!"<key]=s.STack[s.top];
Hash[s.STack[p->key]].key=p->key;
p->key=0;
s.top--;
}
void Print(struct Stack&s)
{
int i;
if (s.top==-1)
{
cout<<"无数据可打印!"<>str;
if (str=='A')
{
y=new struct hash[LEN];
cin>>y->key;
insert(Hash,s,y);
}
if (str=='B')
{
cin>>k;
Delete(Hash,s,k);
}
if (str=='C')
{
cin>>k;
search(Hash,s,k);
}
if (str=='D')
{
Print(s);
}
if (str=='E')
{
break;
}
}
}
//11.2-2
#include
using namespace std;
#define MAX 10 //槽的个数
#define LEN sizeof(struct list)
struct list*head=NULL;
struct list
{
int key;
struct list*next;
struct list*prev;
}slot[MAX];
int hash(int y)
{
int i=y%(MAX-1);
return i;
}
void Init(struct list *slot[])//初始化结构体数组
{
for (int i=0;ikey=a[j];
int i=hash(x->key);
x->next=slot[i];
if (slot[i]!=NULL)
{
slot[i]->prev=x;
}
slot[i]=x;
x->prev=NULL;
return slot[i];
}
void Print(struct list *slot[])
{
int i=0;
while (i!=MAX)
{
cout<<"第"<key;
slot[i]=slot[i]->next;
if (slot[i])
{
cout<<"->";
}
}
cout<
//11.2-4 有自由表的散列表,自由表用来分配和释放内存的。
#include
using namespace std;
#define MAX 13 //槽的个数m
#define max 100 //整个散列表的元素个数n
#define LEN sizeof(struct list)
struct list*Free=NULL;
struct list * Allocate_object(struct list *x);//数组next为自由数组表
void free_object(struct list *x);
struct list
{
int key;
int flag;
struct list*next;
struct list*prev;
};
int hash(int y)
{
return y%MAX;
}
void Init(struct list *slot[])
{
struct list *p,*p1;
for (int i=0;iflag=0;//0表示该结点无数据
if (Free==NULL)
{
p1=Free=p;
}
else
{
p1->next=p;
p->prev=p1;
p1=p;
}
}
p->next=NULL;
}
//查找数据
struct list*search(struct list *slot[],int k)
{//O(1+n/m)
int i=hash(k);//O(1)
struct list*x;
x=slot[i];
while (x!=NULL&&x->key!=k)//O(n/m) 如果散列表中槽和表中元素数成正比,有n=O(m)。那么运行时间就为O(1)。
{
x=x->next;
}
return x;
}
//插入数据
struct list*insert(struct list *slot[],struct list*x)
{
x=Allocate_object(x);
if (!x)
{
return NULL;
}
x->flag=1;//1表示有数据
x->key=rand()%max;
int i=hash(x->key);
x->next=slot[i];
if (slot[i]!=NULL)
{
slot[i]->prev=x;
}
slot[i]=x;
x->prev=NULL;
return slot[i];
}
//删除数据
struct list*Delete(struct list *slot[],int k)
{
int i=hash(k);
struct list *x=search(slot, k);
if (!x)
{
cout<<"待删除数据不存在!"<prev!=NULL)
{
x->prev->next=x->next;
}
else
{
slot[i]=x->next;
}
if (x->next!=NULL)
{
x->next->prev=x->prev;
}
free_object(x);
cout<<"删除成功!"<next;
return x;
}
}
//释放空间
void free_object(struct list *x)
{
x->flag=0;
x->next=Free;
Free=x;
}
void Print(struct list *slot[])
{
int i=0;
while (i!=MAX)
{
cout<<"第"<key;
p=p->next;
if (p)
{
cout<<"->";
}
}
cout<
(2)乘法散列法:h(k) = m * (k * A mod 1) (0
(3)全域散列:从一组散列函数中随机地选择一个,这样平均情况运行时间比较好。
11.3-1 假设我们希望查找一个长度为n的链表,其中每一个元素都包含一个关键字k并具有散列值h(k).每一个关键字都是长字符串。那么在表中查找具有给定关键字的元素时,如何利用各元素的散列值呢?
通过k的散列值h(k)对应的链表找到k.
11.3-2假设将一个长度为r的字符串散列到m个槽中,并将其视为一个以128为基数的数,要求应用除法散列法。我们可以很容易地把数m表示为一个32位的机器字,但对长度为r的字符串,由于它被当做以128为基数的数来处理,就要占用若干个机器字。假设应用散列法计算一个字符串的散列值,那么如何才能在除了该串本身占用的空间外,只利用常数个机器字。
对于每个字母分别取模然后求∑在取模 这一过程利用了模运算的性质,(a+b)%m=(a%m+b%m)%m
#include
#include
using namespace std;
const double A=(sqrt(5)-1)/2.0;
int hash(int k,int m)
{
double x=(A*k-(int)(A*k))*m;
return x;
}
void main()
{
int k;
while (cin>>k)
{
cout<<"Hash["<
//除法,乘法,全域散列。与 线性,二次,双重探查。
#include
#include
#include
using namespace std;
#define Null -1
#define DELETED -2
//除法散列
int hash_div1(int k,int m)//选m的值常常是不接近2的幂的质数。
{
return k%m;
}
//除法散列
int hash_div2(int k,int m)//选m的值常常是不接近2的幂的质数。
{
return k%m;
}
//乘法散列
int hash_mul(int k)
{
double A=(sqrt(5)-1)/2.0;
int m=100;//对于m没有特别要求。m一般选择为2的某个幂。
return (A*k-(int)(A*k))*m;
}
//全域散列 P为质数
int hash_Universal(int k,int p)
{
static int a=0,b=0,flag=0;
int m=6;//m不一定非是质数。
if (flag==0)
{
a=rand()%(p-1)+1;
b=rand()%p;
flag=1;
}
return ((a*k+b)%p)%m;
}
//线性探查
int LineProbe(int k,int m,int i)
{
return (hash_div1(k,m)+i)%m; //选m的值常常是不接近2的幂的质数。
}
//二次探查
int QuadraticProbing(int k,int m,int i)
{
int c1=1,c2=3;
return (hash_div1(k,m)+c1*i+c2*i*i)%m; //其中常数c1,c2,m的值的选择是受限制的
}
//双重探查
int DoublefunProbing(int k,int m,int i)
{
return (hash_div1(k,m)+i*(1+hash_div2(k,m-1)))%m; //其中m为质数,还可以选择m为2的幂,并设置一个总产生奇数的hash_div2
}
int hash_insert1(int T[],int m,int k)
{
int i=0;
do
{
int j=LineProbe(k,m,i);//这里可以替换成二次,双重探查。插入,查找,删除函数同时被替换
if (T[j]==Null||T[j]==DELETED)
{
T[j]=k;
return j;
}
else i++;
} while (i!=m);
cerr<<"hash table overflow"<