算法导论实验报告.docx
- 文档编号:6816910
- 上传时间:2023-01-10
- 格式:DOCX
- 页数:15
- 大小:156.13KB
算法导论实验报告.docx
《算法导论实验报告.docx》由会员分享,可在线阅读,更多相关《算法导论实验报告.docx(15页珍藏版)》请在冰豆网上搜索。
算法导论实验报告
课程实验报告
课程名称《算法导论》
实验名称贪心算法基数排序散列表
参加人员刘英200910010224
唐思咪200910010215
王永久200910010220
指导教师阳卫锋
2011年11月17日
实验一散列表程序设计
一.实验目的:
1.通过本次实验进一步理解散列表的概念;
2.掌握散列表的创建;
3.掌握散列表中数据的存储与查找。
二.实验内容:
应用相关知识设计散列表实现电话号码查找系统。
三.实验要求:
1)设每个记录有下列数据项:
电话号码、用户名、地址;
2)从键盘输入各记录,分别以电话号码和用户名为关键字建立散列表;
3)采用一定的方法解决冲突;
4)查找并显示给定电话号码的记录;
5)查找并显示给定用户名的记录。
四.散列表的基本概念:
1.若散列表结构中存在关键字和K相等的记录,则必定在f(K)的存储位置上。
由此,不需比较便可直接取得所查记录。
称这个对应关系f为散列函数(Hashfunction),按这个思想建立的表为散列表。
2.对不同的关键字可能得到同一散列地址,即key1≠key2,而f(key1)=f(key2),这种现象称冲突。
具有相同函数值的关键字,对该散列函数来说称同义词。
综上所述,根据散列函数和处理冲突的方法将一组关键字映射到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“象”作为记录在表中的存储位置,这种表便称为散列表,这一过程称为散列造表或散列,所得的存储位置称为散列地址。
3.若对于关键字集合中的任何一个关键字,经散列函数映射到地址集合中任何一个地址的概率是相等的,则称此类散列函数为均匀散列函数,这就是使关键字经过散列函数得到一个“随机的地址”,从而减少冲突。
五.源程序:
#include
#include
#include
#defineMAXSIZE20//电话薄记录数量
#defineMAX_SIZE20//人名的最大长度
#defineHASHSIZE53//定义表长
#defineLENsizeof(HashTable)
typedefintSET;
typedefcharAd[MAX_SIZE];
typedefstruct//记录
{
Adname;
Adtel;
Adadd;
}Record;
typedefstruct//哈希表
{
Record*elem[HASHSIZE];//数据元素存储基址
intcount;//当前数据元素个数
intsize;//当前容量
}HashTable;
SETNUM_BER;//记录的个数
voidgetin(Record*a)//键盘输入各人的信息
{
printf("要添加通信人信息的个数:
\n");
scanf("%d",&NUM_BER);
inti;
for(i=0;i printf("请输入第%d个记录的用户名: \n",i+1); scanf("%s",a[i].name); printf("请输入第%d个记录的电话号码: \n",i+1); scanf("%s",a[i].tel); printf("请输入第%d个记录的地址: \n",i+1); scanf("%s",a[i].add);//gets(str2);? ? ? ? ? ? } } voidShowInformation(Record*a)//显示输入的用户信息 { inti; for(i=0;i printf("\n第%d个用户信息: \n姓名: %s\n电话号码: %s\n联系地址: %s\n",i+1,a[i].name,a[i].tel,a[i].add); } intHash1(Adstr)//哈希函数 { longn; intm; m=n%HASHSIZE;//用除留余数法构造哈希函数 returnm;//并返回模值 } intHash2(Adstr)//哈希函数 { longn; intm; n=atoi(str);//把字符串转换成整型数. m=n%HASHSIZE;//用除留余数法构造哈希函数 returnm;//并返回模值 } SETcollision(intp,int&c)//冲突处理函数,采用二次探测再散列法解决冲突 { inti,q; i=c/2+1; while(i if(c%2==0){ c++; q=(p+i*i)%HASHSIZE; if(q>=0)returnq; elsei=c/2+1; } else{ q=(p-i*i)%HASHSIZE; c++; if(q>=0)returnq; elsei=c/2+1; } } return-1; } voidCreateHash1(HashTable*H,Record*a)//建表,以人的姓名为关键字,建立相应的散列表 { //若哈希地址冲突,进行冲突处理 inti,p=-1,c,pp; for(i=0;i c=0; p=Hash1(a[i].name); pp=p; while(H->elem[pp]! =NULL){ pp=collision(p,c); if(pp<0){ printf("第%d记录无法解决冲突",i+1);//需要显示冲突次数时输出 continue; }//无法解决冲突,跳入下一循环 } H->elem[pp]=&(a[i]);//求得哈希地址,将信息存入 H->count++; } printf("\n建表完成! \n此哈希表容量为%d,当前表内存储的记录个数为%d.\n",HASHSIZE,H->count); } voidCreateHash2(HashTable*H,Record*a)//建表,以电话号码为关键字,建立相应的散列表 { //若哈希地址冲突,进行冲突处理 inti,p=-1,c,pp; for(i=0;i c=0; p=Hash2(a[i].tel); pp=p; while(H->elem[pp]! =NULL){ pp=collision(p,c); if(pp<0){ printf("第%d记录无法解决冲突",i+1);//需要显示冲突次数时输出 continue; }//无法解决冲突,跳入下一循环 } H->elem[pp]=&(a[i]);//求得哈希地址,将信息存入 H->count++; printf("第%d个记录冲突次数为%d。 \n",i+1,c);//需要显示冲突次数时输出 } printf("\n建表完成! \n此哈希表容量为%d,当前表内存储的记录个数为%d.\n",HASHSIZE,H->count); } SETeq(Adx,Ady)//关键字比较,相等返回SUCCESS;否则返回UNSUCCESS { if(strcmp(x,y)==0) return1; elsereturn-1; } voidSearchHash2(HashTable*H,int&c)//在通讯录里查找电话号码关键字,若查找成功,显示信息 { //c用来记录冲突次数,查找成功时显示冲突次数 Adtele; printf("\n请输入要查找记录的电话号码: \n"); scanf("%s",tele); intp,pp; p=Hash2(tele); pp=p; while((H->elem[pp]! =NULL)&&(eq(tele,H->elem[pp]->tel)==-1)) pp=collision(p,c); if(H->elem[pp]! =NULL&&eq(tele,H->elem[pp]->tel)==1){ printf("\n查找成功! \n查找过程冲突次数为%d.以下是您需要要查找的信息: \n\n",c); printf("姓名: %s\n电话号码: %s\n联系地址: %s\n",H->elem[pp]->name,H->elem[pp]->tel,H->elem[pp]->add); } elseprintf("\n此人不存在,查找不成功! \n"); } intmain(intargc,char*argv[]){ intc,flag=1; HashTable*H; H=(HashTable*)malloc(LEN); for(inti=0;i H->elem[i]=NULL; H->size=HASHSIZE; H->count=0; Recorda[MAXSIZE]; while (1) { printf("哈希表的设计与实现\n"); printf("【1】.添加用户信息\n"); printf("【2】.读取所有用户信息\n"); printf("【3】.以姓名建立哈希表(再哈希法解决冲突)\n"); printf("【4】.以电话号码建立哈希表(再哈希法解决冲突)\n"); printf("【5】.以电话号码查询\n"); printf("【6】.退出程序\n"); printf("请输入一个任务选项>>>"); printf("\n"); intnum; scanf("%d",&num); switch(num){ case1: getin(a); break; case2: ShowInformation(a); break; case3: CreateHash1(H,a);/*以姓名建立哈希表*/ break; case4: CreateHash2(H,a);/*以电话号码建立哈希表*/ break; case5 c=0; SearchHash2(H,c); break; case6: return0; break; default: printf("你输错了,请重新输入! "); printf("\n"); break; } } return0; } 六.界面设计及运行结果: 1.输入信息: 2.查找用户: 3.以姓名建立哈希表: 4.结果: 七.结果分析: 散列表是普遍数组概念的推广,因为它可以对数组进行直接寻址,故可以在O (1)时间内访问数组的任意元素。 在最坏情况下,在散列表中,查找一个元素的时间与在链表中查找一个元素的时间相同,但在实践中,散列技术的效率是很高的,在一些合理的假设下,在散列表中查找一个元素的期望时间为O (1) 实验二基数排序 一.实验目的: 掌握基数排序算法思想,学会利用基数排序进行排序。 二.实验内容: 对数组利用基数排序进行排序。 三.实验要求: 1)写出算法的伪代码和JAVA程序代码 2)记录每一步数组的中元素的变化 四.堆排序的原理与技术 1.基数排序是一种用在老式穿卡机上的算法。 一张卡片有80列,每一列可以在12个位置上穿孔。 排序器可以被机械地程序化,以便对一叠卡片中的每一列进行检查,再根据穿孔的位置将他们分别放进12个盒子里。 这样,操作员就可以逐个地将他们收集起来,其中第一个位置穿孔的放最上面,第二个位置穿孔的其次; 五.基数排序源程序 packagejisuanpaixu; //计数排序算法 publicclassJiShuPaixu{ privatestaticint[]countingSort(int[]A,intd){ int[]B=newint[A.length]; int[]C=newint[10]; for(inti=0;i<10;i++) C[i]=0; for(inti=0;i C[A[i]%((int)Math.pow(10,d+1))/((int)Math.pow(10,d))]+=1; for(inti=1;i<10;i++) C[i]+=C[i-1]; for(inti=A.length-1;i>=0;i--){ B[C[A[i]%((int)Math.pow(10,d+1))/((int)Math.pow(10,d))]-1]=A[i]; C[A[i]%((int)Math.pow(10,d+1))/((int)Math.pow(10,d))]-=1; } returnB; } publicstaticint[]radixSort(int[]A,intd){ int[]B=newint[A.length]; for(inti=0;i B[i]=A[i]; for(inti=0;i B=countingSort(B,i); } returnB; } /** *@paramargs */ publicstaticvoidmain(String[]args){ int[]A={12,25,13,30,32,43,20,3};//输入的待排序数; System.out.println("待排序列"); for(inti=0;i System.out.print(A[i]+""); } System.out.println(); System.out.println("结果"); int[]B=radixSort(A,2); for(intb: B){ System.out.print(b+""); } System.out.println(); //TODOAuto-generatedmethodstub } } 五.界面设计及运行结果: 注明: 由于本程序是用JAVA语言编写,故没什么界面可言,只能输出结果: 待排序列 122513303243203 结果 312132025303243 六: 结果分析: 把待排序的记录存放在数组intA[1‥n]中,先从最低位开始排序,然后往高位运行;位数不够的,系统自动定义为0;例如3,当对十位排序时,相当于03;结果保存在另一个数组中;当我们需要进行三位数排序的时候,可以把int[]B=radixSort(A,2);中的2变为3就可以了; 对于基数排序,其算法是稳定的,这方法还能扩展到排序时间,日期等;算法所用的时间O(d(n+k));其中d为位数; 实验三贪心算法关于背包问题的程序设计 一.实验目的: 掌握并实现贪心算法。 二.实验内容: 对于输入一系列的物品的价值和重量,用规定的包,带走最大价值的东西; 三.实验要求: 利用贪心思想写出算法的伪代码和C程序代码 四.贪心算法的基本思想及步骤 基本思想: 贪心算法是通过一系列的选择来给出某一个问题的最优解。 对算法中的每一个决策点,做一个当时最佳的选择。 六个步骤: Step1: 决定问题的最优子结构; Step2: 设计出一个递归解; Step3: 证明出任何阶段,最优选择之一总是贪心的选择; Step4: 证明通过做贪心选择,所有的子问题都为空; Step5: 设计出一个实现贪心策略的递归算法; Step6: 将递归算法转换成迭代方法; 五.贪心算法源程序 #include #include #include"conio.h" usingnamespacestd; structgood//表示物品的结构体 { doublep;//价值 doublew;//重量 doubler;//价值与重量的比 }a[20]; doubles,value,m; inti,num; boolbigger(gooda,goodb) { returna.r>b.r; } intmain() { printf("\t\t---------贪心算法解决背包问题----------\n"); printf("请输入您要输入的货物的个数: "); scanf("%d",&num);//物品个数 printf("请输入货物的重量与价值格式为(wp)每输入一组数据回车: \n"); intk; for(i=0;i { scanf("%lf%lf",&a[i].w,&a[i].p); a[i].r=a[i].p/a[i].w; } sort(a,a+num,bigger);//调用sort排序函数 printf("请输入包的容量: "); scanf("%lf",&m);//读入包的容量m s=0;//包内现存货品的重量 value=0;//包内现存货品总价值 for(i=0;i { value+=a[i].p; s+=a[i].w; k=i; } value+=(m-s)*a[k+1].r; printf("背包的最大总价值为%.2lf.\n",value);//输出结果 getch(); return0; } 五.界面设计及运行结果: 六.结果分析: 为得到结果,算法先对每件物品计算其每磅的价值。 按照一种贪心策略,窃贼开始是对每个具有最大每磅价值的物品多拿些。 如果他拿完了该物品还可以取其他的物品,他就再次取具有次大的每磅价值的物品,一直继续下去,直到不能取为止,这样按每磅价值来对所有物品进行排序,贪心算法可以在O(nlgn)时间运行;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 导论 实验 报告