算法设计与分析实验3报告.docx

上传人:b****7 文档编号:15278338 上传时间:2023-07-03 格式:DOCX 页数:18 大小:33.39KB
下载 相关 举报
算法设计与分析实验3报告.docx_第1页
第1页 / 共18页
算法设计与分析实验3报告.docx_第2页
第2页 / 共18页
算法设计与分析实验3报告.docx_第3页
第3页 / 共18页
算法设计与分析实验3报告.docx_第4页
第4页 / 共18页
算法设计与分析实验3报告.docx_第5页
第5页 / 共18页
算法设计与分析实验3报告.docx_第6页
第6页 / 共18页
算法设计与分析实验3报告.docx_第7页
第7页 / 共18页
算法设计与分析实验3报告.docx_第8页
第8页 / 共18页
算法设计与分析实验3报告.docx_第9页
第9页 / 共18页
算法设计与分析实验3报告.docx_第10页
第10页 / 共18页
算法设计与分析实验3报告.docx_第11页
第11页 / 共18页
算法设计与分析实验3报告.docx_第12页
第12页 / 共18页
算法设计与分析实验3报告.docx_第13页
第13页 / 共18页
算法设计与分析实验3报告.docx_第14页
第14页 / 共18页
算法设计与分析实验3报告.docx_第15页
第15页 / 共18页
算法设计与分析实验3报告.docx_第16页
第16页 / 共18页
算法设计与分析实验3报告.docx_第17页
第17页 / 共18页
算法设计与分析实验3报告.docx_第18页
第18页 / 共18页
亲,该文档总共18页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

算法设计与分析实验3报告.docx

《算法设计与分析实验3报告.docx》由会员分享,可在线阅读,更多相关《算法设计与分析实验3报告.docx(18页珍藏版)》请在冰点文库上搜索。

算法设计与分析实验3报告.docx

算法设计与分析实验3报告

湖南科技学院实验报告

系部

数学与计算科学

专业

信息与计算科学

成绩评定

班级

信计0902班

学号

200905002231

姓名

易丹

课程名称

算法设计与分析

实验时间

2012.4.16

实验编号

实验三

实验名称

贪心算法

实验环境

D315、一台电脑、Codeblocks10.05

实验目的

1.理解贪心算法的概念。

2.理解贪心算法与动态规划算法的差异。

3.掌握贪心算法的基本要素。

4.掌握设贪心设计策略。

实验内容(①算法、程序、步骤和方法②输入、输出、实验结果③实验结果分析)

实验内容:

1.最小生成树的Kruskal算法

实现最小生成树的Kruskal算法。

数据文件见附件。

2.哈夫曼编码(选做)

实现哈夫曼算法。

数据文件见附件。

实验要求:

1.实验报告只写实验⑴。

2.写出算法思想、主要程序代码、算法复杂性分析。

实验

(1)的步骤、算法及运行结果:

⑴打开Codeblocks10.05,编辑如下程序如下:

UnionFind.h

#ifndefUNIONFIND_H_INCLUDED

#defineUNIONFIND_H_INCLUDED

//并查集(Union-Find-Sets)

classUnionFind//并查集的类定义

{

private:

int*parent;//集合元素数组(存放各元素的双亲结点的指针)

intsize;//集合元素的数目

public:

UnionFind(ints=10);//构造函数

~UnionFind()//析构函数

{

delete[]parent;

}

UnionFind&operator=(UnionFindconst&Value);//集合赋值

voidUnion(intRoot1,intRoot2);//两个子集合合并

intFind(intx);//搜寻集合x的根

};

UnionFind:

:

UnionFind(ints)//构造函数,s是集合元素个数

{

size=s;

parent=newint[size+1];//创建双亲指针数组

for(inti=0;i<=size;i++)

parent[i]=-1;//每一个自成一个单元素集合

}

intUnionFind:

:

Find(intx)//搜索并返回包含元素x的树的根

{

if(parent[x]<=0)

returnx;

else

returnFind(parent[x]);

}

voidUnionFind:

:

Union(intRoot1,intRoot2)//并

{

parent[Root2]=Root1;//将根Root2连接到另一个根Root1下面  

}

#endif//UNIONFIND_H_INCLUDED

MinHeap.h

#ifndefMINHEAP_H_INCLUDED

#defineMINHEAP_H_INCLUDED

#include

#include

usingnamespacestd;

#defineDefaultSize20

templateclassMinHeap;

template

ostream&operator<<(ostream&os,constMinHeap&);

////////////////////////////////////////////////////////

//MinHeap堆类最小堆的声明和定义

//即以完全二叉树的顺序存储方式来实现优先级队列

//T为结点的类型

////////////////////////////////////////////////////////

template//T为结点的类型

classMinHeap

{

public:

MinHeap(intsz=DefaultSize);//构造函数,建立一个空堆

MinHeap(T*arr,intn);//构造函数,通过数组来建堆

~MinHeap()//析构函数,释放堆的内存空间

{

if(heap!

=NULL)

delete[]heap;

}

boolInsert(constT&x);//将元素x插入到最小堆中

voidInitialize(T*arr,intn,intm);//用有n个元素的数组arr建容量为m的堆

boolDeleteMin(T&x);//删除堆顶的最小元素

boolIsEmpty()const//判断当前堆是否为空

{

returncurrentSize==0;

}

boolIsFull()const//判断当前堆是否为满

{

returncurrentSize==MaxHeapSize;

}

voidMakeEmpty()//把当前堆置空

{

currentSize=0;

}

voidDisplay();//显示当前堆的内容

voidsiftDown();//下浮全部调整

voidsiftUp();//上浮全部调整

voidDeactivate();//释放内存空间

friendostream&operator<<<>(ostream&os,constMinHeap&);//友元重载运算浮输出堆的内容

intGetCurrentSize()//获取堆中元素个数

{

returncurrentSize;

}

intGetMaxheapSize()//获取当前堆的最大容量

{

returnMaxHeapSize;

}

private:

T*heap;//存放最小堆中元素的数组的首指针

intcurrentSize;//最小堆中当前元素的个数

intMaxHeapSize;//最小堆中最多允许的元素的个数

voidsiftDown(intstart,intm);//从start到m下滑调整成为最小堆

voidsiftUp(intstart);//从start到0上滑调整成最小堆

};

///////////////////////////////////////MinHeap类声明结束

////////////////////////////////////////////////////////

//构造函数

//建立一个空的最小堆,并在定义的时指定堆的尺寸大小

//T为结点的类型

////////////////////////////////////////////////////////

template

MinHeap:

:

MinHeap(intsz)

{

//设定堆的最多允许的元素的个数

MaxHeapSize=(DefaultSize

sz:

DefaultSize;

//为堆的顺序存储结构开辟内存空间

heap=newT[MaxHeapSize];

//如果内存分配失败

if(heap==NULL)

{

cout<<"最小堆的内存分配失败!

"<

exit

(1);

}

//刚开始堆中的元素的个数是0个

currentSize=0;

}

////////////////////////////////////////////构造函数结束

////////////////////////////////////////////////////////

//带参数的构造函数用数组中的元素创建堆

////////////////////////////////////////////////////////

template

MinHeap:

:

MinHeap(T*arr,intn)//arr的下标从1开始

{

MaxHeapSize=(DefaultSize

n:

DefaultSize;//得到最大允许的元素的个数

heap=newT[MaxHeapSize];//开辟最小堆的内存

if(heap==NULL)//如果内存分配失败

{

cout<<"最小堆的内存分配失败!

"<

exit

(1);

}

for(inti=1;i<=n;i++)//把参数数组中的元素一次复制到堆中

Insert(arr[i]);

currentSize=n;

}

////////////////////////////////////带参数的构造函数结束

//释放内存空间

template

voidMinHeap:

:

Deactivate()

{

delete[]heap;

}

////////////////////////////////////////////////////////

//siftDown()私有成员函数

//从start到m下滑调整成为最小堆

//下滑调整的前提是当前结点的左右子树都已经成堆

////////////////////////////////////////////////////////

template

voidMinHeap:

:

siftDown(intstart,intm)

{

inti=start;//i从start开始调整

intj=2*i+1;//用于指向要和i对调的结点,先指向i的左子结点

Ttemp;//交换时用到的中间结点

while(j<=m)//到m时调整结束

{

//如果至少有一个子结点小于根结点,则需要调整

if(heap[j]

{

//如果左子结点大于右子结点

if(heap[j]>heap[j+1])

j=j+1;//跟较小的子结点进行位置调整

//如果根根结点更大,则要进行调整

if(heap[i]>heap[j])

{

//交换Heap[i]和Heap[j]的数据内容

temp=heap[i];

heap[i]=heap[j];

heap[j]=temp;

}

i=j;//从刚对调完的子结点继续调整下去

j=2*i+1;

}

else

break;

}

}

//////////////////////////////////////siftDown()函数结束

////////////////////////////////////////////////////////

//siftDown()公有成员函数

//对堆进行全部的下浮调整,只针对所有分支结点从后往前即可

////////////////////////////////////////////////////////

template

voidMinHeap:

:

siftDown()

{

//找到最后一个还有子结点的结点

intcurrentPos=(currentSize-2)/2;

//从当前的currentPos依次向前进行下滑调整

while(currentPos>=0)

{

//局部自上而下地下滑调整

siftDown(currentPos,currentSize-1);

//再向前换一个分支结点

currentPos--;

}

}

/////////////////////////////////////siftDown()函数结束

////////////////////////////////////////////////////////

//siftUp()私有成员函数

//从start开始向上调整到根结点(0)

//利用了一个子结点都至多有一个父结点的特性

////////////////////////////////////////////////////////

template

voidMinHeap:

:

siftUp(intstart)

{

inti=start;//从i结点开始向上浮动调整

intj;//指向要调整的父结点

Ttemp;//交换用的临时变量

while(i>0)

{

//得到当前结点i的父结点的指针

if(i%2==1)//如果i是奇数结点

j=(i-1)/2;//说明i是j的左子结点

else

j=(i-2)/2;//说明i是j的右子结点

if(heap[i]

{

//交换Heap[i]和Heap[j]的数据内容

temp=heap[i];

heap[i]=heap[j];

heap[j]=temp;

}

i=j;//继续上浮调整

}

}

////////////////////////////////////////siftUp()函数结束

////////////////////////////////////////////////////////

//siftUp()公有成员函数

//对堆进行全部的上浮调整,即堆所有的叶子结点从后往前调整

////////////////////////////////////////////////////////

template

voidMinHeap:

:

siftUp()

{

//通过上浮的方法来调整堆

//从最后一个结点进行上浮调整

intcurrentPos=currentSize-1;

//从后往前调整到第一个叶子结点就可以了

intend=currentSize-int((currentSize-1)/2)-1;

//从后往前对每个叶子结点进行上浮调整

while(currentPos>=end)

{

siftUp(currentPos);

currentPos--;

}

}

////////////////////////////////////////siftUp()函数结束

////////////////////////////////////////////////////////

//Display()公有成员函数

//显示当前堆序列的内容

////////////////////////////////////////////////////////

template

voidMinHeap:

:

Display()

{

//显示堆的内容

for(inti=0;i

cout<

}

///////////////////////////////////////Display()函数结束

////////////////////////////////////////////////////////

//友元重载输出运算符<<输出当前堆的内容

////////////////////////////////////////////////////////

template

ostream&operator<<(ostream&os,constMinHeap&MH)

{

//显示堆中的内容

for(inti=0;i

os<

returnos;

}

//////////////////////////////////////////<<友元重载结束

////////////////////////////////////////////////////////

//Insert()公有成员函数

//在堆的尾部插入一个元素,并进行重新调整

////////////////////////////////////////////////////////

template

boolMinHeap:

:

Insert(constT&x)

{

//如果堆中的元素已经满了

if(currentSize==MaxHeapSize)//堆满则调整容量

{

T*p=heap;

heap=newT[MaxHeapSize+DefaultSize];

if(heap==NULL)

{

cout<<"最小堆的内存分配失败!

"<

exit

(1);

}

for(inti=0;i

heap[i]=p[i];

MaxHeapSize+=DefaultSize;

delete[]p;

}

//把新元素先放在最后一个位置

heap[currentSize]=x;

currentSize++;

//对堆进行重新调整,只要对最后一个结点作一次上浮调整即可

siftUp(currentSize-1);

returntrue;

}

////////////////////////////////////////Insert()函数结束

//用有n个元素的数组arr建容量为m的堆

template

voidMinHeap:

:

Initialize(T*arr,intn,intm)//arr的下标从1开始

{

delete[]heap;

intk=n>m?

n:

m;

heap=newT[k];

if(heap==NULL)

{

cout<<"最小堆的内存分配失败!

"<

exit

(1);

}

MaxHeapSize=m;

for(inti=1;i<=n;i++)

Insert(arr[i]);

currentSize=n;

}

////////////////////////////////////////////////////////

//DeleteMin()公有成员函数

//删除堆顶的最小的结点,并进行再次调整

//(只需对新堆顶作一次下沉调整即可)

////////////////////////////////////////////////////////

template

boolMinHeap:

:

DeleteMin(T&x)

{

//如果堆中的元素已经没有了

if(currentSize==0)

{

cout<<"堆中已经没有元素了!

"<

returnfalse;

}

//删除堆顶的元素

x=heap[0];

//把最后一个元素替换到堆顶的位置

heap[0]=heap[currentSize-1];

//现存的元素个数减一

currentSize--;

//对堆顶元素作一次下沉调整即可

siftDown(0,currentSize-1);

returntrue;

}

/////////////////////////////////////DeleteMin()函数结束

#endif//MINHEAP_H_INCLUDED

Main.cpp

#include

#include"MinHeap.h"

#include"UnionFind.h"

usingnamespacestd;

template

classEdgeNode//声明边类

{

template

friendostream&operator<<(ostream&,EdgeNode);

template

friendboolKruskal(int,int,EdgeNode*,EdgeNode*);

public:

EdgeNode(){}

EdgeNode(inta,intb,Typew):

u(a),v(b),weight(w){}

operatorType()const

{

returnweight;

}

private:

intu,v;//边的两个顶点

Typeweight;//边的权

};

template

boolKruskal(intn,inte,EdgeNodeE[],EdgeNodet[])

{

//n,顶点数

//e,边数

//E,边数组

//t,存储生成树的边

MinHeap>H

(1);

H.Initialize(E,e,e);//按边的权建立边的最小堆

UnionFindU(n);//建n个元素的并查集

intk=0;//用于记录合并的次数

while(e&&k

{

EdgeNodex;//定义边数组

H.DeleteMin(x);//取权最小的一条边

cout<<"MIN:

"<

e--;

inta=U.Find(x.u);//找边的两个顶点所在的集合

intb=U.Find(x.v);

if(a!

=b)//两顶点不属于同一集合,则合并两边所在的集合

{

t[k++]=x;//记下此边

U.Union(a,b);

}

}

H.Deactivate();

return(k==n-1);

}

template

ostream&operator<<(ostream&os,EdgeNodee)

{

os<

returnos;

}

intmain()

{

int**M;

charfilename[]="boat.txt";

ifstreaminfile(filename);

intn=0;

infile>>n;

constinte=10;

EdgeNode

E[]={EdgeNode(0,0,0),EdgeNode(1,2,6),EdgeNode(2,5

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2