散列法实验研究源代码

合集下载

散列查找顺序表的实现实验报告

散列查找顺序表的实现实验报告

题目:顺序表的实现一、实验题目顺序表的实现二、实验目的⑴掌握线性表的顺序存储结构;⑵验证顺序表及其基本操作的实现;⑶理解算法与程序的关系,能够将顺序表算法转换为对应的程序。

三、实验内容与实现⑴建立含有若干个元素的顺序表;⑵对已建立的顺序表实现插入、删除、查找等基本操作。

实验实现#include<stdio.h>#include<memory.h>int a[10000];int arrlong(){int j;for(j=0;j<12;j++)if(a[j]==0)break;return j;}int Insect(int n,int s) ////插入{int j;for(j=0;j<10000;j++)if(a[j]==0)break;printf("要操作的元素\n");for(int i=0;i<j;i++)printf("%d ",a[i]);printf("\n");for(int i=j;i>n-1;i--)a[i+1]=a[i];a[n]=s;for(int k=0;k<j+1;k++)printf("%d ",a[k]);printf("\n");}int Search(int p) //查找{int j,h;for(j=0;j<12;j++){if(a[j]==0)break;}for(h=0;h<j;h++){if(a[h]==p){printf("查找到的数在第%d位\n",h+1);break;}}if(h==j)printf("查无此数\n");}int Delate(int g,int q) //删除{int j;g=g-1;for(int j=g;j<12;j++)a[j]=a[j+1];for(q =0;q<12;q++){if(a[q]==0)break;}for(int i=0;i<q;i++)printf("%d ",a[i]);printf("\n");}int main(){int y,c;printf(" 菜单\n");printf("-------------------------------------------------\n");printf("0 建表\n1 插入\n2 查找\n3 删除\n4 退出\n");printf("-------------------------------------------------\n");while(scanf("%d",&y)!=EOF){int n,x,s;if(y==0){memset(a,0,sizeof(a));printf("请输入元素的个数:\n");scanf("%d",&c);printf("请输入数据:\n");for(int i = 0;i < c;i++)scanf("%d",&a[i]);}else if(y==1){int L;printf("请输入插入的第几位\n");scanf("%d",&n);//输入L=arrlong();if(n<=L){printf("请输入插入的数字\n");scanf("%d",&s);Insect(n,s);}else{printf("输入有误\n");continue;}}else if(y==2){int p;printf("请输入要查找的数字\n");scanf("%d",&p);Search(p);}else if(y==3){int g,q,L;printf("请输入要删除数的位置\n");scanf("%d",&g);L=arrlong();if(L>=g){Delate(g,q);}else{printf("输入有误\n");printf(" 菜单\n");printf("-------------------------------------------------\n");printf("0 建表\n1 插入\n2 查找\n3 删除\n4 退出\n");printf("-------------------------------------------------\n");continue;}}else if(y==4)break;else{printf("输入有误\n");printf(" 菜单\n");printf("-------------------------------------------------\n");printf("0 建表\n1 插入\n2 查找\n3 删除\n4 退出\n");printf("-------------------------------------------------\n");continue;}printf(" 菜单\n");printf("-------------------------------------------------\n");printf("0 建表\n1 插入\n2 查找\n3 删除\n4 退出\n");printf("-------------------------------------------------\n");}}建立顺序表:插入操作:查找操作:删除操作:插入数据超出顺序表范围:查找不到输入数据:删除数据超出顺序表范围:四、实验心得1.掌握了为数组赋值的方法,深刻理解了数组的含义2.掌握了为数组排序的方法。

山东大学-数据结构实验报告-矩阵和散列表

山东大学-数据结构实验报告-矩阵和散列表

山东大学计算机科学与技术学院数据结构课程实验报告了Input函数和Output函数。

对问题三,仿课本所述,定义Term类作为SparseMatrix类的友元类,包含行、列、值三个要素的成员变量,用Term类的数组实现稀疏矩阵的行主映射存储。

查找行为的实现方式是,找到位于目标元素前一行的最后一个元素,再从这个元素开始向下搜索,直到找到和目标元素同一行但是列数小于目标元素的元素a[k-1],然后决定下一步的行为————插入一个新项Term作为a[k]并将已有元素向后移位,还是修改已存在的项a[k]。

以此原理编写了Store和Retrieve函数,并扩展编写了Input函数和Output函数。

对问题四,仿照课本例子编写了有序链表类SortedChain、开放寻址的散列表类HashTable、基于有序链表链接的散列表类ChainHashTable,并对这三个类分别扩展编写了Output函数。

3.测试结果(测试输入,测试输出)问题一:问题二:上图显示了输入不符合下三角方阵约束时,抛出异常并退出程序。

上图是正常运行的结果。

问题三:普通的输入和输出操作如下:矩阵相加:矩阵转置:问题四:以上图的数据为例。

从346就应该在链表链接的散列表上看到开放寻址解决冲突的例子。

返回开放寻址的输出段,可以看到符合预期的结果:4.实现源代码(程序风格清晰易理解,有充分的注释)/** TridiagonalMatrix.h** Created on: Nov 22, 2015* Author: xudp*/#ifndef TRIDIAGONALMATRIX_H_#define TRIDIAGONALMATRIX_H_#include<iostream>using namespace std;template<class T>class TridiagonalMatrix {public:// 1、创建三对角矩阵类,采用按列映射方式,提供 store 和 retrieve 方法。

数据结构课程设计-散列法的研究大全

数据结构课程设计-散列法的研究大全

数据结构课程设计-散列法的研究大全第一篇:数据结构课程设计-散列法的研究大全学院:班级:完成人:姓指导教师:数据结构课程设计说明书信息科学与工程学院计算机科学与技术名:学号:山东科技大学 2013年12月25日课程设计任务书一、课程设计题目:散列法的实验研究二、课程设计应解决的主要问题:(1)数据元素的输入和输出(2)线性再散列法建立哈希表(3)二次探测再散列法建立哈希表(4)链地址法建立哈希表(5)线性再散列法进行数据查找(6)二次探测再散列法进行数据查找(7)链地址法进行数据查找(8)退出系统三、任务发出日期: 2013-10-01 课程设计完成日期: 2013-12-20小组分工说明小组编号 7 题目:散列法的实验研究小组分工情况:一人独立完成所有工作。

组长签字: 2013 年 12 月 31 日指导教师对课程设计的评价成绩:指导教师签字:年月日目录1.需求分析说明2.概要设计说明3.详细设计说明4.调试分析5.用户使用说明6.课程设计总结7.测试结果8.参考书目-3-4-5-7-8-10-10-12需求分析说明内部排序教学软件的总体功能要求:散列法中,散列函数构造方法多种多样,同时对于同一散列函数解决冲突的方法也可以不同。

两者是影响查询算法性能的关键因素。

对于几种典型的散列函数构造方法,做实验观察,不同的解决冲突方法对查询性能的影响。

基本功能如下:(1)界面友好,易与操作。

采用菜单方式进行选择。

(2)实现三种方法进行哈希表的构造。

包括线性再散列法、二次探测再散列法和链地址法。

(3)根据三种构造方法分别进行数据元素的查找,若查找成功,则同时输出探查/冲突次数。

以下是各功能模块的功能描述: 1.主函数模块本模块的主要功能是初始化图形界面,调用各模块,实现功能。

2.构造哈希表子模块本模块的主要功能是采用线性再散列法、二次探测再散列法、链地址法三种方法构造哈希表。

3.查找功能及输出子模块本模块的主要功能是在采用线性再散列法、二次探测再散列法、链地址法三种方法构造哈希表后,采用相应的方法对键入的数据进行查找,并计算探查/冲突次数。

散列表实验报告(不同装载因子下链表法和放寻址法对比)

散列表实验报告(不同装载因子下链表法和放寻址法对比)

散列表实验报告(不同装载因子下链表法和放寻址法对比)TOC \o “1-4“ \h \z \u 1 概述22 原理介绍22.1 散列表介绍22.2 直接寻址表32.3 散列函数32.3.1 除法散列42.3.2 乘法散列42.3.3 全域散列42.4 解决碰撞问题52.4.1 链接法52.4.2 开放寻址法52.4.2.1 线性探查62.4.2.2 二次探查62.4.2.3 双重散列73 算法说明73.1 概述73.2 使用链接法解决碰撞问题83.2.1 算法思想83.2.2 伪代码描述93.2.3 算法分析与证明103.3 使用开放寻址法的双重散列解决碰撞问题123.3.1 算法思想123.3.2 伪代码描述123.3.3 算法分析与证明143.4 两个算法的比较144 实验设计与分析165 C++实现与结果分析185.1 C++实现与结果185.2 结果分析266 实验总结和感想27概述该实验报告主要是通过介绍散列表的各种技术,包括散列函数、解决碰撞的机制等技术,并对两种解决碰撞的机制:链接法和开放寻址法进行分析和证明,并通过实验分析两者在不同的规模下的运行时间和空间占用的对比,来证明在“算法说明”一章中的理论分析。

原理介绍散列表介绍散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。

也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。

这个映射函数叫做散列函数,存放记录的数组叫做散列表。

它实际上是是普通数组概念的推广,因为可以对数组进行直接寻址,故可以而在O(1)时间内访问数组的任意元素。

如果存储空间允许,我们可以提供一个数组,为每个可能的关键字保留一个位置,就可以应用直接寻址技术。

基本概念若结构中存在关键字和K相等的记录,则必定在f(K)的存储位置上。

由此,不需比较便可直接取得所查记录。

称这个对应关系f为散列函数(Hash function),按这个思想建立的表为散列表。

数据结构C语言实现散列:创建、解决冲突、查找元素

数据结构C语言实现散列:创建、解决冲突、查找元素

实验课题:做这个实验时采用Open Addressing框架,也可加做Separate Chaining以形成比较。

1 构造散列表,把字符串数组中的各项加入到散列表中string MyBirds[13] = { "robin", "sparrow", "hawk", "eagle", "seagull", "bluejay","owl", "cardinal", "Jakana", "Moa", "Egret", "Penguin", "hawk" };用C表示,可以是char * MyBirds[13] = { "robin", "sparrow", "hawk", "eagle", "seagull", "bluejay","owl", "cardinal", "Jakana", "Moa", "Egret", "Penguin", "hawk" };为便于观察冲突现象,初始构造散列表时,表的容量不要过大,对Open Addressing,装载因子为0.5左右,对于Separate Chaining,装载因子为1左右即可。

也不要做rehash(应该改源代码的哪里,如何改)。

建议对源代码做些改动、增加一些输出(建议用条件编译控制这些输出),以便于观察冲突的发生和解决;对于Open Addressing,参考代码的冲突解决方案是用的平方探测(quadratic probing),如果用线性探测(linear probing)的策略,应该对函数findPos做什么修改(冲突解决的策略都集中在那里)?2 观察不同的散列函数产生冲突散列地址的情况教科书上给了3个以字符串作输入的散列函数(两教科书第3个不一样),观察记录它们产生冲突散列地址的情况,写入你的实验报告。

数据结构实验 散列表实验报告

数据结构实验 散列表实验报告

数据结构实验散列表实验报告一、实验目的本次实验的主要目的是深入理解和掌握散列表这种数据结构的基本原理、实现方法以及其在实际应用中的性能特点。

通过实际编写代码和进行相关测试,提高对散列表的操作能力,并能够分析和解决在使用散列表过程中可能遇到的问题。

二、实验原理散列表(Hash Table)是一种根据关键码值(Key value)而直接进行访问的数据结构。

通过一个特定的函数(哈希函数)将关键码映射到表中的一个位置来访问记录,以加快查找的速度。

这个映射函数称为哈希函数,存放记录的数组称为哈希表。

哈希函数的设计至关重要,它需要尽可能地将不同的关键码值均匀地分布在哈希表中,以减少冲突的发生。

常见的哈希函数有直接定址法、除留余数法、数字分析法等。

冲突解决方法也是散列表中的重要部分。

当不同的关键码通过哈希函数映射到相同的位置时,就会产生冲突。

常见的冲突解决方法有开放定址法(线性探测、二次探测等)和链地址法。

三、实验环境本次实验使用的编程语言为C++,开发工具为Visual Studio 2019。

四、实验内容1、哈希函数的实现采用除留余数法实现哈希函数。

代码如下:```cppint hashFunction(int key, int tableSize) {return key % tableSize;}```2、散列表的创建与初始化使用动态数组创建散列表,并将所有位置初始化为空。

```cppclass HashTable {private:int table;int size;public:HashTable(int tableSize) {size = tableSize;table = new intsize;for (int i = 0; i < size; i++){tablei =-1; //-1 表示为空}}~HashTable(){delete table;}};```3、数据插入操作采用线性探测法解决冲突。

SHA

SHA

用Java语言实现的安全散列算法SHA的源代码:import java.io.*;import java.util.*;public class SHA1 {private final int[] abcde = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };private int[] digestInt = new int[5];private int[] tmpData = new int[80];private int process_input_bytes(byte[] bytedata) { System.arraycopy(abcde, 0, digestInt, 0, abcde.length);byte[] newbyte = byteArrayFormatData(bytedata);int MCount = newbyte.length / 64;for (int pos = 0; pos < MCount; pos++) {for (int j = 0; j < 16; j++) {tmpData[j] = byteArrayToInt(newbyte, (pos * 64) + (j * 4)); }encrypt(); }return 20; }private byte[] byteArrayFormatData(byte[] bytedata) {int zeros = 0;int size = 0;int n = bytedata.length;int m = n % 64;if (m < 56) {zeros = 55 - m;size = n - m + 64;} else if (m == 56) {zeros = 63;size = n + 8 + 64;} else {zeros = 63 - m + 56;size = (n + 64) - m + 64; }byte[] newbyte = new byte[size];System.arraycopy(bytedata, 0, newbyte, 0, n);int l = n;newbyte[l++] = (byte) 0x80;for (int i = 0; i < zeros; i++) {newbyte[l++] = (byte) 0x00; }long N = (long) n * 8;byte h8 = (byte) (N & 0xFF);byte h7 = (byte) ((N >> 8)& 0xFF);byte h6 = (byte) ((N >> 16) & 0xFF);byte h5 = (byte) ((N >> 24) & 0xFF);byte h4 = (byte) ((N >> 32) & 0xFF);byte h3 = (byte) ((N >> 40) & 0xFF);byte h2 = (byte) ((N >> 48) & 0xFF);byte h1 = (byte) (N >> 56);newbyte[l++] = h1;newbyte[l++] = h2;newbyte[l++] = h3;newbyte[l++] = h4;newbyte[l++] = h5;newbyte[l++] = h6;newbyte[l++] = h7;newbyte[l++] = h8;return newbyte; }private int f1(int x, int y, int z) {return (x & y) | (~x & z); }private int f2(int x, int y, int z) {return x ^ y ^ z; }private int f3(int x, int y, int z) {return (x & y) | (x & z) | (y & z); } private int f4(int x, int y) {return (x << y) | x >>> (32 - y); }private void encrypt() {for (int i = 16; i <= 79; i++) {tmpData[i] = f4(tmpData[i - 3] ^ tmpData[i - 8] ^ tmpData[i - 14] ^tmpData[i - 16], 1); }int[] tmpabcde = new int[5];for (int i1 = 0; i1 < tmpabcde.length; i1++) {tmpabcde[i1] = digestInt[i1]; }for (int j = 0; j <= 19; j++) {int tmp = f4(tmpabcde[0], 5) +f1(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] +tmpData[j] + 0x5a827999;tmpabcde[4] = tmpabcde[3];tmpabcde[3] = tmpabcde[2];tmpabcde[2] = f4(tmpabcde[1], 30);tmpabcde[1] = tmpabcde[0];tmpabcde[0] = tmp; }for (int k = 20; k <= 39; k++) {int tmp = f4(tmpabcde[0], 5) +f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] +tmpData[k] + 0x6ed9eba1;tmpabcde[4] = tmpabcde[3];tmpabcde[3] = tmpabcde[2];tmpabcde[2] = f4(tmpabcde[1], 30);tmpabcde[1] = tmpabcde[0];tmpabcde[0] = tmp; }for (int l = 40; l <= 59; l++) {int tmp = f4(tmpabcde[0], 5) +f3(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] +tmpData[l] + 0x8f1bbcdc;tmpabcde[4] = tmpabcde[3];tmpabcde[3] = tmpabcde[2];tmpabcde[2] = f4(tmpabcde[1], 30);tmpabcde[1] = tmpabcde[0];tmpabcde[0] = tmp; }for (int m = 60; m <= 79; m++) {int tmp = f4(tmpabcde[0], 5) +f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] +tmpData[m] + 0xca62c1d6;tmpabcde[4] = tmpabcde[3];tmpabcde[3] = tmpabcde[2];tmpabcde[2] = f4(tmpabcde[1], 30);tmpabcde[1] = tmpabcde[0];tmpabcde[0] = tmp; }for (int i2 = 0; i2 < tmpabcde.length; i2++) {digestInt[i2] = digestInt[i2] + tmpabcde[i2]; }for (int n = 0; n < tmpData.length; n++) {tmpData[n] = 0; } }private int byteArrayToInt(byte[] bytedata, int i) {return ((bytedata[i] & 0xff) << 24) | ((bytedata[i + 1] & 0xff) << 16) |((bytedata[i + 2] & 0xff) << 8)| (bytedata[i + 3] & 0xff); }private void intToByteArray(int intValue, byte[] byteData, int i) {byteData[i] = (byte) (intValue >>> 24);byteData[i + 1] = (byte) (intValue >>> 16);byteData[i + 2] = (byte) (intValue >>> 8);byteData[i + 3] = (byte) intValue; } private static String byteToHexString(byte ib) { char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };char[] ob = new char[2];ob[0] = Digit[(ib >>> 4) & 0X0F];ob[1] = Digit[ib & 0X0F];String s = new String(ob);return s; }private static String byteArrayToHexString(byte[] bytearray) {String strDigest = "";for (int i = 0; i < bytearray.length; i++) {strDigest += byteToHexString(bytearray[i]); }return strDigest; }public byte[] getDigestOfBytes(byte[] byteData) {process_input_bytes(byteData);byte[] digest = new byte[20];for (int i = 0; i < digestInt.length; i++) {intToByteArray(digestInt[i], digest, i * 4); }return digest; }public String getDigestOfString(byte[] byteData) {returnbyteArrayToHexString(getDigestOfBytes(byteData)); }public static void main(String[] args) {String data;Scanner sc = new Scanner(System.in);System.out.println("请输入明文内容:");data = sc.nextLine();System.out.println("\n确认内容:");System.out.println(data);System.out.println("\nSHA-1:");String digest = new SHA1().getDigestOfString(data.getBytes());System.out.println(digest); } }。

散列数据结构代码(线性探测法和拉链法)

散列数据结构代码(线性探测法和拉链法)

散列数据结构代码(线性探测法和拉链法)线性探测法1//使⽤线性探测法和数组结构创建散列表,2//然后输⼊数据的查询。

并且将创建过程3//都输出来4 #include <stdlib.h>5 #include <stdio.h>6 #include <time.h>7#define MAX 10 //最⼤数组容量8#define NUM 8 //随机数⽣成的个数9#define BLANK -1 //空⽩空间1011int hashtable[MAX]; //散列表声明1213//散列函数14int hashfunc(int value)15 {16return value % MAX; //余数17 }1819//线性探测法20int linehash(int key)21 {22int pos; //位置变量23int temp;2425 pos = hashfunc(key);26 temp = pos; //保留开始位置27while(hashtable[temp] != key && //线性探测循环28 hashtable[temp] != BLANK)29 {30//使⽤余数将数组变为环状31 temp = (temp + 1) % MAX; //下⼀个位置32if(pos == temp) //查询结束33return -1; //没有找到34 }35if(hashtable[temp] == BLANK) //是否空⽩36return -1;37else38return temp; //找到了39 }404142//创建散列表43void createtable(int key)44 {45int pos; //位置变量46int temp;47//调⽤散列函数计算位置48 pos = hashfunc(key);49 temp = pos; //保留开始位置50while(hashtable[temp] != BLANK) //找寻存⼊位置51 {52 temp = (temp + 1) % MAX; //下⼀个位置53if(pos == temp) //散列表是否已满54 {55 printf("散列表已满!\n");56return;57 }58 }59 hashtable[temp] = key; //存⼊散列表60 }616263//主程序:散列查找法64int main()65 {66int checked[50]; //检查数组67int i,j,temp;68long temptime;69for(i = 0;i < MAX;i++)70 hashtable[i] = BLANK; //清除散列表71for(i = 0;i < 50;i++)72checked[i] = 0; //清楚检查数组7374 printf("散列表内容:\n");75 srand(time(&temptime) % 60); //使⽤时间初始随机数76 i = 0;77while(i != NUM) //⽣成数组值的循环79 temp = rand() % 50; //随机数取值 0-49 80if(checked[temp] == 0) //是否是已有的值81 {82 createtable(temp); //创建散列表83 printf("%2d => ",temp);84for(j = 0;j < MAX;j++) //输出散列表85 printf("[%2d]",hashtable[j]);86 printf("\n");87checked[temp] = 1; //设置此值⽣成过88 i++; //下⼀个数组值89 }90 }9192while(1) //主循环开始93 {94 printf("\n请输⼊查找值(0-49) ==> ");95 scanf("%d",&temp); //导⼊查找值96if(temp != -1)97 {98 i = linehash(temp); //调⽤散列查找99if(i != -1)100 printf("找到查找值:%d[%d]\n",temp,i); 101else102 printf("没有找到查找值:%d\n",temp); 103 }104else105 exit(1); //结束程序106 }107return0;108 }⽤链表创建散列表1//⽤链表创建散列表2 #include <stdlib.h>3 #include <time.h>4 #include <stdio.h>5#define MAX 106#define NUM 1078struct list9 {10int key;11struct list*next;12 };13 typedef struct list node;14 typedef node* link;1516 node hashtable[MAX];1718int hashfunc(int value)19 {20return value % MAX;21 }23int linkhash(int key)24 {25 link ptr;26int pos;2728 pos = hashfunc(key);29 ptr = hashtable[pos].next;30while(ptr != NULL)31if(ptr->key == key)32return1;33else34 ptr = ptr->next;35return0;36 }3738void createtable(int key)39 {40 link ptr;41 link new;42int pos;4344new = (link)malloc(sizeof(node));45new->key = key;46new->next = NULL;4748 pos = hashfunc(key);49 ptr = hashtable[pos].next;50if(ptr != NULL)51 {52new->next = ptr;53 hashtable[pos].next = new;54 }55else56 hashtable[pos].next = new;57 }5859int main()60 {61 link ptr;62int checked[50];63int i,temp;64long temptime;65for(i = 0;i < MAX;i++)66 hashtable[i].next = NULL;67for(i = 0;i < 50;i++)68checked[i] = 0;6970 srand(time(&temptime) % 60);71 i = 0;72while(i != NUM)73 {74 temp = rand() % 50;75if(checked[temp] == 0)76 {77 createtable(temp);78checked[temp] = 1;79 i++;80 }81 }82 printf("散列表内容:\n");83for(i = 0;i < MAX;i++)84 {85 printf("\n%2d ==> ",i);86 ptr = hashtable[i].next;87while(ptr != NULL)88 {89 printf("[%2d]",ptr->key);90 ptr = ptr->next;91 }92 }9394while(1)95 {96 printf("\n请输⼊查找值(0-49) ==> ");97 scanf("%d",&temp);98if(temp != -1)99 {100 i = linkhash(temp);101if(i != 0)102 printf("找到查找值:%d\n",temp); 103else104 printf("没有找到查找值:%d\n",temp); 105 }106else 107 exit(1); 108 }109return0; 110 }。

数据结构实验散列表

数据结构实验散列表

计算机科学与技术系之欧侯瑞魂创作哈希表的设计与实现项目陈说专业名称计算机科学与技术项目课程数据结构与算法项目名称哈希表的设计与实现班级项目人员钱海峰,郑秀娟,王传敏,杨青,凌波实验日期 2015.12.9目录一.设计目的 (3)二.问题分析 (3)三.设计环境 (3)四.人员分配 (3)五.详细设计和编码 (4)六.实验分析 (7)1测试分析 (7)2性能分析……………………………………………………11附录 (12)参考书目 (17)一.设计目的(1)掌握散列结构和散列函数的相关概念(2)掌握散列结构的存储结构的相关概念(2)掌握散列抵触的处置方法(3)运用散列解决抵触问题.二.问题分析要完成如下要求:设计哈希表实现整数查询系统.实现本项目需要解决以下问题:(1)如何设计一个哈希表.(2)如何在哈希表中拔出记录.(3)如何删除哈希表中的记录.(4)如何查找并显示记录.(5)如何解决抵触问题.三.设计环境⒈硬件:计算机每人一台.⒉软件:Windows把持系统和Microsoft Visual VC++6.0编译器.四.人员分配五.详细设计和编码1.界说结点结构类型在链地址法中,每个结点对应一个链表结点,由3个域组成,结构如图9-1所示.其中,key为关键字域,寄存结点关键字;data为数据域,寄存结点数据信息;next为链域,寄存指向下一个同义词结点的指针.图9-1 链地址法结点结构链地址数据结构类型如下:#define MAX_LENGTH 50typedef struct node{int data;struct node *next;}ElemNode;typedef struct{ElemNode *first;}ElemHeader,HashTable[MAX_LENGTH];#include <stdio.h>设计一个Hash()函数,本设计中对散列函数选择的是除留余数法,即对关键字进行模运算,将运算结果所得的余数作为关键字(或结点)的存储地址,即i=ht mod n,本设计n由用户自己输入,然后将计算出来的结果返回.具体设计如下:int Hash(int ht){ int i;i = ht%n;return i;}3.初始化散列链表初始化链地址散列算法只需要把散列表中所有表头结点的指针域置为NULL.初始化散列链表的算法如下:void initHashTable(HashTable ht,int n){int i;for(i =0;i<n;i++){ ht[i].first= NULL;}}在整个设计中,创立哈希表必需是第一步要做的,结点之前应先输入结点的个数,利用链地址法解决抵触.添加结点实际是调用了拔出结点函数insert(),需要利用哈希函数计算出地址,其次将结点拔出以关键字为地址的链表后.建立结点应包括静态申请内存空间,想地址中输入信息,同时最后一个结点中的next指针即是NULL.具体实现如下:int createHashTable(HashTable ht){HashTable *p=ht;int ad[MAX_LENGTH]={0};int i;printf("请输入拔出个数n:");scanf("%d",&n);printf("\n请输入拔出%d个整数:",n);for(i=0;i<n;i++)scanf("%d",&ad[i]);initHashTable(p,n);for(i=0;i<n;i++)insert(p,ad[i]);return 1;5.散列链表拔出结点算法将一个结点拔出到散列链表中,其算法分为以下几步:(1)根据结点关键字计算散列地址;(2)根据散列地址找到表头结点,并将结点拔出到对应的链表中.链地址法散列表的拔出算法如下:void insert(HashTable ht,int ele){int i;ElemNode *p;i=Hash(ele);p=(ElemNode *)malloc(sizeof(ElemNode));p->data = ele;p->next = ht[i].first;ht[i].first = p;}6.散列链表查找结点算法在散列链表中查找一个结点,其算法分为以下几步:(1)根据待查找关键字计算散列地址;(2)在散列地址所指向的单链表中顺序查找待查找关键字;(3)如果找到待查关键字,则返回指向该结点的指针;否则返回NULL.散列链表中查找结点的算法如下:ElemNode* search(HashTable ht,int ele){ int i;ElemNode *p;i = Hash(ele);p=ht[i].first;while(p!=NULL && p->data != ele){ p = p->next; }if(p!=NULL){printf("数据%d的位置为%d\n",ele,i);return p;}else{ printf("哈希表中无%d\n",ele);return p;}}7.散列链表删除结点算法在散列表中删除一个结点,其算法分为两步:(1)查找要删除的结点;(2)如果找到则删除,否则显示提示信息.在散列表中删除一个结点的算法如下:void dele(HashTable ht,int ele){//删除指定命据int i;ElemNode *p,*q;i = Hash(ele);p=ht[i].first;if(p == NULL){printf("error occurred! ");}if(p->data == ele){ht[i].first = p->next;}else {q= p->next;while(q!=NULL && q->data != ele){p=q;q = q->next;}if(q == NULL){printf("error occurred! ");}else{p->next = q->next;free(q);}}}六.实验分析1.测试分析(1)建立哈希表(2)拔出一个结点并显示:(3)查找结点:在哈希表中没有3这个数,会输出一行提示信息.(4)删除一个结点并显示:2.性能分析散列法实质上是一种通过关键字直接计算存储地址的方法.在理想情况下,散列函数可以把结点均匀地分布在散列表中,不发生抵触,则查找过程无需比力,其时间复杂度O(1).但在实际使用过程中,为了将范围广泛的关键字映射到一组连续的存储空间,往往会发生同义词抵触,这时就需要进行关键字比力.能够把关键字尽可能均匀地分布到散列表中的函数是“好”的散列函数.好的散列函数可以有效地降低抵触的的发生,从而提高查找性能.但好的散列函数和关键字的数字特征有关,因此不存在对任何结点都好的散列函数.对同一种散列函数,采纳分歧的抵触处置方法将发生分歧的效果,例如线性探测法容易招致“二次聚集”,而拉链法可以从根本上根绝二次聚集,从而提高查找性能.不外也会“浪费”一部份散列表的空间.附录****************************法式源代码*********************************//头文件#include <stdio.h>#include <stdlib.h>#define MAX_LENGTH 50typedef struct node{int data;struct node *next;}ElemNode;typedef struct{ElemNode *first;}ElemHeader,HashTable[MAX_LENGTH];int n;//存储哈希表长度void initHashTable(HashTable ht,int n);void insert(HashTable ht,int ele);ElemNode* search(HashTable ht,int ele);void dele(HashTable ht,int ele);int Hash(int ht);int createHashTable(HashTable ht);void showHashTable(HashTable ht);void menu(HashTable ht);//菜单//功能函数sanlibiao.c#include"sanlibiao.h"void initHashTable(HashTable ht,int n){//初始化int i;for(i =0;i<n;i++){ht[i].first= NULL;}}void insert(HashTable ht,int ele){//拔出int i;ElemNode *p;i=Hash(ele);p=(ElemNode *)malloc(sizeof(ElemNode)); // p->key = ele;p->data = ele;p->next = ht[i].first;ht[i].first = p;}ElemNode* search(HashTable ht,int ele){//查找int i;ElemNode *p;i = Hash(ele);p=ht[i].first;while(p!=NULL && p->data != ele){p = p->next;}if(p!=NULL){printf("数据%d的位置为%d\n",ele,i);return p;}else{printf("哈希表中无%d\n",ele);return p;}}void dele(HashTable ht,int ele){//删除指定命据int i;ElemNode *p,*q;i = Hash(ele);p=ht[i].first;if(p == NULL){printf("error occurred! ");}if(p->data == ele){ht[i].first = p->next;}else {q= p->next;while(q!=NULL && q->data != ele){p=q;q = q->next;}if(q == NULL){printf("error occurred! ");}else{p->next = q->next;free(q);}}}int Hash(int ht){//哈希函数int i;i = ht%n;return i;}int createHashTable(HashTable ht)//创立哈希表{HashTable *p=ht;int ad[MAX_LENGTH]={0};int i;printf("请输入拔出个数n:");scanf("%d",&n);printf("\n请输入拔出%d个整数:",n);for(i=0;i<n;i++)scanf("%d",&ad[i]);initHashTable(p,n);for(i=0;i<n;i++)insert(p,ad[i]);return 1;}void showHashTable(HashTable ht)//显示哈希表{int i;ElemNode *p;//i = Hash(ele);for(i=0;i<n;i++){p=ht[i].first;if(p!=NULL)printf("位置%d上的数据:",i);while(p!=NULL){printf("%d ",p->data);p = p->next;}if(ht[i].first!=NULL)printf("\n");}}void menu(HashTable ht){int p,h; //p 菜单选择;do{// system("cls");//清屏printf("★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆\n");printf("☆★☆★\n");printf("★☆************** 欢迎来到哈希表系统! ***************★☆\n");printf("☆★合肥学院☆★\n");printf("★☆计算机科学与技术★☆\n");printf("☆★钱海峰,郑秀娟,王传敏,杨青,凌波☆★\n");printf("☆★☆★\n");printf("☆★※※※※※※※☆★\n");printf("★☆※菜单※★☆\n");printf("☆★※※※※※※※☆★\n");printf("☆★☆★\n");printf("★☆************** (1)---创立哈希表******************★☆\n");printf("☆★************** (2)---查找******************★☆\n");printf("★☆************** (3)---删除******************★☆\n");printf("☆★************** (4)---拔出******************★☆\n");printf("★☆************** (5)---输出哈希表******************★☆\n");printf("☆★************** (0)---退出******************☆★\n");printf("★☆****************************************************★☆\n");printf("☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★\n");printf("\n请在上述序号中选择一个并输入: ");scanf("%d",&p);switch(p){case 1:createHashTable(ht);break;case 2:printf("请输入要查找的数:\n");scanf("%d",&h);search(ht,h);break;case 3:printf("请输入要删除的数:\n");scanf("%d",&h);dele(ht,h);printf("\n");break;case 4:printf("请输入要拔出的数:\n");scanf("%d",&h);insert(ht,h);printf("\n");break;case5:showHashTable(ht);printf("\n");break;case 0: break; //退出default:printf("输入毛病!请重新输入!\n");break;}//system("pause");//系统暂停,提示按任意键继续....}while(p!=0); //for do}//主函数 mian.c#include "sanlibiao.h"int main(){HashTable ht;menu(ht);//进入菜单循环return 0;参考书目王昆仑,李红,《数据结构与算法》,中国铁道出书社,2007年6月初版.谭浩强,《C语言法式设计》,北京:清华年夜学出书社,2005年7月第三版.。

散列法的实验研究课程设计报告

散列法的实验研究课程设计报告

课程设计报告问题描述:(1) 散列法中,散列函数构造方法多种多样,同时对于同一散列函数解决冲突的方法也可以不同。

两者是影响查询算法性能的关键因素。

(2) 程序实现几种典型的散列函数构造方法,并观察,不同的解决冲突方法对查询性能的影响。

a. 需求分析:散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。

对不同的关键字可能得到同一散列地址,即key1≠key2,而f(key1)=f(key2),这种现象称冲突。

具有相同函数值的关键字对该散列函数来说称做同义词。

综上所述,根据散列函数H(key)和处理冲突的方法将一组关键字映象到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“象”作为记录在表中的存储位置,这种表便称为散列表,这一映象过程称为散列造表或散列,所得的存储位置称散列地址。

散列表的查找过程基本上和造表过程相同。

一些关键码可通过散列函数转换的地址直接找到,另一些关键码在散列函数得到的地址上产生了冲突,需要按处理冲突的方法进行查找。

对散列表查找效率的量度,依然用平均查找长度来衡量。

查找过程中,关键码的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。

因此,影响产生冲突多少的因素,也就是影响查找效率的因素。

该课程设计要求比较几种哈希函数的构造方法和解决冲突的方法对查询性能的影响。

b. 概要设计该程序实现对哈希函数的构造方法、处理冲突的方法及在哈希表中查找数据的功能。

用线性再散列方法建立哈希表,用代码实现为:typedef struct{int key;int si;}HashTable1;void CreateHashTable1(HashTable1 *H,int *a,int num)//哈希表线性探测在散列;{int i,d,cnt;for(i=0;i<HashSize;i++){H[i].key=0;H[i].si=0;}for(i=0;i<num;i++){cnt=1;d=a[i]%HashSize;if(H[d].key==0){H[d].key=a[i];H[d].si=cnt;}else{do{d=(d+1)%HashSize; cnt++;}while(H[d].key!=0); H[d].key=a[i];H[d].si=cnt;}}printf("\n线性再探索哈希表已建成!");}用二次探测再散列建立哈希表,代码实现如下:void CreateHash3(HashTable3 *h,int *a,int num)//二次探索表{int i,p=-1,c,pp;for(i=0;i<num;i++){c=0;p=a[i]%HashSize;pp=p;while(h->elem[pp]!=NULL){pp=Collision(p,c);if(pp<0){printf("第%d个记录无法解决冲突\n",i+1);continue;}}h->elem[pp]=&(a[a[i]]);h->count++;printf("第%d个记录冲突次数为%d\n",i+1,c);}printf("\n建表完成!\n此哈希表容量为%d,当前表内存储的记录个数%d.\n",HashSize,h->count);}二次探测再散列法解决冲突int Collision(int p,int &c){int i,q;i=c/2+1;while(i<HashSize) {if(c%2==0){c++;q=(p+i*i)%HashSize; if(q>=0)return q;elsei=c/2+1;}else{q=(p-i*i)%HashSize; c++;if(q>=0)return q; else i=c/2+1;}}return (-1);}用线性再散列法查找,代码实现如下:void SearchHash1(HashTable1 *h,int data){int d;d=data%HashSize;if(h[d].key==data)printf("数字%d的探查次数为:%d\n",h[d].key,h[d].si); else{dod=(d+1)%HashSize;while(h[d].key!=data && d<HashSize);if(d<HashSize)printf("数字%d的探查次数为:%d\n",h[d].key,h[d].si); elseprintf("没有查找到你所输入的数\n");}用二次探测再散列法查找void SearchHash2(HashTable2 * h[],int data,int num) {int d;Node *q;d=data%num;q=h[d]->link;while(q->key!=data && q->next!=NULL)q=q->next;if(q->next!=NULL)printf("数字%d的查找次数为:%d\n",q->key,q->next); elseprintf("没有找到你要查找的那个数\n");}用链地址法查找,代码实现如下:void CreateHashTable2(HashTable2 *ht[],int *a,int num)//哈希表链地址;{int i,d,cnt;Node *s,*q;for(i=0;i<num; i++){ht[i]=(HashTable2 *)malloc(Sizeof(HashTable2));ht[i]->link=NULL;}for(i=0;i<num;i++){cnt=1;s=(Node *)malloc(sizeof(Node));s->key=a[i];s->next=NULL;d=a[i]%num;if(ht[d]->link==NULL) {ht[d]->link=s;s->si=cnt;}else{q=ht[d]->link;while(q->next!=NULL) {q=q->next;cnt++;}cnt++;s->si=cnt;q->next=s;}}}c. 详细设计(1) 程序中结构体的定义typedef struct{int key;int si;}HashTable1;typedef struct node {int key;int si;struct node *next;}Node;typedef struct{Node *link;}HashTable2;typedef struct{int * elem[HashSize];int count;int size;}HashTable3;(2) 主函数模块void main(){int data;HashTable1 hash1[HashSize];HashTable2 * hash2[HashSize];HashTable3 * ha;ha=(HashTable3 *)malloc(sizeof(HashTable3)); for(int i=0;i<HashSize;i++)ha->elem[i]=NULL;ha->count=0;ha->size=HashSize;int a[MaxSize];while(1){printf("\n ┏━━━━━━━━━━━━━━━┓ ");printf("\n ┃欢迎使用本系统┃ ");printf("\n ┏〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓┓");printf("\n ┃★ ★ ★ ★ ★ ★散列法的实验研究★ ★ ★ ★ ★ ★┃");printf("\n ┃ 【1】. 添加数据信息【2】数据的输出┃");printf("\n ┃【3】. 建立哈希表(线性再散列) ┃");printf("\n ┃【4】. 建立哈希表(二次探测再散列) ┃");printf("\n ┃【5】. 建立哈希表(链地址法) ┃");printf("\n ┃【6】. 线性再散列法查找┃");printf("\n ┃【7】. 二次探测再散列法查找┃");printf("\n ┃【8】. 链地址法查找┃");printf("\n ┃【0】. 退出程序┃");printf("\n ┗〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓┛");printf("\n");。

数据结构实验四矩阵和散列表代码实现

数据结构实验四矩阵和散列表代码实现

1、创建稀疏矩阵类,采用行主顺序把稀疏矩阵映射到一维数组中,实现稀疏矩阵的转置和两个稀疏矩阵的加法操作。

#include <iostream>#include <stdio.h>using namespace std;//三元组struct Trituple{int row, col; //非零元素的行号、列号int val; //非零元素的值};//稀疏矩阵类声明class SparseMatrix{public:SparseMatrix(int maxt = 100); //构造函数~SparseMatrix(); //析构函数bool TransposeTo(SparseMatrix &); //转置void add(SparseMatrix &,SparseMatrix &);//加运算void map();//采用行主顺序把稀疏矩阵映射到一维数组中bool Input(); //输入稀疏矩阵void Output();//输出稀疏矩阵Trituple *data; //存储非零元素三元组的数组int rows, cols, terms; //矩阵的行数、列数、非零元素个数int maxterms; //数组data的大小};//构造函数,分配maxt个三元组结点的顺序空间,构造一个空的稀疏矩阵三元组表。

SparseMatrix::SparseMatrix(int maxt){maxterms = maxt;data = new Trituple [maxterms];terms = rows = cols = 0;}//析构函数,将三元组表结构销毁。

SparseMatrix::~SparseMatrix(){if (data != NULL) delete [] data;}//输出稀疏矩阵ostream& operator << (ostream & out, SparseMatrix & M){out << "rows=" << M.rows << endl;out << "cols=" << M.cols << endl;out << "terms=" << M.terms << endl;for (int i = 0; i < M.terms; i++)out << "data[" << M.data[i].row << "," << M.data[i].col << "]=" << M.data[i].val << endl;return out;};//输入稀疏矩阵istream& operator >> (istream & in, SparseMatrix & N){cout << "输入稀疏矩阵的行数、列数以及非零元素个数" << endl;in >> N.rows >> N.cols >>N.terms;if (N.terms > N.maxterms) exit (1);cout << "terms=" << N.terms << endl;for (int i = 0; i < N.terms; i++){cout << "输入非零元素的行号、列号和元素值" << i + 1 << endl;in >> N.data[i].row >>N.data[i].col >> N.data[i].val;}return in;};//转置,将*this的转置矩阵送入Bbool SparseMatrix::TransposeTo(SparseMatrix &B){if(terms > B.maxterms)return false;B.rows = cols;B.cols = rows;B.terms = terms;if (terms > 0) {int p = 0;for (int j = 1; j <= cols; j++)for (int k = 0; k < terms; k++)if (data[k].col == j) {B.data[p].row = j;B.data[p].col = data[k].row;B.data[p].val = data[k].val;p++;}}return true;}void SparseMatrix::add(SparseMatrix &A,SparseMatrix &B){if (A.rows!=B.rows || A.cols!=B.cols)cout<<"矩阵不相容,不能相加!"<<endl;else{rows = A.rows;cols = A.cols;terms = 0;int a,b,e,k;a =b = e = 0;for(k=1;k<=A.rows;k++){while(A.data[a].row == k && B.data[b].row == k) //两结点属于同一行{if(A.data[a].col < B.data[b].col) //A中下标a的结点小于B中下标为b 的结点的列数{data[e].val=A.data[a].val;data[e].row=A.data[a].row;data[e].col=A.data[a].col;e++;a++;}else if(A.data[a].col==B.data[b].col) //两结点属于同一列{int temp = A.data[a].val+B.data[b].val;if(temp == 0) //两结点数值相加等于0{a++;b++;}else //两结点数值相加不等于0{data[e].val = temp;data[e].row = A.data[a].row;data[e].col = A.data[a].col;e++;a++;b++;}}else{ //A中下标a的结点大于B中下标为b的结点的列数data[e].val = B.data[b].val;data[e].row=B.data[b].row;data[e].col=B.data[b].col;e++;b++;}}while(A.data[a].row == k){ //只有A中剩下行数为k的未处理结点data[e].val = A.data[a].val;data[e].row = A.data[a].row;data[e].col = A.data[a].col;e++;a++;}while(B.data[b].row == k){ //只有B中剩下行数为k的未处理结点data[e].val = B.data[b].val;data[e].row =B.data[b].row;data[e].col = B.data[b].col;e++;b++;}}terms=e;cout<<"和矩阵为:"<<endl;Output();}}void SparseMatrix::map(){bool sorted = false;for(int size = terms;!sorted && (size>1); size--){int indexOfMax = 0;sorted = true;for(int i = 1;i<size; i++)if (data[indexOfMax].row<= data[i].row)indexOfMax = i;elsesorted = false;swap(data[indexOfMax],data[size-1]);}for(int size = terms;!sorted && (size>1); size--){int indexOfMax = 0;sorted = true;for(int i = 1;i<size; i++){if (data[indexOfMax].row > data[i].row){if (data[indexOfMax].col <= data[i].col)indexOfMax = i;elsesorted = false;swap(data[indexOfMax],data[size-1]);}}}for (int i = 0;i < terms;i++)cout << data[i].val <<" ";cout << "\n";}bool SparseMatrix::Input(){cout << "输入稀疏矩阵的行数、列数以及非零元素个数" << endl;cin >> rows >> cols >> terms;if (terms > maxterms) {cout << "非零元个数太多!" << endl;return false;}if (terms == 0)return true;cout << "按行序输入" << terms << "个非零元素的三元组" << endl;for (int i = 0; i < terms; i++) {cout << "输入第" << i + 1 << "个非零元素的行号、列号和元素值" << endl;cin >> data[i].row >> data[i].col >> data[i].val;if (data[i].row < 1 || data[i].row > rows || data[i].col < 1 || data[i].col > cols) { cout << "矩阵输入有误!" << endl;return false;}}return true;}//输出稀疏矩阵void SparseMatrix::Output(){cout << "rows=" << rows << endl;cout << "cols=" << cols << endl;cout << "terms=" << terms << endl;for (int i = 0; i < terms; i++)cout << "data[" << data[i].row << "," << data[i].col << "]=" << data[i].val << endl;}int main(){SparseMatrix M,T,C,D;if (M.Input()) {cout << "原始矩阵:" << endl;M.Output();cout << "采用行主顺序把稀疏矩阵映射到一维数组中并输出" << endl;M.map();}cout << "转置矩阵:" << endl;if(M.TransposeTo(T))T.Output();cout<<"输入第二个矩阵"<<endl;if (C.Input()) {cout << "第二矩阵:" << endl;C.Output();}D.add(M,C);cout << "采用行主顺序把稀疏矩阵映射到一维数组中并输出" << endl;D.map();system("pause");return 0;}2、使用散列表设计实现一个字典,假设关键字为整数且D为961,在字典中插入随机产生的500个不同的整数,实现字典的建立和搜索操作。

数据结构实验报告散列查找

数据结构实验报告散列查找

《数据结构》实验报告题目: 散列查找一、实验题目散列查找二、实验目的⑴掌握散列查找的基本思想;⑵掌握闭散列表的构造方法;⑶掌握线性探测处理冲突的方法;⑷验证散列技术的查找性能。

三、实验内容与实现⑴对于给定的一组整数和散列函数,采用线性探测法处理冲突构造散列表;⑵设计查找算法,验证查找性能。

实验实现:#include <stdio.h>#include <stdlib.h>#define HASHSIZE 10 // 长度#define NULLKEY -32768typedef struct{int *elem; // 数据元素存储地址,动态分配数组int count; // 当前数据元素个数}HashTable;int m = 0;int Init(HashTable *H){int i;m = HASHSIZE;H->elem = (int *)malloc(m * sizeof(int)); //分配内存H->count = m;for (i = 0; i<m; i++){H->elem[i] = NULLKEY;}return 1;}int Hash(int k)//除留余数法{return k % m;}void Insert(HashTable *H, int k)//插入数字如果有冲突用开放定址法{int addr = Hash(k);while (H->elem[addr] != NULLKEY){addr = (addr+1) % m;}H->elem[addr] = k;}int Search(HashTable *H, int k)//求哈希地址开放定址法解决冲突{int addr = Hash(k);while (H->elem[addr] != k){addr = (addr+1) % m;if (H->elem[addr] == NULLKEY || addr == Hash(k)) return -1;}return addr;}void Result(HashTable *H)//散列表元素显示{int i;for (i = 0; i<H->count; i++){if(H->elem[i]!=-32768)printf("%d ", H->elem[i]);}printf("\n");}int main(){int i, j, addr,n;HashTable H;int arr[HASHSIZE] = { NULL };Init(&H);printf("请输入数:");for (i = 0; i<10; i++)scanf("%d", &arr[i]);Insert(&H, arr[i]);}printf("输入的数存入哈希表后:");Result(&H);int b;printf("输入需要查找的数:\n");while(scanf("%d",&j)!=EOF){addr = Search(&H, j);if (addr == -1){printf("元素不存在,程序结束\n");break;}elseprintf("%d元素在表中的位置是:%d\n", j,addr+1); }}四、实验心得。

散列函数实验原理

散列函数实验原理

散列函数实验【实验原理】散列函数是一种单向密码,即是一个从明文到密文的不可逆映射,只有加密过程,不可解密;同时散列函数可以将任意长度的输入经过变换以后得到固定长度的输出。

散列函数在完整性认证和数字签名等领域有广泛应用。

散列函数应满足以下要求:(1)算法公开,不需要密钥。

(2)具有数据压缩功能,可将任意长度的输入转换为固定长度的输出。

(3)已知m,容易计算出H(m)。

(4)给定消息散列值H(m),要计算出m在计算上是不可行的。

(5)对任意不同的输入m和n,它们的散列值是不能相同的。

一、MD5算法MD5(Message-Digest Algorithm 5)即信息-摘要算法,是MD4算法的改进;算法的输入为任意长度的消息,分为512比特长的分组,输出为128比特的消息摘要。

处理过程如下:(1)对消息进行填充,使其比特长度为n512+448(n为正整数),填充方式是固定的:第一位为1,其后各位为0。

(2)附加消息长度,使用上一步骤留出的64比特以小端(最低有效字节/位存储于低地址字节/位)方式来表示消息被填充前的长度,若消息长度大于264,则以264为模数取模。

(3)对消息摘要缓冲区初始化,算法使用128比特长的缓冲区来存储中间结果和最终散列值,将缓冲区表示成4个32比特长的寄存器A、B、C、D,每个寄存器以小端方式存储数据,初始值为(十六进制,低位字节在前)A=01234567,B=89ABCDEF,C=FEDCBA98,D=76543210。

(4)以分组为单位对消息进行处理,每一个分组都经过压缩函数HMD5处理;HMD5有4轮处理过程,每轮有16步迭代,4轮处理过程的处理结构一样,所用逻辑函数不同,分别表示为F、G、H、I;每轮的输入为当前处理的消息分组和缓冲区当前的值,输出仍存放在缓冲区中。

最后第四轮的输出与第一轮输入的缓冲区值V相加,相加时将V看做4个32比特的字,每个字与第四轮输出的对应的字按模232相加,相加结果为HMD5的输出。

散列——实验及提升训练

散列——实验及提升训练

散列——实验及提升训练散列(Hashing)是一种常见的数据结构,它将任意长度的输入(又称为预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值(Hash值)。

散列算法是一种单向函数,即无法通过散列值反推出原始输入。

散列算法广泛应用于密码学、数据完整性校验、数据压缩等领域。

散列算法的应用非常广泛,但是在实际应用中,我们需要考虑散列算法的效率和安全性。

在本文中,我们将介绍散列算法的实验和提升训练。

一、散列算法的实验散列算法的实验可以帮助我们了解散列算法的性能和特点。

下面我们将介绍两个散列算法的实验。

1. MD5算法实验MD5算法是一种广泛使用的散列算法,它可以将任意长度的输入转换成128位的输出。

我们可以使用Python中的hashlib库来计算MD5散列值。

下面是一个简单的MD5算法实验:```pythonimport hashlib# 计算字符串的MD5散列值def md5(string):m = hashlib.md5()m.update(string.encode('utf-8'))return m.hexdigest()# 测试print(md5('hello world'))```输出结果为:```5eb63bbbe01eeed093cb22bb8f5acdc3```2. SHA256算法实验SHA256算法是一种更安全的散列算法,它可以将任意长度的输入转换成256位的输出。

我们同样可以使用Python中的hashlib库来计算SHA256散列值。

下面是一个简单的SHA256算法实验:```pythonimport hashlib# 计算字符串的SHA256散列值def sha256(string):m = hashlib.sha256()m.update(string.encode('utf-8'))return m.hexdigest()# 测试print(sha256('hello world'))```输出结果为:```b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee908 8f7ace2efcde9```二、散列算法的提升训练散列算法的提升训练可以帮助我们提高散列算法的效率和安全性。

作业散列法实验研究

作业散列法实验研究

课程设计题目1. 具体要求散列法中,散列函数构造方法多种多样,同时对于同一散列函数解决冲突的方法也可以不同。

两者是影响查询算法性能的关键因素。

对于几种典型的散列函数构造方法,做实验观察,不同的解决冲突方法对查询性能的影响。

2.开发环境VC++ 6.03. 算法设计思想散列又称哈希或杂凑。

散列法(Hashing)在表项的存储位置与它的关键码之间建立一个确定的对应函数关系Hash(),以使每个关键码与结构中的唯一存储位置相对应,该关系可用下式表示:Address=Hash(Record.key)相应的表称为哈希表,这种方法的基本思想是:首先在元素的关键字k和元素的存储位置p之间建立一个对应关系H,使得p=H(k),H称为哈希函数。

创建哈希表时,把关键字为k的元素直接存入地址为H(k)的单元;以后当查找关键字为k 的元素时,再利用哈希函数计算出该元素的存储位置p=H(k),从而达到按关键字直接存取元素的目的。

哈希函数是一个映象,哈希函数的设定灵活,只要使得任何关键字所得的哈希函数值都落在表长范围之内即可。

当关键字集合很大时,关键字值不同的元素可能会映象到哈希表的同一地址上,即 k1≠k2,但H(k1)=H(k2),这种现象称为冲突,此时称k1和k2为同义词。

实际中,冲突是不可避免的,只能通过改进哈希函数的性能来减少冲突。

综上所述,哈希法主要包括以下两方面的内容:(1)如何构造哈希函数;(2)如何处理冲突。

4. 数据结构与算法描述一、散列函数通常,构造散列函数应该注意的几个问题包括:首先,散列函数的定义域必须包括需要存储的全部关键码,而如果散列表允许有m个地址,其值域必须在1~m-1之间;其次,散列函数计算出来的地址应能均匀分布在整个地址空间中;再次,散列函数应当是尽量简单的。

(1)直接定址法直接定址法蓝颜元素关键码的某个线性函数值作为该元素的散列地址(散列地址,即元素最终在字典中的存储位置)。

如下面的函数式:Hash(key)=a×key+b式中,a,b为常数。

散列表查找算法 python3

散列表查找算法 python3

散列表查找算法 python3散列表(Hash Table)是一种通过计算某个值(关键字)的散列函数,将这个值映射到一个表中的位置来进行快速查找的数据结构。

在Python中,我们可以使用字典(dictionary)来实现散列表。

下面是一个用Python实现散列表查找算法的例子:```pythondef hash_function(key):return key % 10 # 使用取余操作符作为散列函数def insert(hash_table, key, value):index = hash_function(key)hash_table[index] = valuedef search(hash_table, key):index = hash_function(key)if index in hash_table: # 判断散列表中是否存在该索引return hash_table[index]else:return None# 示例hash_table = {} # 创建一个空散列表# 在散列表中插入键值对insert(hash_table, 23, 'Alice')insert(hash_table, 14, 'Bob')insert(hash_table, 7, 'Charlie')# 查找键值对print(search(hash_table, 23)) # 输出:Aliceprint(search(hash_table, 14)) # 输出:Bobprint(search(hash_table, 7)) # 输出:Charlieprint(search(hash_table, 10)) # 输出:None(散列表中不存在该键)```在上面的例子中,我们使用简单的取余操作符作为散列函数,并且假设散列表的大小为10。

其中,`hash_function()`函数用于计算键的散列值,`insert()`函数用于将键值对插入散列表中,`search()`函数用于搜索相应的键。

散列的平方探测法实现

散列的平方探测法实现

散列的平⽅探测法实现public class QuadraticProbingHashTable<T> {private static final int DEFAULT_TABLE_SIZE=10;private HashEntry<T>[] array;private int currentsize;public QuadraticProbingHashTable(){this(DEFAULT_TABLE_SIZE);}public QuadraticProbingHashTable(int size){allocateArray(size);makeEmpty();}public void makeEmpty(){currentsize=0;for(int i=0;i<array.length;i++){array[i]=null;}}public boolean contain(T val){int address=findPos(val);return isActive(address);}public void remove(T val){int address=findPos(val);if(isActive(address)){array[address].active=false;}currentsize--;}public void insert(T val){int address=findPos(val);if((isActive(address)))return;array[address]=new HashEntry<T>(val, true);if(++currentsize>array.length/2){rehash();}}private static class HashEntry<T>{public T val;public boolean active;public HashEntry(T val){this(val,true);}public HashEntry(T val,boolean active){this.val=val;this.active=active;}}private void allocateArray(int arraySize){array=new HashEntry[nextPrime(arraySize)];}private boolean isActive(int currentPos){return array[currentPos]!=null&&array[currentPos].active;}private int findPos(T val){int num=1;int currentnum=myhash(val);while(array[currentnum]!=null&&!array[currentnum].val.equals(val)){currentnum+=num;num+=2;if(currentnum>array.length){currentnum-=array.length;}}return currentnum;}private void rehash(){}private int myhash(T val){int t=val.hashCode()%array.length;if(t<0){t+=array.length;}return t;}private static int nextPrime(int n){if(isPrime(n)){return n;}boolean b=false;boolean b=false;while(!b){n+=1;b=isPrime(n);}return n;}private static boolean isPrime(int n){ if(n==1&&n==3){return true;}if(n==2&&n==4){return false;}for(int i=5;i<= Math.sqrt( n ); i++){if(n%i==0){return false;}}return true;}}。

散列表的查找代码实现

散列表的查找代码实现

散列表的查找代码实现1//定义⼀个散列表的结构2#define HASHSIZE 12 //初始⼤⼩3#define NULLKEY -32768//默认值,散列表中不可能出现的值4 typedef struct5 {6int *elem;//数据元素的基址,均匀分配数组7int ecount;//当前数据元素的个数8 }HashTable;9//初始化散列表10int InitHashTable(HashTable *H)11 {12 H->ecount=HASHSIZE;13 H->elem=(int *)malloc(HASHSIZE*sizeof(int));14if(!H->elem)//⽣成空间失败15 {16return -1;17 }18for(i=0;i<HASHSIZE;i++)19 {20 H->elem[i]=NULLKEY;21 }22return0;23 }24//使⽤除留余数法25int Hash(int key)26 {27return key % HASHSIZE;28 }29//插⼊关键字到数列表30void InsertHash(HashTable *H,int key)//传⼊散列表,待插⼊的关键字31 {32int addr;//地址33 addr=Hash(key);//余数作为地址(偏移地址)34while(H->elem[addr]!=NULLKEY){//如果不为空,则冲突出现,存放默认值35 addr=(addr+1)%HASHSIZE;//开放定址法的线性探测36 }37 H->elem[addr]=key;38 }39//数列表查找关键字40int SearchHash(HashTable H,int key,int *addr)//待查找的key,addr代表待查找的key存放的地址41 {42 ×addr=Hash(key);//查找效率直接为143while(H.elem[*addr]!=key)44 {45 *addr=(×addr+1)%HASHSIZE;46if(H.elem[*addr]==NULLKEY||×addr==Hash(key))//H.elem[*addr]==NULLKEY代表查找到最后⼀个元素,×addr==Hash(key)//代表查找到第⼀个元素,即查找元素不存在47 {48return -1;49 }50 }51return0;52 }。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

散列法实验研究源代码#include "iostream.h"#include "string.h"#include "fstream.h"#define NULL 0unsigned 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;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;}。

相关文档
最新文档