1.实验目的
熟练掌握顺序表和有序表的查找方法,掌握其时间复杂度的分析方法
2.实验内容
(1)验证并设计顺序表的查找(顺序查找、折半查找)算法
(2)验证二叉排序树上的查找(创建、查找、插入)算法
(3)验证Hash表查找(Hash函数定义、建立,查找,插入)算法
//顺序表的顺序查找 折半查找 二叉排序树 以数值型关键字为例
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
#define INCRESIZE 20
#define EQ(a,b) a==b
#define LT(a,b) a<b
#define LQ(a,b) a<=b
#define ERROR 0
#define FALSE 0
#define TRUE 1
#define OK 1
typedef int ElemType;
typedef int KeyType;
typedef int Status;
typedef struct{
ElemType *base;
int length;//表长度 0号单元不存储内容
}SSTable;
typedef struct BTNode{
ElemType data;
struct BTNode *lchild;
struct BTNode *rchild;
}BTNode,*BiTree;
Status Init_Seq(SSTable &ST){
ST.base = (ElemType *)malloc(MAXSIZE*sizeof(ElemType));
if(!ST.base) return ERROR;
ST.length = 0;
return OK;
}
Status Creat_Seq(SSTable &ST){
int count = 1;
printf("\n构造顺序表,输入-111意为停止输入\n");
scanf("%d",ST.base+count);
while(ST.base[count]!=-111){
count++;
if(count>MAXSIZE){
ST.base = (ElemType *)realloc(ST.base,(MAXSIZE+INCRESIZE)*sizeof(ElemType));
if(!ST.base) return ERROR;
}
scanf("%d",ST.base+count);
}
ST.length = --count;
return OK;
}
int Search_Seq(SSTable ST,KeyType key){//0号单元设哨兵
ST.base[0] = key;
int i;
for(i=ST.length;*(ST.base+i)!=key;i--) ;//空语句
return i;
}
Status Sort(SSTable &ST){
int min,temp;
for(int i=1;i<=ST.length;i++){
min = i;
for(int j=i;j<=ST.length;j++){
if(ST.base[min]>ST.base[j]) min = j;
}
temp = ST.base[min];
ST.base[min] = ST.base[i];
ST.base[i] = temp;
}
printf("\n\n排序后的序列为:");
for(int i=1;i<=ST.length;i++) printf("%d ",ST.base[i]);
}
int Search_Bin(SSTable ST,KeyType key){
int low=1,high=ST.length,mid;
Sort(ST);
while(low<=high){
mid = (low+high)/2;
if(EQ(key,ST.base[mid])) return mid;
else if(LT(key,ST.base[mid])) high = mid-1;
else low = mid+1;
}
return 0;
}
Status SearchBST(BiTree T,KeyType key,BiTree f,BiTree &p){//查找成功p为数据所在结点指针 否则是插入位置指针 f是工作指针 始终指向当前查找结点的父母
if(!T){
p = f;//直接插入在根结点
return FALSE;//查找失败
}else if(EQ(key,T->data)){
p = T;
return TRUE;//查找成功
}else if(LT(key,T->data)){
return SearchBST(T->lchild,key,T,p);//在左子树中继续查找
}else{
return SearchBST(T->rchild,key,T,p);//在右子树中继续查找
}
}
Status InsertBST(BiTree &T,ElemType e){
BiTree p;
if(!SearchBST(T,e,NULL,p)){//如果是空树的话p返回NULL 不是空树的话f在SearchBST()里会做改变 最后查找失败时p=f是不为空的
BiTree s = (BiTree)malloc(sizeof(BTNode));
s->data = e; s->lchild = s->rchild = NULL;
if(!p) T=s;//空树
else if(p->data>e) p->lchild = s;//已经查找到了叶子结点处
else p->rchild = s;
return TRUE;
}
return FALSE;
}
Status CreatBST(BiTree &T){
printf("\n\n建立一棵二叉排序树,输入-111意为停止\n");
ElemType e;
scanf("%d",&e);
while(e!=-111){
InsertBST(T,e);
scanf("%d",&e);
}
return OK;
}
int main(){
SSTable ST;
KeyType key;
BiTree T=NULL,p=NULL;
int locate;
Init_Seq(ST);
Creat_Seq(ST);
printf("\n\n请输入待查找的数:");
scanf("%d",&key);
if(Search_Seq(ST,key)) printf("\n\n顺序查找结果:%d在顺序表中的第%d位\n",key,Search_Seq(ST,key));
else printf("\n顺序查找失败 该数据不存在!\n");
locate = Search_Bin(ST,key);
if(locate) printf("\n折半查找结果:%d在有序表中的第%d位\n",key,locate);
else printf("\n\n折半查找失败 该数据不存在!\n");
CreatBST(T);
printf("\n请输入待查找的数:");
scanf("%d",&key);
SearchBST(T,key,NULL,p);
if(SearchBST(T,key,NULL,p)) printf("查找成功!\n");
else printf("查找失败!\n");
}
//哈希表的定义 创建 查找 插入 以数值型元素为例
#include<stdio.h>
#include<stdlib.h>
#define EQ(a,b) a==b
#define LT(a,b) a<b
#define LQ(a,b) a<=b
#define MAXSIZE 40
#define INCRESIZE 10
#define SUCCESS 1
#define UNSUCCESS 0
#define DUPLICATE -1
#define NULLKEY -111
typedef int KeyType;
typedef int Status;
typedef int ElemType;
typedef struct{
ElemType *base;//数据元素存储基址 动态分配数组
int count;//当前数据元素的个数
int sizeindex;//hashsize[sizeindex]为当前容量
}HashTable;
//初始化
Status InitHash(HashTable &H){
H.base = (ElemType *)malloc(MAXSIZE*sizeof(ElemType));
if(!H.base) exit(DUPLICATE);
H.sizeindex = MAXSIZE;
H.count = 0;
for(int i=0;i<H.sizeindex;i++) H.base[i] = NULLKEY;
return SUCCESS;
}
//构造哈希函数
Status Hash(ElemType e,int &p){//根据函数计算存储位置并赋给p
p = e%19;//除留余数法和平方取中法结合构造哈希函数
return SUCCESS;
}
Status collision(HashTable H,int &p){//线性探测再散列表
int i;
for(i=p+1;i<H.sizeindex;i++)
if(H.base[i]==NULLKEY) p=i;
if(i==H.sizeindex){
H.base = (ElemType *)realloc(H.base,(H.sizeindex+INCRESIZE)*sizeof(ElemType));
if(!H.base) exit(DUPLICATE);
H.sizeindex += INCRESIZE;
p = H.sizeindex;
}
return SUCCESS;
}
//在哈希表里查找key 如果查找成功 p存储在表中的下标 返回成功 否则p指示插入位置 返回不成功,c用来计算冲突个数
Status SearchHash(HashTable H,KeyType key,int &p,int &c){
Hash(key,p);//用公式来计算他在数组里的下标
//当该位置中填有记录 并且与所查找的关键字不相等的时候
while(H.base[p]!=NULLKEY&&H.base[p]!=key) {
collision(H,p);//求得下一探测地址
}
if(EQ(H.base[p],key)) return SUCCESS;
return UNSUCCESS;//NULLKEY
}
//插入
Status InsertHash(HashTable &H,ElemType e){
int p,c=0;//c初始值为0在建表的时候可以用作参考
if(SearchHash(H,e,p,c)){
return UNSUCCESS;
}
else{
H.base[p] = e;
H.count++;
return SUCCESS;
}
}
Status CreatHash(HashTable &H){
InitHash(H);
ElemType a;
printf("请构造哈希表 输入-111意为停止:\n");
scanf("%d",&a);
while(a!=-111){
if(!InsertHash(H,a)) printf("已存在该关键字!\n");
scanf("%d ",&a);
}
return SUCCESS;
}
void Visitall(HashTable H){
int num = H.count;
printf("\nresult:");
for(int i=0;i<H.sizeindex,num!=0;i++){
if(H.base[i]!=NULLKEY){
printf("%d ",H.base[i]);
num--;
}
}
}
int main(){
ElemType num;
int p,c;
HashTable H;
CreatHash(H);
Visitall(H);
printf("\n请输入你要查找的关键字:");
scanf("%d",&num);
if(SearchHash(H,num,p,c)) printf("\n查找成功!\n");
else printf("\n查找失败!\n");
return 0;
}