当前位置:文档之家› 算法分析实验5堆排序

算法分析实验5堆排序

算法分析实验5堆排序
算法分析实验5堆排序

实验五堆排序(四号黑体)

【一】实验目的(小四黑体)

1.实现堆的创建和堆排序;

2.理解变治法的思想。

【二】实验内容(小四黑体)

1.给定一个序列,构造大根堆并实现堆排序;

2.分析堆排序算法的时间复杂度,并与合并排序、快速排序比较。

【三】实验步骤(代码、结果)(小四黑体)

程序代码

#include

/*注意:这个函数仅仅会在调整被交换的位置为大根堆。未交换的分支不会处理,所以不能将一个非大根堆二叉树的根结点传递过来让这个函数将其处理为大根堆*/

void heap_ajust(int *a, int i, int size) /*a为堆存储数组,size为堆的大小*/

{

int lchild = 2*i; //i的左孩子节点序号

int rchild = 2*i +1; //i的右孩子节点序号

int max = i; /*存放三个顶点中最大的数的下标*/

int temp;

if(i <= size/2) //假设i是叶节点就不用进行调整

{

if(lchild<=size && a[lchild]>a[max])

{

max = lchild;

}

if(rchild<=size && a[rchild]>a[max])

{

max = rchild;

}

if(max != i)

{

temp = a[i]; /*交换a[i]和a[max]的值*/

a[i] = a[max];

a[max] = temp;

heap_ajust(a, max, size); /*被交换的位置曾经是大根堆,如今可能不是大根堆

所以须要又一次调整使其成为大根堆结构*/

}

}

}

void build_bheap(int *a, int size) /*建立大根堆*/

{

int i;

for(i=size/2; i >= 1; i--) /*非叶节点最大序号值为size/2*/

{

heap_ajust(a, i, size); /*每一个非叶子结点都须要调用这个函数*/ }

}

void heap_sort(int *a, int size) /*堆排序*/

{

int i;

int temp;

build_bheap(a, size);

for(i=size; i >= 1; i--)

{

temp = a[1];

a[1] = a[i];

a[i] = temp; /*交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面*/

heap_ajust(a, 1, i-1); /*又一次调整堆顶节点成为大顶堆,仅仅有被交换的分支才有可能不是大根堆*/

}

}

int main()

{

printf("Z09315221谭召\n");

int a[7]={0,7,6,1,2,4,8};

int i;

for(i=1;i <= 6; i++)

printf("%d ", a[i]);

printf("\n");

heap_sort(a, 6);

for(i=1;i <= 6; i++)

printf("%d ", a[i]);

printf("\n");

return 0;

}

【四】实验结果分析(小四黑体)

在堆排序中,建堆的时间复杂度是。建堆的过程需要重新排列n次,所以整个算法的时间复杂度是。而合并排序的时间复杂度是,快速排序平均的时间复杂度,并且其中的常数因子较小,并且快速排序时原地排序。所以快速排序算法比较常用。

时间复杂度:

堆排序归并排序快速排序

最坏时间O(nlogn) O(nlogn) O(n^2)

最好时间O(nlogn) O(nlogn) O(nlogn)

平均时间O(nlogn) O(nlogn) O(nlogn)

堆 排 序 算 法

堆排序——C#实现 一算法描述 堆排序(Heap Sort)是利用一种被称作二叉堆的数据结构进行排序的排序算法。 二叉堆在内部维护一个数组,可被看成一棵近似的完全二叉树,树上每个节点对应数组中的一个元素。除最底层外,该树是满的。 二叉堆中,有两个与所维护数组相关的属性。Length表示数组的元素个数,而HeapSize则表示二叉堆中所维护的数组中的元素的个数(并不是数组中的所有元素都一定是二叉堆的有效元素)。因此,根据上述定义有: 0 = HeapSize = Length。 二叉堆可分为最大堆和最小堆两种类型。在最大堆中,二叉树上所有的节点都不大于其父节点,即 A[Parent(i)] = A[i]。最小堆正好相反:A[Parent(i)] = A[i]。 为维护一个二叉堆是最大(小)堆,我们调用一个叫做MaxHeapify (MinHeapify)的过程。以MaxHeapify,在调用MaxHeapify时,先假定根节点为Left(i)和Right(i)的二叉树都是最大堆,如果A[i]小于其子节点中元素,则交换A[i]和其子节点中的较大的元素。但这样一来,以被交换的子节点为根元素的二叉堆有可能又不满足最大堆性质,此时则递归调用MaxHeapify方法,直到所有的子级二叉堆都满足最大堆性质。如下图所示: 因为在调用MaxHeapify(MinHeapify)方法使根节点为A[i]的

二叉堆满足最大(小)堆性质时我们有其左右子堆均已满足最大(小)堆性质这个假设,所以如果我们在将一个待排序的数组构造成最大(小)堆时,需要自底向上地调用 MaxHeapify(MinHeapify)方法。 在利用最大堆进行排序时,我们先将待排序数组构造成一个最大堆,此时A[0](根节点)则为数组中的最大元素,将A[0]与A[n - 1]交换,则把A[0]放到了最终正确的排序位置。然后通过将HeapSize 减去1,将(交换后的)最后一个元素从堆中去掉。然后通过MaxHeapify方法将余下的堆改造成最大堆,然后重复以上的交换。重复这一动作,直到堆中元素只有2个。则最终得到的数组为按照升序排列的数组。 二算法实现 1 注意到在C#中数组的起始下标为0,因此,计算一个给定下标的节点的父节点和左右子节点时应该特别小心。 private static int Parrent(int i) return (i - 1) - 2; private static int Left(int i) return 2 * i + 1; private static int Right(int i) return 2 * i + 2; 2 算法的核心部分是MaxHeapify(MinHeapify)方法,根据算法描述中的说明,一下代码分别实现了对整数数组的最大堆化和最小堆化方法,以及一个泛型版本。

算法设计与分析实验报告贪心算法

算法设计与分析实验报告 贪心算法 班级:2013156 学号:201315614 姓名:张春阳哈夫曼编码 代码 #include float small1,small2; int flag1,flag2,count; typedefstructHuffmanTree { float weight; intlchild,rchild,parent; }huffman; huffmanhuffmantree[100]; void CreatHuffmanTree(intn,int m) { inti; void select(); printf("请输入%d个节点的权值:",n); for(i=0;i

printf("\n"); for(i=0;i

算法分析与设计实验指导书

《算法分析与设计》实验指导书本书是为配合《算法分析与设计实验教学大纲》而编写的上机指导,其目的是使学生消化理论知识,加深对讲授容的理解,尤其是一些算法的实现及其应用,培养学生独立编程和调试程序的能力,使学生对算法的分析与设计有更深刻的认识。 上机实验一般应包括以下几个步骤: (1)、准备好上机所需的程序。手编程序应书写整齐,并经人工检查无误后才能上机。(2)、上机输入和调试自己所编的程序。一人一组,独立上机调试,上机时出现的问题,最好独立解决。 (3)、上机结束后,整理出实验报告。 实验报告应包括: 1)问题分析 2)算法描述 3)运行结果、 4)算法性能分析。 实验一 实验名称:贪心算法应用及设计 实验学时:6学时 实验类型:验证 实验目的: 1.理解贪心算法的基本思想 2.掌握利用贪心算法求解问题的求解步骤 实验容 1.活动选择问题(2学时) 问题描述: 设有11个会议等待安排,用贪心法找出满足目标要求的会议集合,这些会议按结束时间的非减序排列如下表。 实验实现提示: 1)数据结构设计: 将会议开始时间存储在数组B中,结束时间存储在数组E中,数组下标为会议的代码。结果存储在数组A中,其元素A[i]==true,表示会议i被选中。 2)算法: void GreedySelect(int n, struct time B[], struct time E[], bool A[]) { int i,j;

A[1]=true; j=1; i=2; while( i<=n) if (B[i]>=E[j]) { A[i]=true; j=i;} else A[i]=false; } 思考题:证明所得的解是最优解? 2.单源点最短路径问题。(2学时) 问题描述 如图所示的有向带权图中,求源点0到其余顶点的最短路径及最短路径长度。并对算法进行性能分析。 实现提示 1)数据结构设计: 将图存储在邻接矩阵C中,结点个数为n,源点编号为u, 源点u到其余顶点的最短路径长度存储在dist[],最短路径存储在p[]。 2) 算法 void Dijkstra(int C[n][n], int n,int u,float dist[],int p[]) { bool s[n]; for( int i=1; i<=n; i++) { dist[i]=C[u][i]; s[i]=false; if (dist[i]=∞) p[i]=-1; else p[i]=u; } p[u]=-1; s[u]=true; for( i=1; i<=n; i++) { int temp= ∞; int t=u; for( int j=1;j<=n;j++)

算法分析——实验一

算法分析实验报告 实验一分治策略排序 实验目的 1)以排序问题为例,掌握分治法的基本设计策略; 2)熟练掌握合并排序算法的实现; 3)熟练掌握快速排序算法的实现; 4) 理解常见的算法经验分析方法。 实验环境 计算机、C语言程序设计环境、VC++6.0 实验步骤 算法的基本描述: 1、合并排序的基本思想描述:首先将序列分为两部分,分到每组只有两个元 素,然后对每一部分进行循环递归地合并排序,然后逐个将结果进行合并。 2、快速排序的基本思想描述:将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,最后达到排序效果。 要求:编写一个函数data-generate,生成2000个在区间[1,10000]上的随机整数,并将这些数输出到外部文件data.txt中。这些数作为本算法实验的输入数据。 程序流程图:

合并排序原理图 快速排序流程图1.生成2000个随机整数的程序:#include #include #include int main()

{ FILE *fpt; fpt = fopen("D://data.txt","w"); srand(time(0)); for(int i=0;i<2000;i++) fprintf(fpt,"%3d\t",rand()%10000+1); return 0; fclose(fpt); } 并生成data.txt文件。 2.读取data.txt文件,并排序。实现合并排序算法输入:待排数据文件data.txt; 输出:有序数据文件resultsMS.txt 合并排序算法: #include #include #include void mergesort(int a[],int n); void merge(int a[],int b[],int i,int c[],int j);

算法分析与设计实验报告

算法设计与分析 学院:计算机科学与技术 学号:129074106 姓名:张淼淼 2014 11 14

1、 当问题规模100 N 时,快速排序和插入排序各需多少时间?写清机器配置,列出五种 快速排序所需时间(ms) 插入排序所需时间(ms ) 两者相差多少 N=100 0.00600 0.019000 -0.013000 N=1000 0.074000 0.724000 -0.650000 N=10000 0.032000 64.657000 -64.625000 N=100000 13.300000 50.900000 -37.600000 N=1000000 53.500000 117.700000 -64.200000 Window 7 32位 Cpu :Inter(R) Core(TM) i3-2120 cpu@3.30GHz AMD Radeon HD 6450 Graphics

程序: #include #include #include #include int a[1000000];

int b[1000000]; void QuickSort(int low ,int high) { long i,j; int x; i=low; j=high; x=a[i]; while(i=x&&i(j+1)) QuickSort(j+1,high); } void BinaryInsertSort(int length) { int low,high,mid; int i,j,m;//m为保存待插入的元素 for(i=1;i=b[mid]) low=mid+1; else high=mid-1; } for(j=i-1;j>=high+1;j--)//high为插入位置 b[j+1]=b[j];//后移元素,留出插入的空位b[high+1]=m;//将元素插入正确的位置 }

内部堆排序算法的实现课程设计说明书

数据结构课程设计设计说明书 内部堆排序算法的实现 学生姓名金少伟 学号1121024029 班级信管1101 成绩 指导教师曹阳 数学与计算机科学学院 2013年3月15日

课程设计任务书 2012—2013学年第二学期 课程设计名称:数据结构课程设计 课程设计题目:内部堆排序算法的实现 完成期限:自2013年3 月4日至2013年3 月15 日共 2 周 设计内容: 堆排序(heap sort)是直接选择排序法的改进,排序时,需要一个记录大小的辅助空间。n个关键字序列K1,K2,…,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质):ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤ n) 若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。(即如果按照线性存储该树,可得到一个不下降序列或不上升序列)。 本课程设计中主要完成以下内容: 1.设计堆排序算法并实现该算法。 2.对堆排序的时间复杂度及空间复杂度进行计算与探讨。 3.寻找改进堆排序的方法。 基本要求如下: 1.程序设计界面友好; 2.设计思想阐述清晰; 3.算法流程图正确; 4.软件测试方案合理、有效。指导教师:曹阳教研室负责人:申静 课程设计评阅

摘要 堆排序是直接选择排序法的改进。本课设以VC++6.0作为开发环境,C语言作为编程语言,编程实现了堆排序算法。程序运行正确,操作简单,易于为用户接受。 关键词:堆排序;C语言;时间复杂度

算法分析_实验报告3

兰州交通大学 《算法设计与分析》 实验报告3 题目03-动态规划 专业计算机科学与技术 班级计算机科学与技术2016-02班学号201610333 姓名石博洋

第3章动态规划 1. 实验题目与环境 1.1实验题目及要求 (1) 用代码实现矩阵连乘问题。 给定n个矩阵{A1,A2,…,A n},其中A i与A i+1是可乘的,i=1,2,…,n-1。考察这n 个矩阵的连乘积A1A2…A n。由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序,这种计算次序可以用加括号的方式来确定。若一个矩阵连乘积的计算次序完全确定,则可以依此次序反复调用2个矩阵相乘的标准算法(有改进的方法,这里不考虑)计算出矩阵连乘积。 确定一个计算顺序,使得需要的乘的次数最少。 (2) 用代码实现最长公共子序列问题。 一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序列X= < x1, x2,…, xm>,则另一序列Z= < z1, z2,…, zk>是X的子序列是指存在一个严格递增的下标序列< i1, i2,…, ik>,使得对于所有j=1,2,…,k有Xij=Zj 。例如,序列Z=是序列X=的子序列,相应的递增下标序列为<2,3,5,7>。给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。例如,若X= < A, B, C, B, D, A, B>和Y= < B, D, C, A, B, A>,则序列是X和Y的一个公共子序列,序列也是X和Y的一个公共子序列。而且,后者是X和Y的一个最长公共子序列,因为X和Y没有长度大于4的公共子序列。 (3) 0-1背包问题。 现有n种物品,对1<=i<=n,已知第i种物品的重量为正整数W i,价值为正整数V i,背包能承受的最大载重量为正整数W,现要求找出这n种物品的一个子集,使得子集中物品的总重量不超过W且总价值尽量大。(注意:这里对每种物品或者全取或者一点都不取,不允许只取一部分) 使用动态规划使得装入背包的物品价值之和最大。 1.2实验环境: CPU:Intel(R) Core(TM) i3-2120 3.3GHZ 内存:12GB 操作系统:Windows 7.1 X64 编译环境:Mircosoft Visual C++ 6 2. 问题分析 (1) 分析。

计算机算法设计与分析

算法设计与分析 实 验 报 告 班级: 姓名: 学号: (备注:共给出5个参考实验案例,根据学号尾数做对应的实验,即如尾号为1,则模仿案例实验123;尾号2,则模仿案例实验234;尾号3,即345;尾号4,同1.)

目录 实验一分治与递归 (1) 1、基本递归算法 (1) 2、棋盘覆盖问题 (2) 3、二分搜索 (3) 4、实验小结 (5) 实验二动态规划算法 (5) 1、最长公共子序列问题 (5) 2、最大子段和问题 (7) 3、实验小结 (8) 实验三贪心算法 (8) 1、多机调度问题 (8) 2、用贪心算法求解最小生成树 (10) 3、实验小结 (12) 实验四回溯算法和分支限界法 (12) 1、符号三角形问题 (12) 2、0—1背包问题 (14) 3、实验小结 (18) 实验五多种排序算法效率比较 1、算法:起泡排序、选择排序、插入排序、shell排序,归并排序、快速排序等 (19) 2、实验小结 (18)

P art1:课程设计过程 设计选题--→题目分析---→系统设计--→系统实现--→结果分析---→撰写报告 P art2:课程设计撰写的主要规范 1.题目分析:主要阐述学生对题目的分析结果,包括题目描述、 分析得出的有关模型、相关定义及假设; 2.总体设计:系统的基本组成部分,各部分所完成的功能及相互 关系; 3.数据结构设计:主要功能模块所需的数据结构,集中在逻辑设 计上; 4.算法设计:在数据结构基础上,完成算法设计; 5.物理实现:主要有数据结构的物理存储,算法的物理实现,系 统相关的实现。具体在重要结果的截图,测试案例的结果数据,核心算法的实现结果等; 6.结果分析:对第五步的分析,包括定性分析和定量分析,正确 性分析,功能结构分析,复杂性分析等; 7.结论:学生需对自己的课程设计进行总结,给出评价,并写出 设计体会; 8.附录:带有注释的源代码,系统使用说明等; 9.参考文献:列出在撰写过程中所需要用到的参考文献。

堆排序算法的基本思想及算法实现示例

堆排序算法的基本思想及算法实现示例 堆排序 1、堆排序定义 n个关键字序列Kl,K2,…,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质): (1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤ ) 若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。 【例】关键字序列(10,15,56,25,30,70)和(70,56,30,25,15,10)分别满足堆性质(1)和(2),故它们均是堆,其对应的完全二叉树分别如小根堆示例和大根堆示例所示。 2、大根堆和小根堆 根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最小者的堆称为小根堆。 根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆。 注意: ①堆中任一子树亦是堆。 ②以上讨论的堆实际上是二叉堆(Binary Heap),类似地可定义k叉堆。 3、堆排序特点 堆排序(HeapSort)是一树形选择排序。 堆排序的特点是:在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系【参见二叉树的顺序存储结构】,在当前无序区中选择关键字最大(或最小)的记录。 4、堆排序与直接插入排序的区别 直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。 堆排序可通过树形结构保存部分比较结果,可减少比较次数。5、堆排序 堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。 (1)用大根堆排序的基本思想

算法分析实验报告--分治策略

《算法设计与分析》实验报告 分治策略 姓名:XXX 专业班级:XXX 学号:XXX 指导教师:XXX 完成日期:XXX

一、试验名称:分治策略 (1)写出源程序,并编译运行 (2)详细记录程序调试及运行结果 二、实验目的 (1)了解分治策略算法思想 (2)掌握快速排序、归并排序算法 (3)了解其他分治问题典型算法 三、实验内容 (1)编写一个简单的程序,实现归并排序。 (2)编写一段程序,实现快速排序。 (3)编写程序实现循环赛日程表。设有n=2k个运动员要进行网球循环赛。现 要设计一个满足以下要求的比赛日程表:(1)每个选手必须与其它n-1个选手各赛一次(2)每个选手一天只能赛一场(3)循环赛进行n-1天 四、算法思想分析 (1)编写一个简单的程序,实现归并排序。 将待排序元素分成大小大致相同的2个子集合,分别对2个子集合进行 排序,最终将排好序的子集合合并成为所要求的排好序的集合。 (2)编写一段程序,实现快速排序。 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有 数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数 据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据 变成有序序列。 (3)编写程序实现循环日赛表。 按分治策略,将所有的选手分为两组,n个选手的比赛日程表就可以通

过为n/2个选手设计的比赛日程表来决定。递归地用对选手进行分割, 直到只剩下2个选手时,比赛日程表的制定就变得很简单。这时只要让 这2个选手进行比赛就可以了。 五、算法源代码及用户程序 (1)编写一个简单的程序,实现归并排序。 #include #include #define MAX 10 using namespace std; void merge(int array[],int p,int q,int r) { int i,k; int begin1,end1,begin2,end2; int* temp = new int[r-p+1]; begin1 = p; end1 = q; begin2 = q+1; end2 = r; k = 0; while((begin1 <= end1)&&(begin2 <= end2)) { if(array[begin1] < array[begin2]) { temp[k] = array[begin1]; begin1++; } else { temp[k] = array[begin2]; begin2++; } k++; } while(begin1 <= end1) {

堆排序算法分析(C语言版)

堆排序 堆排序是利用堆的性质进行的一种选择排序,下面先讨论一下堆。 1.堆 堆实际上是一棵完全二叉树,其任何一非叶节点满足性质: Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2] 即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。 堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足Key[i]<= key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的。 2.堆排序的思想 利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。 其基本思想为(大顶堆): 1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区; 2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n]; 3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。 操作过程如下: 1)初始化堆:将R[1..n]构造为堆; 2)将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆。 因此对于堆排序,最重要的两个操作就是构造初始堆和调整堆,其实构造初始堆事实上也是调整堆的过程,只不过构造初始堆是对所有的非叶节点都进行调整。 下面举例说明: 给定一个整形数组a[]={16,7,3,20,17,8},对其进行堆排序。 首先根据该数组元素构建一个完全二叉树,得到

《算法分析与设计》实验指导书

《计算机算法设计与分析》实验指导书(第一版)

前言 计算机算法分析与设计是面向设计的,它是计算机科学的核心。无论是计算机系统、系统软件和解决计算机的各种应用问题都可归结为算法的设计。通过本课程的学习,使学生掌握计算机领域中许多常用的非数值的算法描述:分治法、贪心法、动态规划、回溯法、分枝限界等算法,并掌握算法分析的方法,从而把学生的分析问题和解决问题能力提高到理论的高度。 前期课程为程序设计语言、数据结构、高等数学,即学生应该具备一门高级语言程序设计编程基础,学习基本的数据结构知识,还要求学生掌握较好的数学基础。 开发环境不限,本书采用C/C++语言的集成开发环境等。 实验完成后书写实验报告,包含实验问题、基本思想、关键算法流程图、测试数据及运行结果(截图)、调试心得和源程序。 总实验学时为16学时。

目录 预备实验验证算法的方法 (4) 实验目的: (4) 实验课时: (4) 实验原理: (4) 实验题目: (6) 基本题: (6) 提高题: (6) 实验一递归与分治 (7) 实验目的: (7) 实验课时: (7) 实验原理: (7) 实验题目: (7) 基本题: (7) 提高题: (8) 思考问题: (8) 实验二动态规划算法 (9) 实验目的: (9) 实验课时: (9) 实验原理: (9) 实验题目: (9) 基本题: (9) 提高题: (10) 思考问题: (10) 实验三贪心选择算法 (11) 实验目的: (11) 实验课时: (11) 实验原理: (11) 实验题目: (11) 基本题: (11) 提高题: (12) 思考问题: (12) 实验四回溯算法 (13) 实验目的: (13) 实验课时: (13) 实验原理: (13) 实验题目: (14) 基本题: (14) 提高题: (14) 思考问题: (14)

堆排序

算法与数据结构程设计报告 一.设计题目: 堆排序的算法 二.运行环境: 1、硬件:计算机 2、软件:Microsoft Visual C++6.0 三.目的和意义: 目的:创建一个大堆,按从大到小顺序输出堆元素,实现堆排序。 意义:利用堆排序,即使在最坏情况下的时间复杂度也是O(nlog2n),相对于快速排序来说,时间复杂度小,这是堆排序的最大优点,可用于对若干元素进行排序,加快排序速度。 四.算法设计的基本思想: 堆排序算法设计基本思想: 堆排序利用了大根堆堆顶记录的关键字最大这一特征,使得在当前无序区中选取最大关键字的记录变得简单。先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区。再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录r[n]交换,由此得到新的无序区r[1..n-1]和有序区r[n],且满足r[1..n-1].keys≤r[n].key。由于交换后新的根R[1]可能违反堆性质,故应将当前无序区r[1..n-1]调整为堆。然后再次将r[1..n-1]中关键字最大的记录r[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区r[1..n-2]和有序区r[n-1..n],且仍满足关系r[1..n-2].keys≤r[n-1..n].keys,同样要将r[1..n-2]调整为堆。直到无序区只有一个元素为止.

. .

流程图3:打印数组函数print()

六.算法设计分析: 性能分析:堆排序的时间主要由建立初始堆和不断重复建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的。其中:建立初始堆时,总共需进行的关键字比较次数≤ 4n =O(n) ;排序过程中进行n-1次重建堆所进行的总比较次数不超过下式:2*(└ log2(n-1) ┘+└ log2(n-2) ┘+…+ └ log22 ┘) < 2n └ log2n ┘=O(n log2n)因此堆排序总的时间复杂度是 O(n+ n log2n)= O(n log2n)。堆排序在最坏情况下的时间复杂度也是O(nlog2n),相对于快速排序来说,这是堆排序的最大优点。另外,堆排序仅需一个记录大小供交换用的辅助空间。由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录较少的文件,但对n较大的文件还是很有效的。堆排序是就地排序,辅助空间为O(1),它是不稳定的排序方法。 堆的描述:堆排序(HeapSort)是一树形选择排序。堆是对基于数组的树的重要应用场合之一。它是节点间具有层次次序关系的完全二叉树。其中,父节点值大于或等于其孩子节点值的,叫“最大堆(maximum heap)”;父节点值小于或等于孩子节点值的,叫“最小堆(minimum heap)”.在最大堆中,根中的元素值最大;在最小堆中,根中的元素值最小。堆排序的特点是:在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序区中选择关键字最大(或最小)的记录。 从算法描述来看,堆排序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函数。 堆的存储特点:在这里,讨论作为顺序表存储的堆。它是按某种次序将一系列数据以完全二叉树形式存放的一种表。它要求堆中的节点的值都大于或等于其孩子节点的值。 按照这种存储方式,可知第i个元素的左右儿子分别是第2i和第2i+1个元素,而它的父亲节点是第i/2个元素。由于父亲节点和儿子节点具有这样的顺序关系,所以可以方便地由父亲节点找到儿子节点,反之亦然。 可见,这种存储方式大大节省了存储空间,高效快速。 堆的相关操作:作为抽象表结构,堆允许增加和删除表项。插入过程不用假定新表项占有一个特定的位置而只需维持堆顺序。但是删除操作总是删去表中的最大项(根)。堆可以用于那些客户程序想直接访问最大(小)元素的场合。作为表,堆并不提供Find操作,而对表的直接访问是只读的。所有的堆处理算法都有责任更新树和维持堆顺序。 1.建堆:数组具有对应的树表示形式。一般情况下,树并不满足堆的条件。通过重新排列元素,可以建立一棵“堆化”的树。 2.插入一个元素:新元素被加入到表中,随后树被更新以恢复堆次序。例如,下面的步骤将15加入到表中。 3.删除一个元素:删除总是发生在根节点处。用表中的最后一个元素来填补空缺位置,结果树被更新以恢复堆条件。 在堆实现时我们是采用数组来存储堆的完全二叉树表示,并且用一种有效的算法来保证对堆的所有操作不破坏堆的性质。这种表示的主要问题在于数组的大小需要事先确定,这使得对堆的大小有了一个初始的限定。在堆中数据增长到

武汉理工大学算法分析实验报告

学生实验报告书 实验课程名称算法设计与分析开课学院计算机科学与技术学院 指导教师姓名李晓红 学生姓名 学生专业班级软件工程zy1302班2015-- 2016学年第一学期

实验课程名称:算法设计与分析 同组者实验日期2015年10月20日第一部分:实验分析与设计 一.实验内容描述(问题域描述) 1、利用分治法,写一个快速排序的递归算法,并利用任何一种语言,在计算机上实现,同时 进行时间复杂性分析; 2、要求用递归的方法实现。 二.实验基本原理与设计(包括实验方案设计,实验手段的确定,试验步骤等,用硬件逻辑或者算法描述) 本次的解法使用的是“三向切分的快速排序”,它是快速排序的一种优化版本。不仅利用了分治法和递归实现,而且对于存在大量重复元素的数组,它的效率比快速排序基本版高得多。 它从左到右遍历数组一次,维护一个指针lt使得a[lo..lt-1]中的元素都小于v,一个指针gt 使得a[gt+1..hi]中的元素都大于v,一个指针i使得a[lt..i-1]中的元素都等于v,a[i..gt]中的元素都还未确定,如下图所示: public class Quick3way { public static void sort(Comparable[] a, int lo, int hi) { if (lo >= hi) return; int lt = lo, i = lo + 1, gt = hi; Comparable pivot = a[lo];

第二部分:实验调试与结果分析 一、调试过程(包括调试方法描述、实验数据记录,实验现象记录,实验过程发现的问题等) 1、调试方法描述: 对程序入口进行断点,随着程序的运行,一步一步的调试,得到运行轨迹; 2、实验数据: "R", "B", "W", "W", "R", "W", "B", "R", "R", "W", "B", "R"; 3、实验现象: 4、实验过程中发现的问题: (1)边界问题: 在设计快速排序的代码时要非常小心,因为其中包含非常关键的边界问题,例如: 什么时候跳出while循环,递归什么时候结束,是对指针的左半部分还是右半部分 排序等等; (2)程序的调试跳转: 在调试过程中要时刻记住程序是对那一部分进行排序,当完成了这部分的排序后, 会跳到哪里又去对另外的那一部分进行排序,这些都是要了然于心的,这样才能准 确的定位程序。 二、实验结果分析(包括结果描述、实验现象分析、影响因素讨论、综合分析和结论等) 1、实验结果:

算法分析与设计实验指导书

《算法分析与设计》实验指导书 《算法分析与设计》课程是计算机专业的一门必修课程。开设算法分析与设计实验,目的就是为了使学生消化理论知识,加深对讲授内容的理解,尤其是一些算法的实现及其应用,培养学生独立编程和调试程序的能力,使学生对算法的分析与设计有更深刻的认识。 《算法分析与设计》课程实验的目的:是为了使学生在课程学习的同时,通过实验环境中的实际操作,对部分算法的具体应用有一个初步的了解,使学生加深了解和更好地掌握《算法分析与设计》课程教学大纲要求的内容。 《算法分析与设计》课程实验的注意事项:在《算法分析与设计》的课程实验过程中,要求学生做到: (1)预习实验指导书有关部分,认真做好实验内容的准备,就实验可能出 现的情况提前作出思考和分析。 (2)认真书写实验报告。实验报告包括实验目的和要求,实验情况及其分 析。 (3)遵守机房纪律,服从辅导教师指挥,爱护实验设备。 (4)实验课程不迟到。如有事不能出席,所缺实验一般不补。 《算法分析与设计》课程实验的验收:实验的验收将分为两个部分。第一部分是上机操作,包括检查程序运行和即时提问。第二部分是提交电子的实验报告。

实验一算法实现一 一、实验目的与要求 熟悉C/C++语言的集成开发环境; 通过本实验加深对分治法、贪心算法的理解。 二、实验内容: 掌握分治法、贪心算法的概念和基本思想,并结合具体的问题学习如何用相应策略进行求解的方法。 三、实验题 1. 【伪造硬币问题】给你一个装有n个硬币的袋子。n个硬币中有一个是伪造的。你的 任务是找出这个伪造的硬币。为了帮助你完成这一任务,将提供一台可用来比较两组硬币重量的仪器,利用这台仪器,可以知道两组硬币的重量是否相同。试用分治法的思想写出解决问题的算法,并计算其时间复杂度。 2.【找零钱问题】一个小孩买了价值为33美分的糖,并将1美元的钱交给售货员。售 货员希望用数目最少的硬币找给小孩。假设提供了数目有限的面值为25美分、10美分、5美分、及1美分的硬币。给出一种找零钱的贪心算法。 a)实验步骤 理解算法思想和问题要求; 编程实现题目要求; 上机输入和调试自己所编的程序; 验证分析实验结果; 整理出实验报告。 四、实验程序 五、实验结果 六、实验分析

算法设计与分析实验报告

本科实验报告 课程名称:算法设计与分析 实验项目:递归与分治算法 实验地点:计算机系实验楼110 专业班级:物联网1601 学号:2016002105 学生:俞梦真 指导教师:郝晓丽 2018年05月04 日

实验一递归与分治算法 1.1 实验目的与要求 1.进一步熟悉C/C++语言的集成开发环境; 2.通过本实验加深对递归与分治策略的理解和运用。 1.2 实验课时 2学时 1.3 实验原理 分治(Divide-and-Conquer)的思想:一个规模为n的复杂问题的求解,可以划分成若干个规模小于n的子问题,再将子问题的解合并成原问题的解。 需要注意的是,分治法使用递归的思想。划分后的每一个子问题与原问题的性质相同,可用相同的求解方法。最后,当子问题规模足够小时,可以直接求解,然后逆求原问题的解。 1.4 实验题目 1.上机题目:格雷码构造问题 Gray码是一个长度为2n的序列。序列无相同元素,每个元素都是长度为n的串,相邻元素恰好只有一位不同。试设计一个算法对任意n构造相应的Gray码(分治、减治、变治皆可)。 对于给定的正整数n,格雷码为满足如下条件的一个编码序列。 (1)序列由2n个编码组成,每个编码都是长度为n的二进制位串。 (2)序列中无相同的编码。 (3)序列中位置相邻的两个编码恰有一位不同。 2.设计思想: 根据格雷码的性质,找到他的规律,可发现,1位是0 1。两位是00 01 11 10。三位是000 001 011

010 110 111 101 100。n位是前n-1位的2倍个。N-1个位前面加0,N-2为倒转再前面再加1。 3.代码设计:

算法设计与分析实验报告

算法设计与分析实验报告 教师: 学号: 姓名:

实验一:串匹配问题 实验目的:(1) 深刻理解并掌握蛮力法的设计思想; (2) 提高应用蛮力法设计算法的技能; (3) 理解这样一个观点: 用蛮力法设计的算法, 一般来说, 经过适度的努力后, 都可以对算法的第一个版本进行一定程度的改良, 改进其时间性能。 三、实验要求:( 1) 实现BF 算法; (2 ) 实现BF 算法的改进算法: KMP 算法和BM 算法; (3 ) 对上述 3 个算法进行时间复杂性分析, 并设计实验程序验证 分析结果。 #include "stdio.h" #include "conio.h" #include //BF算法 int BF(char s[],char t[]) { int i; int a; int b; int m,n; m=strlen(s); //主串长度 n=strlen(t); //子串长度 printf("\n*****BF*****算法\n"); for(i=0;i

算法分析与设计实验六

实验五动态规划实验 一、实验目的 1.掌握动态规划算法的基本思想。 二、实验内容 1、参考教材描述,使用动态规划算法求解多段图的最短路径问题。#include #include #define max_value 10000 #define zero_value 0 typedef struct NODE{ int v_num; int len; struct NODE *next; }LinkStackNode,LinkStack; /* typedef struct PNODE{ int data; int len; struct PNODE *next; }*LinkStackPnode,*LinkStack;*/ int fgraph(LinkStack top[],int route[],int n) { int i; LinkStackNode *pnode; int *path=new int[n];

int *cost=new int[n]; int min_cost; for(i=0;i=0;i--) { pnode=top[i].next; while(pnode!=NULL) { if(pnode->len+cost[pnode->v_num]len+cost[pnode->v_num]; path[i]=pnode->v_num; } pnode = pnode-> next; } } i=0; while((route[i]!=n-1)&&(path[i]!=-1)) { i++; route[i]=path[route[i-1]]; } min_cost=cost[0]; delete path;

算法分析与设计实验报告

实验一、归并排序及各种排序算法性能比较 一、实验实习目的及要求 了解归并排序等各种排序算法,并能独立在计算机上实现,同时并能够计算它们的时间复杂度,并用计算机来验证。 二、实验实习设备(环境)及要求(软硬件条件) 计算机eclipse软件,执行环境JavaSE-1.8. 三、实验实习项目、内容与步骤(注意是主要关键步骤,适当文字+代码+截图说明) 项目:对10 4 6 3 8 2 5 7进行从小到大排序,采用几种排序方法,并统计这几种方法的运行时间,与归并排序比较。 内容及步骤: (1)归并排序:将序列每次分成两组,再进行合并,直到递归完成; 1、递归调用mergeSort对数组排序 2、merge将两个有序数组合并为一个有序数组

3、主函数调用mergeSort对数组排序 4、统计时间 (2) 选择排序:每次选择一个当前最小的并和当前的相对的第一个元素交换,直到最后 只有一个元素时结束;也可选择当前最大的并与当前的相对的最后一个 元素交换,直到最后只有一个元素时结束。

1、数组长度为n,需要选择n-1次;每次选择完成后,将数组中的最大值与最后一 个元素互换,调用java.util包中Arrays类。 2、主函数调用ChooseSort对数组排序。 3、统计运行时间。 (3)插入排序:从第二个元素开始,每次插入一个到当前有序序列中,使得有序,当 所有的元素插入完毕时,就排好序了; 1、从第二个元素开始,与之前序列比较,插入到合适的位置。

2、主函数调用sort对数组排序。 3、统计运行时间 (4) 快速排序:每次选择一个中间元素,并进行交换,使得中间元素的左边比它小,右 边比它大,然后对左右两边进行递归; 1、选取一个基准位,从右边向左边看,找比基准位小的元素,再从左边向右边看, 找比基准位大的元素,若两者均存在则交换;若两者相遇,则相遇元素与基准位元素交换,然后递归排序左右半数组。

相关主题
文本预览
相关文档 最新文档