当前位置:首页 » 编程语言 » c语言用除余留数法构建哈希表
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

c语言用除余留数法构建哈希表

发布时间: 2022-09-23 03:18:02

① 谁能帮忙写一个c语言的哈希排序小女感激不尽~~

1.选择合适的哈希函数H(key)=key%p(p为小于或等于哈希表长的最大质数);
2.计算各个关键字的直接哈希函数值;
3.根据处理冲突的方法建立哈希表,并输出;
4.在哈希表中进行查找,输出查找的结果,以及所需和记录关键字比较的次数,并计算和输出在等概率情况下查找成功的平均查找长度。

#include<stdlib.h>
#include<stdio.h>
#define NULL 0
typedef int KeyType;
typedef struct
{
KeyType key;
} ElemType;
int haxi(KeyType key,int m) /*根据哈希表长m,构造除留余数法的哈希函数haxi*/
{
int i,p,flag;
for(p=m;p>=2;p--) /*p为不超过m的最大素数*/
{
for(i=2,flag=1;i<=p/2&&flag;i++)
if(p%i==0)
flag=0;
if(flag==1)
break;
}
return key%p; /*哈希函数*/
}
void inputdata(ElemType **ST,int n) /*从键盘输入n个数据,存入数据表ST(采用动态分配的数组空间)*/
{
KeyType key;
int i;
(*ST)=(ElemType*)malloc(n*sizeof(ElemType));
printf("\nPlease input %d data:",n);
for(i=1;i<=n;i++)
scanf("%d",&((*ST)[i].key));
}
void createhaxi(ElemType **HASH,ElemType *ST,int n,int m) /*由数据表ST构造哈希表HASH,n、m分别为数据集合ST和哈希表的长度*/
{
int i,j;
(*HASH)=(ElemType *)malloc(m*sizeof(ElemType));
for(i=0;i<m;i++)
(*HASH)[i].key=NULL; /*初始化哈希为空表(以0表示空)*/
for(i=0;i<n;i++)
{
j=haxi(ST[i].key,m); /*获得直接哈希地址*/
while((*HASH)[j].key!=NULL)
j=(j+1)%m; /*用线性探测再散列技术确定存放位置*/
(*HASH)[j].key=ST[i].key; /*将元素存入哈希表的相应位置*/
}
}
int search(ElemType *HASH,KeyType key,int m,int *time) /*在表长为m的哈希表中查找关键字等于key的元素,并用time记录比较次数,若查找成功,函数返回值为其在哈希表中的位置,否则返回-1*/
{
int i;
*time=1;
i=haxi(key,m);
while(HASH[i].key!=0&&HASH[i].key!=key)
{
i++;
++*time;
}
if(HASH[i].key==0)
return -1;
else
return i;
}
main()
{
ElemType *ST,*HASH;
KeyType key;
int i,n,m,stime,time;
char ch;
printf("\nPlease input n&&m(n<=m)"); /*输入关键字集合元素个数和哈希表长*/
scanf("%d%d",&n,&m);
inputdata(&ST,n); /*输入n个数据*/
createhaxi(&HASH,ST,n,m); /*创建哈希表*/
printf("\nThe haxi Table is\n"); /*输出已建立的哈希表*/
for(i=0;i<m;i++)
printf("%5d",i);
printf("\n");
for(i=0;i<m;i++)
printf("%5d",HASH[i].key);
do /*哈希表的查找,可进行多次查找*/
{
printf("\nInput the key you want to search:");
scanf("%d",&key);
i=search(HASH,key,m,&time);
if(i!=-1) /*查找成功*/
{
printf("\nSuccess,the position is %d",i);
printf("\nThe time of compare is %d",time);
}
else /*查找失败*/
{
printf("\nUnsuccess");
printf("\nThe time of compare is %d",time);
}
printf("\nContiue(y/n):\n"); /*是否继续查找yes or no*/
ch=getch();
}
while(ch=='y'||ch=='Y'); /*计算表在等概率情况下的平均查找长度,并输出*/
for(stime=0,i=0;i<n;i++)
{
search(HASH,ST[i].key,m,&time);
stime+=time;
}
printf("\nThe Average Search Length is %5.2f",(float)stime/n);
ch=getch();
}

② 哈希表的设计(数据结构C语言版)

解决冲突方法无非两种嘛,而且这个不难的,帮你写不是害你嘛,这个不学好以后的课程容易出现问题的!

③ 构造哈希表存储电话号码,用再哈希法处理冲突要c语言程序代码

给你个hash表的接口和实现
你根据需求该下吧
#ifndef _Hash_H_
#define _Hash_H_
/*
* 查找算法时间是 O(1)
* 优点:查找迅速
* 缺点:比较占用内存
*/

/*
*
* hash原子结构体
*
*
*/
typedef struct hash_table_pair_s{
/*hash表长*/
int length;
/*hash key*/
char *key;
/*储存的值,可以是地址*/
int value;
struct hash_table_pair_s *next;
}hash_table;

/*
* function: hash_insert
* --------------------------------------
* 往hash表中增加一个元素
* Usage:
*
* #include "corelib/hash.h"
* void run(hash_table*hash){
* int i, status, value;
* status = hash_get(hash,"hawk", &value);
* if(status!=-1){
* printf("find,%d",value);
* }else{
* printf("not find");
* }
* }
* void main(){
* hash_table* hash= hash_create(10);//创建一个表长是10的hash表
* hash_insert(hash,"robin", 0);
* hash_insert(hash,"sparrow", 1);
* hash_insert(hash,"hawk", 2);
* hash_insert(hash,"jack", 3);
* hash_insert(hash,"seagull", 4);
* run(hash);
* }
*
*/
void hash_insert(hash_table *hash,const char *key, int value);

/*
* function: hash_get
* --------------------------------------
* 根据key值在hash表中获取一个元素对象
*
*
*/
int hash_get(hash_table *hash,const char* key, int *value);

/*
* function: hash_create
* 创建一个hash表
*
*/
hash_table* hash_create(int size);

#include "corelib/hash.c"
#endif
//-----------------------------------------------------------------------------------------------
#include <default.c>
#include <stdio.h>
/*
*一个key字符串占用的字节数
*/
#define KEY_SIZE 64

/*
*
*hash函数
*
*/
int ELFhash(const char *key){
unsigned long h = 0;
unsigned long g;
while( *key )
{
h =( h<< 4) + *key++;
g = h & 0xf0000000L;
if( g ) h ^= g >> 24;
h &= ~g;
}
return h;
}
void hash_insert(hash_table *hash,const char *key, int value){
char keystr[KEY_SIZE];
memset(keystr,0,KEY_SIZE);
memcpy(keystr,key,strlen(key));

int pos;
hash_table *new_pair;
char *new_str;
pos = ELFhash(key) % hash[0].length;

if (hash[pos].key != NULL) {
/*发生冲突*/
char log[512];
memset(log,0,512);
int j=0;
j+=sprintf(log+j,"冲突: %s and %s\n", keystr, hash[pos].key);
new_pair = (hash_table *)malloc(sizeof(hash_table));
new_str = (char *)malloc(sizeof(char) * (strlen(keystr) + 1));
strcpy(new_str, keystr);
new_pair->key = new_str;
new_pair->value = value;
new_pair->next = hash[pos].next;
hash[pos].next = new_pair;
// printf("%s",log);
}else{
int len = sizeof(char) * (strlen(keystr) + 1);
new_str = (char *)malloc(len);
memset(new_str,0,len);
strcpy(new_str, keystr);
hash[pos].key = new_str;
hash[pos].value = value;
hash[pos].next = NULL;
}
}
int hash_get(hash_table *hash,const char* key, int *value){
int pos;
hash_table *p;

char keystr[KEY_SIZE];
memset(keystr,0,KEY_SIZE);
memcpy(keystr,key,strlen(key));
pos = ELFhash(key) % hash[0].length;
for (p = &(hash[pos]); p != NULL; p = p->next) {
if (!strcmp(p->key, keystr)) {
*value = p->value;
return 0;
}
}
return -1;
}
hash_table* hash_create(int size){
int i;
hash_table *hash = (hash_table *)malloc(size * sizeof(hash_table));
hash[0].length = size;

for (i = 0; i < size; i++) {
hash[i].key = NULL;
hash[i].next = NULL;
hash[i].value = 0;
}
return hash;
}

#undef KEY_SIZE

④ 可以不学数据结构直接学哈希表吗C语言实现

可以的,哈希表那部分和图,树联系不是很大。直接看是完全可以的,而且哈希这部分也比较容易些。

⑤ 编写一个C语言程序,求出1至1000之间满足“用3除余2;用5除余3;用7除余2”的数,并把满足条件的数显示...

#include "stdio.h"

int main()

{

int i,j=0;

for(i=1;i<=1000;i++)

{

if(i%3==2&&i%5==3&&i%7==2)

{

printf("%d ",i);

j++;

if (j%5==0)

{printf(" ");}

}

}

return 0;

}

C语言是一种结构化的语言,提供的控制语句具有结构化特征,如for语句、if⋯else语句和switch语句等。可以用于实现函数的逻辑控制,方便面向过程的程序设计。



(5)c语言用除余留数法构建哈希表扩展阅读:

C语言是面向过程的编程语言,用户只需要关注所被解决问题的本身,而不需要花费过多的精力去了解相关硬件,且针对不同的硬件环境。

在用C语言实现相同功能时的代码基本一致,不需或仅需进行少量改动便可完成移植,这就意味着,对于一台计算机编写的C程序可以在另一台计算机上轻松地运行,从而极大的减少了程序移植的工作强度。

⑥ 利用C语言如何提取Excel中的数据并利用其中的数据生成哈希表

应该有专门的工具软件吧,类似与fuzzytech,visual state之类的

⑦ 希望大家帮帮我啊!!!C语言 哈希表生成及哈希查找算法 输入:待哈希数据序列 功能要求:输出哈希方法和

你看看这个哈希算法吧、、貌似。,,也差不多咯

#include<stdlib.h>
#include<stdio.h>
#include<malloc.h>
typedef int KeyType;
typedef struct /*元素类型定义*/
{
KeyType key; /*关键字*/
int hi; /*冲突次数*/
}DataType;
typedef struct /*哈希表类型定义*/
{
DataType *data;
int tableSize; /*哈希表的长度*/
int curSize; /*表中关键字个数*/
}HashTable;
void CreateHashTable(HashTable *H,int m,int p,int hash[],int n);
int SearchHash(HashTable H,KeyType k);
void DisplayHash(HashTable H,int m);
void HashASL(HashTable H,int m);
void CreateHashTable(HashTable *H,int m,int p,int hash[],int n)
/*构造一个空的哈希表,并处理冲突*/
{
int i,sum,addr,di,k=1;
(*H).data=(DataType*)malloc(m*sizeof(DataType));/*为哈希表分配存储空间*/
if(!(*H).data)
exit(-1);
for(i=0;i<m;i++) /*初始化哈希表*/
{
(*H).data[i].key=-1;
(*H).data[i].hi=0;
}
for(i=0;i<n;i++) /*求哈希函数地址并处理冲突*/
{
sum=0; /*冲突的次数*/
addr=hash[i]%p; /*利用除留余数法求哈希函数地址*/
di=addr;
if((*H).data[addr].key==-1) /*如果不冲突则将元素存储在表中*/
{
(*H).data[addr].key=hash[i];
(*H).data[addr].hi=1;
}
else /*用线性探测再散列法处理冲突*/
{
do
{
di=(di+k)%m;
sum+=1;
} while((*H).data[di].key!=-1);
(*H).data[di].key=hash[i];
(*H).data[di].hi=sum+1;
}
}
(*H).curSize=n; /*哈希表中关键字个数为n*/
(*H).tableSize=m; /*哈希表的长度*/
}
int SearchHash(HashTable H,KeyType k)
/*在哈希表H中查找关键字k的元素*/
{
int d,d1,m;
m=H.tableSize;
d=d1=k%m; /*求k的哈希地址*/
while(H.data[d].key!=-1)
{
if(H.data[d].key==k)/*如果是要查找的关键字k,则返回k的位置*/
return d;
else /*继续往后查找*/
d=(d+1)%m;
if(d==d1) /*如果查找了哈希表中的所有位置,没有找到返回0*/
return 0;
}
return 0; /*该位置不存在关键字k*/
}
void DisplayHash(HashTable H,int m)
/*输出哈希表*/
{
int i;
printf("哈希表地址:");
for(i=0;i<m;i++)
printf("%-5d",i);
printf("\n");
printf("关键字key: ");
for(i=0;i<m;i++)
printf("%-5d",H.data[i].key);
printf("\n");
printf("冲突次数: ");
for(i=0;i<m;i++)
printf("%-5d",H.data[i].hi);
printf("\n");

}
void HashASL(HashTable H,int m)
/*求哈希表的平均查找长度*/
{
float average=0;
int i;
for(i=0;i<m;i++)
average=average+H.data[i].hi;
average=average/H.curSize;
printf("平均查找长度ASL=%.2f",average);
printf("\n");
}

void main()
{
int hash[]={23,35,12,56,123,39,342,90};
int m=11,p=11,n=8,pos;
KeyType k;
HashTable H;
CreateHashTable(&H,m,p,hash,n);
DisplayHash(H,m);
k=123;
pos=SearchHash(H,k);
printf("关键字%d在哈希表中的位置为:%d\n",k,pos);
HashASL(H,m);
}

⑧ 如何用C语言中实现哈希表

C++有 map,set
还有其他的,看STL相关的吧

数组还慢....

⑨ C语言哈希表

/#include "iostream.h"
#include <iostream>
#include "string.h"
#include "fstream"
#define NULL 0
unsigned int key;
unsigned int key2;
int *p;
struct node //建节点
{
char name[8],address[20];
char num[11];
node * next;
};

typedef node* pnode;
typedef node* mingzi;
node **phone;
node **nam;
node *a;

using namespace std; //使用名称空间

void hash(char num[11]) //哈希函数
{
int i = 3;
key=(int)num[2];

while(num[i]!=NULL)
{
key+=(int)num[i];
i++;
}
key=key%20;
}

void hash2(char name[8]) //哈希函数
{
int i = 1;
key2=(int)name[0];
while(name[i]!=NULL)
{
key2+=(int)name[i];
i++;
}
key2=key2%20;
}

node* input() //输入节点
{
node *temp;
temp = new node;
temp->next=NULL;
cout<<"输入姓名:"<<endl;
cin>>temp->name;
cout<<"输入地址:"<<endl;
cin>>temp->address;
cout<<"输入电话:"<<endl;
cin>>temp->num;
return temp;
}

int apend() //添加节点
{
node *newphone;
node *newname;
newphone=input();
newname=newphone;
newphone->next=NULL;
newname->next=NULL;
hash(newphone->num);
hash2(newname->name);
newphone->next = phone[key]->next;
phone[key]->next=newphone;
newname->next = nam[key2]->next;
nam[key2]->next=newname;
return 0;
}

void create() //新建节点
{
int i;
phone=new pnode[20];
for(i=0;i<20;i++)
{
phone[i]=new node;
phone[i]->next=NULL;
}
}
void create2() //新建节点
{
int i;
nam=new mingzi[20];
for(i=0;i<20;i++)
{
nam[i]=new node;
nam[i]->next=NULL;
}
}
void list() //显示列表
{
int i;
node *p;
for(i=0;i<20;i++)
{
p=phone[i]->next;
while(p)
{
cout<<p->name<<'_'<<p->address<<'_'<<p->num<<endl;
p=p->next;
}
}
}
void list2() //显示列表
{
int i;
node *p;
for(i=0;i<20;i++)
{
p=nam[i]->next;
while(p)
{
cout<<p->name<<'_'<<p->address<<'_'<<p->num<<endl;
p=p->next;
}
}
}

void find(char num[11]) //查找用户信息
{
hash(num);
node *q=phone[key]->next;
while(q!= NULL)
{
if(strcmp(num,q->num)==0)
break;
q=q->next;
}
if(q)
cout<<q->name<<"_" <<q->address<<"_"<<q->num<<endl;
else cout<<"无此记录"<<endl;
}
void find2(char name[8]) //查找用户信息
{
hash2(name);
node *q=nam[key2]->next;
while(q!= NULL)
{
if(strcmp(name,q->name)==0)
break;
q=q->next;
}
if(q)
cout<<q->name<<"_" <<q->address<<"_"<<q->num<<endl;
else cout<<"无此记录"<<endl;
}

void save() //保存用户信息
{
int i;
node *p;
for(i=0;i<20;i++)
{
p=phone[i]->next;
while(p)
{
fstream iiout("out.txt", ios::out);
iiout<<p->name<<"_"<<p->address<<"_"<<p->num<<endl;
p=p->next;
}
}
}

void menu() //菜单
{

cout<<"0.添加记录"<<endl;
cout<<"3.查找记录"<<endl;
cout<<"2.姓名散列"<<endl;
cout<<"4.号码散列"<<endl;
cout<<"5.清空记录"<<endl;
cout<<"6.保存记录"<<endl;
cout<<"7.退出系统"<<endl;
}

int main()
{
char num[11];
char name[8];

create();
create2() ;

int sel;
while(1)
{
menu();
cin>>sel;
if(sel==3)
{ cout<<"9号码查询,8姓名查询"<<endl;
int b;
cin>>b;
if(b==9)
{ cout<<"请输入电话号码:"<<endl;
cin >>num;
cout<<"输出查找的信息:"<<endl;
find(num);
}
else
{ cout<<"请输入姓名:"<<endl;
cin >>name;
cout<<"输出查找的信息:"<<endl;
find2(name);}
}
if(sel==2)
{ cout<<"姓名散列结果:"<<endl;
list2();
}
if(sel==0)
{ cout<<"请输入要添加的内容:"<<endl;
apend();
}
if(sel==4)
{ cout<<"号码散列结果:"<<endl;
list();
}
if(sel==5)
{ cout<<"列表已清空:"<<endl;
create();
create2();
}
if(sel==6)
{ cout<<"通信录已保存:"<<endl;
save();
}
if(sel==7) return 0;
}
return 0;

}

⑩ C语言 数据结构中解决冲突的方法是什么

可以参考如下方法:

1 基本原理
使用一个下标范围比较大的数组来存储元素。可以设计一个函数(哈希函数, 也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标)相对应,于是用这个数组单元来存储这个元素;也可以简单的理解为,按照关键字为每一个元素"分类",然后将这个元素存储在相应"类"所对应的地方。
但是,不能够保证每个元素的关键字与函数值是一一对应的,因此极有可能出现对于不同的元素,却计算出了相同的函数值,这样就产生了"冲突",换句话说,就是把不同的元素分在了相同的"类"之中。后面我们将看到一种解决"冲突"的简便做法。
总的来说,"直接寻址"与"解决冲突"是哈希表的两大特点。

2 函数构造
构造函数的常用方法(下面为了叙述简洁,设 h(k) 表示关键字为 k 的元素所对应的函数值):
a) 除余法:
选择一个适当的正整数 p ,令 h(k ) = k mod p
这里, p 如果选取的是比较大的素数,效果比较好。而且此法非常容易实现,因此是最常用的方法。
b) 数字选择法:
如果关键字的位数比较多,超过长整型范围而无法直接运算,可以选择其中数字分布比较均匀的若干位,所组成的新的值作为关键字或者直接作为函数值。

3 冲突处理
线性重新散列技术易于实现且可以较好的达到目的。令数组元素个数为 S ,则当 h(k) 已经存储了元素的时候,依次探查 (h(k)+i) mod S , i=1,2,3…… ,直到找到空的存储单元为止(或者从头到尾扫描一圈仍未发现空单元,这就是哈希表已经满了,发生了错误。当然这是可以通过扩大数组范围避免的)。

4 支持运算
哈希表支持的运算主要有:初始化(makenull)、哈希函数值的运算(h(x))、插入元素(insert)、查找元素(member)。
设插入的元素的关键字为 x ,A 为存储的数组。
初始化比较容易,例如
const empty=maxlongint; // 用非常大的整数代表这个位置没有存储元素
p=9997; // 表的大小
procere makenull;
var i:integer;
begin
for i:=0 to p-1 do
A[i]:=empty;
End;
哈希函数值的运算根据函数的不同而变化,例如除余法的一个例子:
function h(x:longint):Integer;
begin
h:= x mod p;
end;
我们注意到,插入和查找首先都需要对这个元素定位,即如果这个元素若存在,它应该存储在什么位置,因此加入一个定位的函数 locate
function locate(x:longint):integer;
var orig,i:integer;
begin
orig:=h(x);
i:=0;
while (i<S)and(A[(orig+i)mod S]<>x)and(A[(orig+i)mod S]<>empty) do
inc(i);
//当这个循环停下来时,要么找到一个空的存储单元,要么找到这个元
//素存储的单元,要么表已经满了
locate:=(orig+i) mod S;
end;
插入元素
procere insert(x:longint);
var posi:integer;
begin
posi:=locate(x); //定位函数的返回值
if A[posi]=empty then A[posi]:=x
else error; //error 即为发生了错误,当然这是可以避免的
end;
查找元素是否已经在表中
procere member(x:longint):boolean;
var posi:integer;
begin
posi:=locate(x);
if A[posi]=x then member:=true
else member:=false;
end;
这些就是建立在哈希表上的常用基本运算。

4.1 应用的简单原则
什么时候适合应用哈希表呢?如果发现解决这个问题时经常要询问:"某个元素是否在已知集合中?",也就是需要高效的数据存储和查找,则使用哈希表是最好不过的了!那么,在应用哈希表的过程中,值得注意的是什么呢?
哈希函数的设计很重要。一个不好的哈希函数,就是指造成很多冲突的情况,从前面的例子已经可以看出来,解决冲突会浪费掉大量时间,因此我们的目标就是尽力避免冲突。前面提到,在使用"除余法"的时候,h(k)=k mod p ,p 最好是一个大素数。这就是为了尽力避免冲突。为什么呢?假设 p=1000 ,则哈希函数分类的标准实际上就变成了按照末三位数分类,这样最多1000类,冲突会很多。一般地说,如果 p 的约数越多,那么冲突的几率就越大。
简单的证明:假设 p 是一个有较多约数的数,同时在数据中存在 q 满足 gcd(p,q)=d >1 ,即有 p=a*d , q=b*d, 则有 q mod p= q - p* [q div p] =q - p*[b div a] . ① 其中 [b div a ] 的取值范围是不会超过 [0,b] 的正整数。也就是说, [b div a] 的值只有 b+1 种可能,而 p 是一个预先确定的数。因此 ① 式的值就只有 b+1 种可能了。这样,虽然mod 运算之后的余数仍然在 [0,p-1] 内,但是它的取值仅限于 ① 可能取到的那些值。也就是说余数的分布变得不均匀了。容易看出, p 的约数越多,发生这种余数分布不均匀的情况就越频繁,冲突的几率越高。而素数的约数是最少的,因此我们选用大素数。记住"素数是我们的得力助手"。
另一方面,一味的追求低冲突率也不好。理论上,是可以设计出一个几乎完美,几乎没有冲突的函数的。然而,这样做显然不值得,因为这样的函数设计很浪费时间而且编码一定很复杂,与其花费这么大的精力去设计函数,还不如用一个虽然冲突多一些但是编码简单的函数。因此,函数还需要易于编码,即易于实现。
综上所述,设计一个好的哈希函数是很关键的。而"好"的标准,就是较低的冲突率和易于实现。