数据结构实验七(查找)

题目描述:为班级30个人的姓名设计一个哈希表,假设姓名用汉语拼音表示。要求用除留余数法
构造哈希函数,用线性探测再散列法处理冲突,平均查找长度的上限为2。编写数据结构和算法来实现。并在此基础上通过适当修改,采用顺序查找二分查找对姓名进行查找,计算两种方法的查找长度
本次有文档操作,故直接放本次文件
百度网盘提取提取码:2t3x
你的三连就是我创作的最大动力!
顺序查找的平均长度: n + 1 2 \frac{n+1}{2} 2n+1
折半查找的平均长度 : log ⁡ 2 ( n + 1 ) − 1 ( n ⟶ ∞ ) \log_2(n+1)-1 (n\longrightarrow\infty ) log2(n+1)1(n) 当n大于50时候,接近于 log ⁡ 2 ( n + 1 ) − 1 \log_2(n+1)-1 log2(n+1)1
用不同方法解决冲突时哈希表的平均查找长度(成功)

解决冲突的办法成功的查找(a为装填因子)
线性探查法 1 2 ( 1 + 1 1 − a ) \frac{1}{2}(1+\frac{1}{1-a} ) 21(1+1a1)
平方探查法 − 1 a log ⁡ e ( 1 − a ) -\frac{1}{a} \log_e(1-a) a1loge(1a)
拉链法 1 + a 2 1+\frac{a}{2} 1+2a

本例中,装填因子取0.71,平均查找长度约等于2,符合题意。
解答:
1.顺序查找算法的实现

/*顺序查找法*/
int SeqSearch(RecordList l,string cname){
   l.a[0].name=cname;
   int i=l.length;
   while(l.a[i].name!=cname) i--;
   return i;
}

2.折半查找算法的实现

/*先进行排序,折半查找法*/
int BinSearch(RecordList l,string cname){
    int low=1,high=l.length;
    int mid;
    while(low<=high){
        mid=(low+high)/2;
        if(l.a[mid].name==cname) return mid;
        else if(l.a[mid].name>cname) high=mid-1;
        else low=mid+1;
    }
    return 0;
}

3.散列查找算法的实现

/*在hash表中查找*/
void hashFind(string cname){
    int csum=asc(cname);
    int adr=csum%M,d=adr,count=1;
    if(hasha[adr].name==cname) cout<<cname<<"在hash表中是第"<<d<<"位,"<<"查找了"<<count<<"几次"<<endl;
    else if(hasha[adr].sum==0) cout<<"查无此人"<<endl;
    else{
        while(1){
            d=(d+(csum%10)+1)%M;
            count++;
            if(hasha[d].name==cname){
                cout<<cname<<"在hash表中是第"<<d<<"位,"<<"查找了"<<count<<"几次"<<endl;
                break;
            }
            if(hasha[d].sum==0){
                cout<<"查无此人"<<endl;
                break;
            }
        }
    }
}

将上述进行整合,其中30个姓名已做成txt文档。
并且通过Excel文档对三种方法进行整合,下面附完整代码进行验证。其中需要说明的是,这里折半查找的排序是通过字符串大小进行排序的,而Hash则是通过字符串的ASCII码除留余数法进行创建。其中hash装填因子我选的是0.71,(一共30个数据,hash表的长度为41)
有时间更新哈希表各种方法与STL中的hash,这个还是比较重要的!
下面附完整代码:

#include <iostream>
#include <cstring>
#include <string>
#include <fstream>
#include <algorithm>
#include <cmath>

using namespace std;

const int  hashlength=41;
#define M 37//比表长最大的素数

typedef struct{
    string name;
    int sum;
}Stud;

typedef struct{
    Stud a[100];//a[0]为工作单元
    int length;
}RecordList;

typedef struct{
    string name;
    int sum;
    int si;
}HashList;

/*以ASCII将姓名从小到大排*/
bool cmp(Stud a,Stud b){
    return a.name<b.name;
}

/*ascii求和*/
int asc(string name){
    int sum=0;
    for(int i=0;i<name.length();i++){
        sum+=name[i]-'a';
    }
    return sum;
}


/*顺序查找法*/
int SeqSearch(RecordList l,string cname){
   l.a[0].name=cname;
   int i=l.length;
   while(l.a[i].name!=cname) i--;
   return i;
}

/*先进行排序,折半查找法*/
int BinSearch(RecordList l,string cname){
    int low=1,high=l.length;
    int mid;
    while(low<=high){
        mid=(low+high)/2;
        if(l.a[mid].name==cname) return mid;
        else if(l.a[mid].name>cname) high=mid-1;
        else low=mid+1;
    }
    return 0;
}

HashList hasha[hashlength];


/*创建hash表*/
void CreatHash(RecordList l){
    int i,count,adr,d;
    /*初始化hash列表*/
    for(i=1;i<hashlength;i++){
        hasha[i].name="0";
        hasha[i].sum=0;
        hasha[i].si=0;
    }
    for(i=1;i<=30;i++){
        count=1;
        adr=(l.a[i].sum)%M;//hash函数
        d=adr;
        if(hasha[adr].si==0){//如果不冲突
            hasha[adr].name=l.a[i].name;
            hasha[adr].sum=l.a[i].sum;
            hasha[adr].si=1;
        }
        else{
            while(1){
                d=(d+(l.a[i].sum%10)+1)%M;
                count++;
                if(hasha[d].sum==0) break;
            }
            hasha[d].name=l.a[i].name;
            hasha[d].sum=l.a[i].sum;
            hasha[d].si=count;
        }
    }
}

/*在hash表中查找*/
void hashFind(string cname){
    int csum=asc(cname);
    int adr=csum%M,d=adr,count=1;
    if(hasha[adr].name==cname) cout<<cname<<"在hash表中是第"<<d<<"位,"<<"查找了"<<count<<"次"<<endl;
    else if(hasha[adr].sum==0) cout<<"查无此人"<<endl;
    else{
        while(1){
            d=(d+(csum%10)+1)%M;
            count++;
            if(hasha[d].name==cname){
                cout<<cname<<"在hash表中是第"<<d<<"位,"<<"查找了"<<count<<"次"<<endl;
                break;
            }
            if(hasha[d].sum==0){
                cout<<"查无此人"<<endl;
                break;
            }
        }
    }
}

int main(){
    RecordList l;
    l.length=0;
    ifstream in("Name.txt", ios::in);
	if (!in.is_open()) {
		cout <<"文件打开错误!"<< endl;
		exit (0);
	}
    cout<<"姓名保存在Name.txt文档中"<<endl;
    int i=1;
	while (!in.eof()) {
		in >> l.a[i].name;
        l.length++;
        i++;
	}
    for(i=1;i<=30;i++){
        l.a[i].sum=asc(l.a[i].name);
    }

    cout<<"请输入需要查找的姓名拼音"<<endl;
    string s;
    cin>>s;

    //顺序查找表
    int t=SeqSearch(l,s);
    if(t!=0){
        cout<<s<<"出现在乱序文件的第"<<t<<"位"<<endl;
    }
    else{
        cout<<"查无此人"<<endl;
    }
    cout<<"顺序查找成功的平均查找长度为"<<0.5*(30+1)<<endl;

    //折半查找
    sort(l.a+1,l.a+31,cmp);
    int tm=BinSearch(l,s);
    if(tm!=0){
        cout<<s<<"出现在正序文件的第"<<tm<<"位"<<endl;
    }
    else{
        cout<<"查无此人"<<endl;
    }
    cout<<"折半查找成功的平均长度"<<log(31)/log(2)-1<<endl;

    //Hash表
    CreatHash(l);
    hashFind(s);
    return 0;
}


下面是运行结果
在这里插入图片描述
我这里查找的是lihao字符,通过excel表格查看,确实符合上述答案。当然我提前在excel表格中创建这序列,通过打印字符串然后保存文件。
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值