数据结构(查找,Hash表)

查找的原理

查找概念

  • 设记录表L=(R1,R2,R3…Rn),其中R(1<=i<=n)为记录,对给定的某个值k,在表L中确定key=k的记录的过程,称为查找。
  • 若表中存在一个记录Ri的key=k,记为Ri.key=k,则查找成功,返回该记录在表L中的序号i(或Ri的地址),否则(查找失败)返回0(或空地址NULL)。

顺序表的查找
折半查找:对给定值k,逐步确定待查记录所在区间,每次将搜索空间减少一半(折半),直到查找成功或失败为止。
设两个游标low,high,分别指向当前待查找表的上界(表头)和下界(表尾),mid指向中间元素。
Hash表的查找:对给定的k,不经任何比较便能获取所需记录,其查找的时间复杂度为常数级O©。当腰查找key=k的记录时,通过关系f就 可以得到相应的记录的地址而获取记录,从而免去了key的比较过程。这个关系f就是所谓的hash函数(或成为散列函数),记为H(key)。它实际上就是一个地址映射函数,其自变量为key,函数值为记录的存储地址(或你的hash地址)。不同的key可能得到同一个hash地址,即当key1!=key2时,可能有H(key1)=H(key2),此时key1和key2 为同义词,这种现象称为“冲突”,或“碰撞”,因为一个数据单位只能存放一条记录。一般,选取hash函数只能做到使冲突尽可能减少,却不可能完全避免,这就要求再出现冲突之后,寻找适当的方法来解决冲突记录存放的问题。

选取(或构造)hash函数的方法有很多,原则是尽可能将记录均匀分配,以减少冲突的发生。以下有几种常用的方法:
直接地址法,平方取中法,叠加法,保留余数法。

	保留余数法:又称为质数除余法,设Hash表空间长度为m,选取一个不大于m的质数p,令:H(key)=key%p
						若取p=19(质数),同样对上给定的key集合k,有key:28,35,63,77,105       H(key)=key%19:9,16,6,1,10    H(key)的随机读就好多了。

	处理冲突的方法:选取随机度好的hash函数可以减少冲突的发生,一般来讲不能完全避免冲突,设hash表地址空间为0~m-1(表长为m).
								在地址j的前面或者后面找一个空闲单元存放冲突的记录,或将冲突的记录拉成链表。
								还有一个因素就是表的装填因子&(阿尔法),&=n/m,其中m为表长,n 为表中记录个数,一般&在0.7-0.8之间,使表保持一定的空闲余量,以减少冲突聚积现象。

							开放地址法:当发生冲突时,在H(key)的前后找一个空闲单元来存放冲突的记录,即在H(key)的基础上获取下一个地址:Hi=(H(key)+di)%m;   m为表长,%运算是保证Hi落在【0,m-1]区间,di为地址增量,di的取法有很多种。
							(1)di=1,2,3,....(m-1)---------------------------称为线性探查法
							(2)1的平方,-1的平方,2的平方,-2的平方-----------称为二次探查法
							设记录的key集合k={23,34,14,38,46,16,68,15,07,31,26}记录数n=11
							H(key)=key%13
							Hi(H(key)+di)%15;  di=1,2,3,4....(m-1)
	
							链式地址法:设H(key)取值范围(值域)为【0,m-1],建立头指针向量HP[m],HP[i](0<=i<=m-1)初值为空。
													设H(key)=key%13,k={23,34,14,38,46,16,68,15,07,31,26}.,链存储冲突。键值对(键(key),值(H(key))
							链式地址法解决冲突的优点:无聚集现象,删除表中数据容易实现。

在这里插入图片描述

hash.h
#ifdef_HASH_H
#define _HASH_H

#define N  15
typedef int datatype ;
typedef struct node{
	datatype key;
	datatype value;
	strcut node *next;
}listnode ,*linklist;

typedef strcut {
	listnode data[N];
}hash;

hash *hash_create();
int hash_insert(hash *HT,datatype key);
linklist *hash_search(hash *HT,datatype key);

#endif
 
hash.c
#include<stdio.h>
#include"hash.h"
#include<string.h>
#include<stdlib.h>
hash *hash_create()
{
	if((HT=(hash *)malloc(sizeof(hash)))==NULL){
		printf("malloc failed\n");
		return NULL;
	}
	memset(HT,0,sizeof(hash));
	return HT;

}
int hash_insert(hash *HT,datatype key)
{
	linklist p;
	if(HT==NULL){
		printf("HT is null\n");
		return -1;
	}
	if((p=(linklist )malloc(sizeof(listnode)))==NULL){
		printf("malloc is failed\n");
		return -1;
	}
	p->key=key;
	p->vlue=key%N;
	p->next=NULL;
	
	q=&(HT->data[key%N]);
	while(q->next&&q->next->key<p->key){
		q=q->next;
	}
	p->next=q->next;
	q->next=p;
	return 0;

}
linklist *hash_search(hash *HT,datatype key)
{
	linklist p;
	if(HT==NULL){
		printf("HT is null\n");
		return -1;
	}
	p=&(HT->data[key%N]);  //头结点
	while(p->next&&p->next->ke!=key){
		p=p->next;
	}
	if(p->next==NULL){
		return NULL;
	}else{
		printf("found\n");
		return p->next;
	}
}
test.c
#include<stdio.h>
#include"hash.h"
int main(int argc,char *argv[])
{
	hash *HT;
	int data[]={23,34,14,38,46,16,68,15,07,31,26};
	int i;
	linklist r;
	if(HT==NULL){
		return -1;
	}
	for(i=0;i<sizeof(data)/sizeof(int);i++){
		hash_insert(HT,data[i]);
	}

	printf("input:);
	scanf("%d",&key);
	r=hash_search(HT,key);
	if(r==NULL)
		printf("r not found\n");
	else
		printf("found:%d %d\n",key,r->key);
	
	return 0;
}

排序

快速排序
#include<stdio.h>
#include<stdlib.h>
#define N 15
int compare(const void *pl,const void *p2)
int quick_sort(int *data,int low,int high);
int partion(int *data,int low,int high);
int main(int argc,char *argv[])
{
	int data[N]={0};
	int i;
	srandom(10);
	for(i=0;i<N;i++){
		data[i]=random()%100;
	}
	for(i=0;i<N;i++){
		printf("%d ",data[i]);
		puts("");
	}
	//quick_sort(data,0,N-1);
	qsort(data,N,sizeof(int),&compare);
	for(i=0;i<N;i++){
			printf("%d ",data[i]);
			puts("");
	}
	return 0;
}

int partion(int *data,int low,int high)
{
	int temp=data[low];
	while(low<high){
		while(lox<high &&temp<data[high]){
			high--;
		}
		data[low]=data[high];
		while(low<high&&temp>=data[high]){
			low++;
		}
		data[high]=data[low];
	}
	data[low]=temp;
	return low;

}

int quick_sort(int *data,int low,int high)
{
	int t;
	if(data==NULL){
		return -1;
	}
	if(low>=high){
		return 0;
	}
	t=partion(data,low,high);
	quick_sort(data,low,t-1);
	quick_sort(data,t+1,high);
	
	return 0;
}

int compare(const void *p1,const void *p2)
{
	return (*(const void *)p1-*(const void *)p2);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值