最小生成树和最短路径-数据结构实验

最小生成树和最短路径-数据结构实验
最小生成树和最短路径-数据结构实验

June 18

2015

姓名:陈斌学号:E11314079

专业:13计算机科学与技术

学号E11314079专业计算机科学与技术姓名陈斌

实验日期2015.06.18 教师签字成绩

实验报告

【实验名称】最小生成树和最短路径

【实验目的】

(1)掌握最小生成树以及最短路径的相关概念;

(2)掌握Prim算法和Kruskal算法;

(3)掌握Dijkstra算法

【实验内容】

采用普里姆算法求最小生成树

(1)编写一个算法,对于教材图7.16(a)所示的无向带权图G采用普里姆算法输出从

顶点V1出发的最小生成树。图的存储结构自选。

(2)对于上图,采用克鲁斯卡尔算法输出该图的最小生成树。(提示:a.先对边按

权值从小到大排序,得有序边集E;为所有顶点辅设一个数组Vset,标记各顶

点所处的连通分量,初始时各不相同。b. 依次从E中取出一条边(i,j),检查顶点i和j是否属于同一连通分量,如是,则重取下一条边;否则,该边即为生成树的一条边,输出该边,同时将所有与j处于同一连通分量的顶点的Vset值都修改为与i的相同。c.重复b步直至输出n-1条边。)

源代码:

head.h:

#include

#include

#include //malloc( )

#include // INT ,MAX

#include //EOF,NULL

#include //atoi( )

#include //eof( )

#include //floor( ),ceil( ),abs( )

#include //exit( )

#include //cout,cin

//函数结果状态代码

#define TRUE 1

#define FALSE 0

#define OK 1

#define ERROR 0

#define INFEASIBLE -1

//OVERFLOW 在math.h 中已定义为3

typedef int Status;

typedef int Boolean; // 布尔类型

main.cpp:

#include"head.h"

typedef int VRType;

typedef char InfoType;

#define MAX_NAME 3 /* 顶点字符串的最大长度+1 */

#define MAX_INFO 20 /* 相关信息字符串的最大长度+1 */

typedef char VertexType[MAX_NAME];

/*图的数组(邻接矩阵)存储表示*/

#define INFINITY INT_MAX /* 用整型最大值代替∞*/

#define MAX_VERTEX_NUM 20 /* 最大顶点个数*/

typedef enum{DG,DN,AG,AN}GraphKind; /* {有向图,有向网,无向图,无向网} */ typedef struct

{

VRType adj; /* 顶点关系类型。对无权图,用1(是)或0(否)表示相邻否;*/ /* 对带权图,c则为权值类型*/

InfoType *info; /* 该弧相关信息的指针(可无) */

}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct

{

VertexType vexs[MAX_VERTEX_NUM]; /* 顶点向量*/

AdjMatrix arcs; /* 邻接矩阵*/

int vexnum,arcnum; /* 图的当前顶点数和弧数*/

GraphKind kind; /* 图的种类标志*/

}MGraph;

int LocateVex(MGraph G,VertexType u)

{ /* 初始条件:图G存在,u和G中顶点有相同特征*/

/* 操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 */ int i;

for(i=0;i

if(strcmp(u,G.vexs[i])==0)

return i;

return -1;

}

Status CreateAN(MGraph &G)

{ /* 采用数组(邻接矩阵)表示法,构造无向网G*/

int i,j,k,w;

VertexType va,vb;

printf("请输入无向网G的顶点数边数(用逗号隔开):");

scanf("%d,%d",&G.vexnum,&G.arcnum);

printf("请输入%d个顶点的值(<%d个字符;用空格隔

开):\n",G.vexnum,MAX_NAME);

for(i=0;i

scanf("%s",G.vexs[i]);

for(i=0;i

for(j=0;j

{

G.arcs[i][j].adj=INFINITY; /* 网*/

}

printf("请输入%d条边的顶点1 顶点2 权值(用空格隔开): \n",G.arcnum);

for(k=0;k

{

scanf("%s%s%d%*c",va,vb,&w); /* %*c吃掉回车符*/

i=LocateVex(G,va);

j=LocateVex(G,vb);

G.arcs[i][j].adj=G.arcs[j][i].adj=w; /* 无向*/

}

G.kind=AN;

return OK;

}

typedef struct

{ /* 记录从顶点集U到V-U的代价最小的边的辅助数组定义*/

VertexType adjvex;

VRType lowcost;

}minside[MAX_VERTEX_NUM];

int minimum(minside SZ,MGraph G)

{ /* 求closedge.lowcost的最小正值*/

int i=0,j,k,min;

while(!SZ[i].lowcost)

i++;

min=SZ[i].lowcost; /* 第一个不为0的值*/

k=i;

for(j=i+1;j

if(SZ[j].lowcost>0)

if(min>SZ[j].lowcost)

{

min=SZ[j].lowcost;

k=j;

}

return k;

}

void MiniSpanTree_PRIM(MGraph G,VertexType u)

{ /* 用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边算法7.9 */

int i,j,k;

minside closedge;

k=LocateVex(G,u);

for(j=0;j

{

if(j!=k)

{

strcpy(closedge[j].adjvex,u);

closedge[j].lowcost=G.arcs[k][j].adj;

}

}

closedge[k].lowcost=0; /* 初始,U={u} */

printf("最小代价生成树的各条边为:\n");

for(i=1;i

{ /* 选择其余G.vexnum-1个顶点*/

k=minimum(closedge,G); /* 求出T的下一个结点:第K顶点*/

printf("(%s-%s)\n",closedge[k].adjvex,G.vexs[k]); /* 输出生成树的边*/

closedge[k].lowcost=0; /* 第K顶点并入U集*/

for(j=0;j

if(G.arcs[k][j].adj

{ /* 新顶点并入U集后重新选择最小边*/

strcpy(closedge[j].adjvex,G.vexs[k]);

closedge[j].lowcost=G.arcs[k][j].adj;

}

}

}

typedef struct node

{

int va; //边的起始顶点

int vb; //边的终止顶点

int w; //边的权值}Edge;

int Vset[MAX_VERTEX_NUM];

void Initialize(MGraph &G)

{

for(int i=0;i

Vset[i] = i;

}

int Sizearray(MGraph G)

{

return 2*G.arcnum-1;

}

void Switch(Edge &b,Edge a)

{

b.va=a.va;

b.vb=a.vb;

b.w=a.w;

}

void HeapAdjust(Edge a[],int low,int high)

{//建大顶堆

int i=low;

Edge temp;

Switch(temp,a[i]); //先将堆顶存入temp for(int j=2*i+1;j<=high;j=2*j+1)

{

if(j

j++;

if(temp.w

{ //若不满足大顶堆条件,则需进行调准Switch(a[i],a[j]);

i=j;

}

else

break;

}

Switch(a[i],temp); //最后确定a[i]的位置}

void Heapsort(Edge a[],MGraph G)

{

Edge temp;

for(int i=Sizearray(G)/2;i>=0;--i)

HeapAdjust(a,i,Sizearray(G));

for(i=Sizearray(G);i>0;--i)

{

Switch(temp,a[0]);

Switch(a[0],a[i]);

Switch(a[i],temp);

HeapAdjust(a,0,i-1);

}

}

void MiniSpanTree_Kruskal(MGraph G)

{

Edge E[MAX_VERTEX_NUM];

int k=0;

for (int i=0;i

{

for (int j=0;j

{

if (G.arcs[i][j].adj!=INFINITY)

{

E[k].va=i;

E[k].vb=j;

E[k].w=G.arcs[i][j].adj;

k++;

}

}

}

Heapsort(E,G);

Initialize(G); //初始化辅助数组k=1; //生成的边数,最后要刚好为总边数

int j=0; //E中的下标 printf("最小代价生成树的各条边及相应权值为:\n");

while (k

{

int sn1=Vset[E[j].va];

int sn2=Vset[E[j].vb]; //得到两顶点属于的集合编号

if (sn1!=sn2) //不在同一集合编号内的话,把边加入最小生成树

{

printf("(%s-%s):%d\n",G.vexs[E[j].va],G.vexs[E[j].vb],E[j].w);

k++;

for (i=0;i

if (Vset[i]==sn2)

Vset[i]=sn1;

}

j++;

}

}

void main()

{

MGraph G;

CreateAN(G);

cout<<"--------普里姆算法输出从顶点V1出发的最小生成树--------\n"<

MiniSpanTree_PRIM(G,G.vexs[0]);

cout<<"------------------------------------------------------\n"<

cout<<"--------克鲁斯卡尔算法输出从顶点V1出发的最小生成树----\n"<

MiniSpanTree_Kruskal(G);

cout<<"------------------------------------------------------"<

}

运行结果:

采用迪杰斯特拉算法求单源最短路径

编写一个算法,采用迪杰斯特拉算法,输出如下图所示的有向带权图G 中从顶点a 到其他各顶点的最短路径长度和最短路径。图的存储结构自

选。

e c g

f a d b

15 2

源代码:

head.h:

#include

#include

#include //malloc( )

#include // INT ,MAX

#include //EOF,NULL

#include //atoi( )

#include //eof( )

#include //floor( ),ceil( ),abs( )

#include //exit( )

#include //cout,cin

//函数结果状态代码

#define TRUE 1

#define FALSE 0

#define OK 1

#define ERROR 0

#define INFEASIBLE -1

//OVERFLOW 在math.h 中已定义为3

typedef int Status;

typedef int Boolean; // 布尔类型

main.cpp:

#include"head.h"

#define MAX_NAME 5 /* 顶点字符串的最大长度+1 */

#define MAX_INFO 20 /* 相关信息字符串的最大长度+1 */

typedef int VRType;

typedef char InfoType;

typedef char VertexType[MAX_NAME];

/*图的数组(邻接矩阵)存储表示*/

#define INFINITY INT_MAX /* 用整型最大值代替∞*/

#define MAX_VERTEX_NUM 20 /* 最大顶点个数*/

typedef enum{DG,DN,AG,AN}GraphKind; /* {有向图,有向网,无向图,无向网} */ typedef struct

{

VRType adj; /* 顶点关系类型。对无权图,用1(是)或0(否)表示相邻否;*/ /* 对带权图,c则为权值类型*/

InfoType *info; /* 该弧相关信息的指针(可无) */

}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct

{

VertexType vexs[MAX_VERTEX_NUM]; /* 顶点向量*/

AdjMatrix arcs; /* 邻接矩阵*/

int vexnum,arcnum; /* 图的当前顶点数和弧数*/

GraphKind kind; /* 图的种类标志*/

}MGraph;

typedef int PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef int ShortPathTable[MAX_VERTEX_NUM];

int LocateVex(MGraph G,VertexType u)

{ /* 初始条件:图G存在,u和G中顶点有相同特征*/

/* 操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 */ int i;

for(i=0;i

if(strcmp(u,G.vexs[i])==0)

return i;

return -1;

}

Status CreateDN(MGraph *G)

{ /* 采用数组(邻接矩阵)表示法,构造有向网G */

int i,j,k,w;

VertexType va,vb;

printf("请输入有向网G的顶点数,弧数: ");

scanf("%d,%d",&(*G).vexnum,&(*G).arcnum);

printf("请输入%d个顶点的值(<%d个字符):\n",(*G).vexnum,MAX_NAME);

for(i=0;i<(*G).vexnum;++i) /* 构造顶点向量*/

scanf("%s",(*G).vexs[i]);

for(i=0;i<(*G).vexnum;++i) /* 初始化邻接矩阵*/

for(j=0;j<(*G).vexnum;++j)

{

(*G).arcs[i][j].adj=INFINITY; /* 网*/

}

printf("请输入%d条弧的弧尾弧头权值(以空格作为间隔): \n",(*G).arcnum);

for(k=0;k<(*G).arcnum;++k)

{

scanf("%s%s%d%*c",va,vb,&w); /* %*c吃掉回车符*/

i=LocateVex(*G,va);

j=LocateVex(*G,vb);

(*G).arcs[i][j].adj=w; /* 有向网*/

}

(*G).kind=DN;

return OK;

}

typedef int QElemType;

/*单链队列--队列的链式存储结构*/

typedef struct QNode

{

QElemType data;

struct QNode *next;

}QNode,*QueuePtr;

typedef struct

{

QueuePtr front,rear; /* 队头、队尾指针*/

}LinkQueue;

LinkQueue Q;

Status InitQueue(LinkQueue *Q)

{ /* 构造一个空队列Q */

(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));

if(!(*Q).front)

exit(OVERFLOW);

(*Q).front->next=NULL;

return OK;

}

Status QueueEmpty(LinkQueue Q)

{ /* 若Q为空队列,则返回TRUE,否则返回FALSE */

if(Q.front==Q.rear)

return TRUE;

else

return FALSE;

}

Status EnQueue(LinkQueue *Q,QElemType e)

{ /* 插入元素e为Q的新的队尾元素*/

QueuePtr p=(QueuePtr)malloc(sizeof(QNode));

if(!p) /* 存储分配失败*/

exit(OVERFLOW);

p->data=e;

p->next=NULL;

(*Q).rear->next=p;

(*Q).rear=p;

return OK;

}

Status DeQueue(LinkQueue *Q,QElemType *e)

{ /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */ QueuePtr p;

if((*Q).front==(*Q).rear)

return ERROR;

p=(*Q).front->next;

*e=p->data;

(*Q).front->next=p->next;

if((*Q).rear==p)

(*Q).rear=(*Q).front;

free(p);

return OK;

}

void ShortestPath_DIJ(MGraph G,int v0,PathMatrix *P,ShortPathTable *D)

{ /* 用Dijkstra算法求有向网G的v0顶点到其余顶点v的最短路径P[v]及带权长度*/ /* D[v]。若P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点。*/ /* final[v]为TRUE当且仅当v∈S,即已经求得从v0到v的最短路径算法7.15 */ int v,w,i,j,min;

Status final[MAX_VERTEX_NUM];

for(v=0;v

{

final[v]=FALSE;

(*D)[v]=G.arcs[v0][v].adj;

for(w=0;w

(*P)[v][w]=FALSE; /* 设空路径*/

if((*D)[v]

{

(*P)[v][v0]=TRUE;

(*P)[v][v]=TRUE;

}

}

(*D)[v0]=0;

final[v0]=TRUE; /* 初始化,v0顶点属于S集*/

for(i=1;i

{ /* 开始主循环,每次求得v0到某个v顶点的最短路径,并加v到S集*/

min=INFINITY; /* 当前所知离v0顶点的最近距离*/

for(w=0;w

if(!final[w]) /* w顶点在V-S中*/

if((*D)[w]

{

v=w;

min=(*D)[w];

} /* w顶点离v0顶点更近*/

final[v]=TRUE; /* 离v0顶点最近的v加入S集*/

EnQueue(&Q,v);

for(w=0;w

{

if(!final[w]&&min

{ /* 修改D[w]和P[w],w∈V-S */

(*D)[w]=min+G.arcs[v][w].adj;

for(j=0;j

(*P)[w][j]=(*P)[v][j];

(*P)[w][w]=TRUE;

}

}

}

}

void main()

{

InitQueue(&Q);

int i,j,e,v0=0; /* v0为源点*/

MGraph g;

PathMatrix p;

ShortPathTable d;

CreateDN(&g);

ShortestPath_DIJ(g,v0,&p,&d);

printf("最短路径数组p[i][j]如下:\n");

for(i=0;i

{

for(j=0;j

printf("%2d",p[i][j]);

printf("\n");

}

printf("%s到各顶点的最短路径长度为:\n",g.vexs[0]);

for(i=1;i

printf("%s-%s:%d\n",g.vexs[0],g.vexs[i],d[i]);

int t[6];//用来存放最短路径的终点的序号(来自队列Q)

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

DeQueue(&Q,&t[i]);

printf("%s到各顶点的最短路径为:\n",g.vexs[0]);

for(i=1;i

{

cout<

for(j=1;j

if(p[i][t[j-1]])

{

cout<

}

cout<

}

}

运行结果:

【小结或讨论】

(1)通过本次实验,掌握了最小生成树以及最短路径的相关概念,并且会实现Prim

算法、Kruskal算法以及Dijkstra算法。

(2)在实现Prim算法时需附设一个辅助数组closedge,以记录从U到V-U具有最小

代价的边。

(3)在实现Kruskal算法时为所有顶点附设一个数组Vset,标记各顶点所处的连通

分量,还附设了一个结构体变量存放各边的起点、终点和边的权值;在对各边

按权值大小进行排序时,采用的是堆排序,初始建的是大顶堆,最终排完序后

就是按边权值从小到大的有序序列。排序过程中注意双亲结点和左右孩子结点

的序号问题,因为序号是从0开始的,所以结点i的孩子结点是2*i+1。

(4)在实现Dijkstra算法时附设了二维数组P记录从V0到各顶点的最短路径上包含

的顶点,用数组D记录各最短路径的长度,此外还附设了一个队列Q,将每次

找到的最短路径的终点入队,最后输出最短路径时根据当时入队的顺序依次输

出,这里队列可以用一维数组代替,用队列可以更好地体现算法的思想。

(5)从时间复杂度上看,Prim算法的时间复杂度为O(n^2),与边数无关,适用于求

边稠密的网的最小生成树;Kruskal算法的时间复杂度为O(eloge)(e为网中边的

数目),适用于边稀疏的网的最小生成树。Dijkstra算法的时间复杂度为O(n^2)。

数据结构课程实验指导书

数据结构实验指导书 一、实验目的 《数据结构》是计算机学科一门重要的专业基础课程,也是计算机学科的一门核心课程。本课程较为系统地论述了软件设计中常用的数据结构以及相应的存储结构与实现算法,并做了相应的性能分析和比较,课程内容丰富,理论系统。本课程的学习将为后续课程的学习以及软件设计水平的提高打下良好的基础。 由于以下原因,使得掌握这门课程具有较大的难度: 1)理论艰深,方法灵活,给学习带来困难; 2)内容丰富,涉及的知识较多,学习有一定的难度; 3)侧重于知识的实际应用,要求学生有较好的思维以及较强的分析和解决问题的能力,因而加大了学习的难度; 根据《数据结构》课程本身的特性,通过实验实践内容的训练,突出构造性思维训练的特征,目的是提高学生分析问题,组织数据及设计大型软件的能力。 课程上机实验的目的,不仅仅是验证教材和讲课的内容,检查自己所编的程序是否正确,课程安排的上机实验的目的可以概括为如下几个方面: (1)加深对课堂讲授内容的理解 实验是对学生的一种全面综合训练。是与课堂听讲、自学和练习相辅相成的必不可少的一个教学环节。通常,实验题中的问题比平时的习题复杂得多,也更接近实际。实验着眼于原理与应用的结合点,使学生学会如何把书上学到的知识用于解决实际问题,培养软件工作所需要的动手能力;另一方面,能使书上的知识变" 活" ,起到深化理解和灵活掌握教学内容的目的。 不少学生在解答习题尤其是算法设计时,觉得无从下手。实验中的内容和教科书的内容是密切相关的,解决题目要求所需的各种技术大多可从教科书中找到,只不过其出

现的形式呈多样化,因此需要仔细体会,在反复实践的过程中才能掌握。 (2) 培养学生软件设计的综合能力 平时的练习较偏重于如何编写功能单一的" 小" 算法,而实验题是软件设计的综合训练,包括问题分析、总体结构设计、用户界面设计、程序设计基本技能和技巧,多人合作,以至一整套软件工作规范的训练和科学作风的培养。 通过实验使学生不仅能够深化理解教学内容,进一步提高灵活运用数据结构、算法和程序设计技术的能力,而且可以在需求分析、总体结构设计、算法设计、程序设计、上机操作及程序调试等基本技能方面受到综合训练。实验着眼于原理与应用的结合点,使学生学会如何把书本上和课堂上学到的知识用于解决实际问题,从而培养计算机软件工作所需要的动手能力。 (3) 熟悉程序开发环境,学习上机调试程序一个程序从编辑,编译,连接到运行,都要在一定的外部操作环境下才能进行。所谓" 环境" 就是所用的计算机系统硬件,软件条件,只有学会使用这些环境,才能进行 程序开发工作。通过上机实验,熟练地掌握程序的开发环境,为以后真正编写计算机程序解决实际问题打下基础。同时,在今后遇到其它开发环境时就会触类旁通,很快掌握新系统的使用。 完成程序的编写,决不意味着万事大吉。你认为万无一失的程序,实际上机运行时可能不断出现麻烦。如编译程序检测出一大堆语法错误。有时程序本身不存在语法错误,也能够顺利运行,但是运行结果显然是错误的。开发环境所提供的编译系统无法发现这种程序逻辑错误,只能靠自己的上机经验分析判断错误所在。程序的调试是一个技巧性很强的工作,尽快掌握程序调试方法是非常重要的。分析问题,选择算法,编好程序,只能说完成一半工作,另一半工作就是调试程序,运行程序并得到正确结果。 二、实验要求 常用的软件开发方法,是将软件开发过程划分为分析、设计、实现和维护四个阶段。虽然数据结构课程中的实验题目的远不如从实际问题中的复杂程度度高,但为了培养一个软件工作者所应具备的科学工作的方法和作风,也应遵循以下五个步骤来完成实验题目: 1) 问题分析和任务定义 在进行设计之前,首先应该充分地分析和理解问题,明确问题要求做什么?限制条件是什么。本步骤强调的是做什么?而不是怎么做。对问题的描述应避开算法和所涉及的数据类型,而是对所需完成的任务作出明确的回答。例如:输入数据的类型、值的范围以及输入的

用Prim算法构造最小生成树

用Prim算法构造最小生成树 班级:2010级计算机1班学号:2010131116 姓名:杨才一、实验目的 了解最小生成树的概念,掌握生成最小生成树的方法。 二、实验内容 建立一个含任意结点的无向连通网,并用Prim算法构造其最小生成树 三、实验要点及说明 如果无向连通图是一个网,则其所有生成树中必有一棵树的边的权值总和最小,这棵生成树为最小生成树。 Prim算法:在图G=(V,E)(V为顶点集,E为边集)中任选一顶点v0,令集合U={v0}为初态,在一个顶点在U中,另一顶点在V-U 中的所有边中找权值最小的边(u,v)(U∈ u,v∈ V-U),并将v加入到U中,同时将边(u,v)加入集合T中(T的初态为空集),这样不断地扩大U,直至U=V,则集合T中的边为所求最小生成树的边 四、算法思想与算法描述 1、邻接矩阵的数据类型的定义如下: typedef struct { int no; /*顶点编号*/ string name; /*顶点其他信息*/ } VertexType; /*顶点类型*/ typedef struct/*图的定义*/ { int edges[MAXV][MAXV]; /*邻接矩阵*/ int vexnum,arcnum; /*顶点数,弧数*/ VertexType vexs[MAXV]; /*存放顶点信息*/ }MGraph; 2、临时数组的存放的数据类型 struct { int closest; // U集中的顶点序号 int lowcost; // 边的权值 } closedge[MAXV]; int const INF=32767; /*INF表示∞*/ 3、prime算法实现:(原理见实验说明) void prime(MGraph g,int v) { int lowcost[MAXV]; int min; int closest[MAXV]; int i,j,k; for(i=0;i

数据结构二叉树实验报告

实验三二叉树的遍历 一、实验目的 1、熟悉二叉树的结点类型和二叉树的基本操作。 2、掌握二叉树的前序、中序和后序遍历的算法。 3、加深对二叉树的理解,逐步培养解决实际问题的编程能力。 二、实验环境 运行C或VC++的微机。 三、实验内容 1、依次输入元素值,以链表方式建立二叉树,并输出结点的值。 2、分别以前序、中序和后序遍历二叉树的方式输出结点内容。 四、设计思路 1. 对于这道题,我的设计思路是先做好各个分部函数,然后在主函数中进行顺序排列,以此完成实验要求 2.二叉树采用动态数组 3.二叉树运用9个函数,主要有主函数、构建空二叉树函数、建立二叉树函数、访问节点函数、销毁二叉树函数、先序函数、中序函数、后序函数、范例函数,关键在于访问节点 五、程序代码 #include #include #include #define OK 1 #define ERROR 0 typedef struct TNode//结构体定义 {

int data; //数据域 struct TNode *lchild,*rchild; // 指针域包括左右孩子指针 }TNode,*Tree; void CreateT(Tree *T)//创建二叉树按,依次输入二叉树中结点的值 { int a; scanf("%d",&a); if(a==00) // 结点的值为空 *T=NULL; else // 结点的值不为空 { *T=(Tree)malloc(sizeof(TNode)); if(!T) { printf("分配空间失败!!TAT"); exit(ERROR); } (*T)->data=a; CreateT(&((*T)->lchild)); // 递归调用函数,构造左子树 CreateT(&((*T)->rchild)); // 递归调用函数,构造右子树 } } void InitT(Tree *T)//构建空二叉树 { T=NULL; } void DestroyT(Tree *T)//销毁二叉树 { if(*T) // 二叉树非空 { DestroyT(&((*T)->lchild)); // 递归调用函数,销毁左子树 DestroyT(&((*T)->rchild)); // 递归调用函数,销毁右子树 free(T); T=NULL; } } void visit(int e)//访问结点 { printf("%d ",e); }

数据结构实验报告代码

线性表 代码一 #include "stdio.h" #include "malloc.h" #define OK 1 #define ERROR 0 #define OVERFLOW -2 #define LIST_INIT_SIZE 100 #define LISTINCREMENT 10 typedef struct { int * elem; int length; int listsize; }SqList; int InitList_Sq(SqList *L) { L->elem = (int*)malloc(LIST_INIT_SIZE*sizeof(int)); if (!L->elem) return ERROR; L->length = 0; L->listsize = LIST_INIT_SIZE; return OK; } int ListInsert_Sq(SqList *L, int i,int e) { int *p,*newbase,*q; if (i < 1 || i > L->length+1) return ERROR; if (L->length >= L->listsize) { newbase = (int *)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof (int)); if (!newbase) return ERROR; L->elem = newbase; L->listsize += LISTINCREMENT; } q = &(L->elem[i-1]); //插入后元素后移for(p=&(L->elem[L->length-1]);p>=q;p--) *(p+1)=*p; *q=e; L->length++; return OK; } int ListDelete_Sq(SqList *L, int i, int *e) {

数据结构实验一的源代码

#include #include typedef struct Node { int key;//密码 int num;//编号 struct Node *next;//指向下一个节点 } Node, *Link; void InitList(Link &L) //创建一个空的链表{ L = (Node *)malloc(sizeof(Node)); if (!L) exit(1); L->key = 0; L->num = 0; L->next = L; } void Creatlinklist(int n, Link &L) //初始化链表{ Link p, q; q = L; for (int i = 1; i <= n; i++) { p = (Node *)malloc(sizeof(Node)); if (!p) exit(1); scanf("%d", &p->key); p->num = i; L->next = p; L = p; } L->next = q->next; free(q); } Link Locate_m(Link &p, int m)//找到第m个 { Link q; for (int j = 1; jnext; q = p->next; m = q->key;

return q; } void Delete_m(Link &L, Link p, Link q)//删除第m个{ p->next = q->next; free(q); } void main() { Link L, p, q; int n, m; L = NULL; InitList(L);//构造出一个只有头结点的空链表 printf("请输入初始密码人数每个人的密码:\n"); scanf("%d", &m);//初始密码为m scanf("%d", &n);// Creatlinklist(n, L);//构建 p = L; for (int i = 1; i <= n; i++) { q = Locate_m(p, m);//找到第m个 printf("%d", q->num); Delete_m(L, p, q);//删除第m个 } system("pause"); }

数据结构实验报告-二叉树的实现与遍历

《数据结构》第六次实验报告 学生姓名 学生班级 学生学号 指导老师

一、实验内容 1) 采用二叉树链表作为存储结构,完成二叉树的建立,先序、中序和后序 以及按层次遍历的操作,求所有叶子及结点总数的操作。 2) 输出树的深度,最大元,最小元。 二、需求分析 遍历二叉树首先有三种方法,即先序遍历,中序遍历和后序遍历。 递归方法比较简单,首先获得结点指针如果指针不为空,且有左子,从左子递归到下一层,如果没有左子,从右子递归到下一层,如果指针为空,则结束一层递归调用。直到递归全部结束。 下面重点来讲述非递归方法: 首先介绍先序遍历: 先序遍历的顺序是根左右,也就是说先访问根结点然后访问其左子再然后访问其右子。具体算法实现如下:如果结点的指针不为空,结点指针入栈,输出相应结点的数据,同时指针指向其左子,如果结点的指针为空,表示左子树访问结束,栈顶结点指针出栈,指针指向其右子,对其右子树进行访问,如此循环,直至结点指针和栈均为空时,遍历结束。 再次介绍中序遍历: 中序遍历的顺序是左根右,中序遍历和先序遍历思想差不多,只是打印顺序稍有变化。具体实现算法如下:如果结点指针不为空,结点入栈,指针指向其左子,如果指针为空,表示左子树访问完成,则栈顶结点指针出栈,并输出相应结点的数据,同时指针指向其右子,对其右子树进行访问。如此循环直至结点指针和栈均为空,遍历结束。 最后介绍后序遍历: 后序遍历的顺序是左右根,后序遍历是比较难的一种,首先需要建立两个栈,一个用来存放结点的指针,另一个存放标志位,也是首先访问根结点,如果结点的指针不为空,根结点入栈,与之对应的标志位也随之入标志位栈,并赋值0,表示该结点的右子还没有访问,指针指向该结点的左子,如果结点指针为空,表示左子访问完成,父结点出栈,与之对应的标志位也随之出栈,如果相应的标志位值为0,表示右子树还没有访问,指针指向其右子,父结点再次入栈,与之对应的标志位也入栈,但要给标志位赋值为1,表示右子访问过。如果相应的标志位值为1,表示右子树已经访问完成,此时要输出相应结点的数据,同时将结点指针赋值为空,如此循环直至结点指针和栈均为空,遍历结束。 三、详细设计 源代码:

数据结构实验程序

顺序表的基本操作 #include using namespace std; typedef int datatype; #define maxsize 1024 #define NULL -1 typedef struct { datatype *data; int last; }sequenlist; void SETNULL(sequenlist &L) { L.data=new datatype[maxsize]; for(int i=0;i>https://www.360docs.net/doc/be18853780.html,st; cout<<"请输入"<>L.data[i]; } int LENGTH(sequenlist &L) { int i=0; while(L.data[i]!=NULL) i++; return i; } datatype GET(sequenlist &L,int i) { if(i<1||i>https://www.360docs.net/doc/be18853780.html,st) { cout<<"error1"<

int j=0; while(L.data[j]!=x) j++; if(j==https://www.360docs.net/doc/be18853780.html,st) { cout<<"所查找值不存在!"<=maxsize-1) { cout<<"overflow"; return NULL; } else if(i<1||(i>https://www.360docs.net/doc/be18853780.html,st)) { cout<<"error2"<=i-1;j--) L.data[j+1]=L.data[j]; L.data[i-1]=x; https://www.360docs.net/doc/be18853780.html,st++; } return 1; } int DELETE(sequenlist &L,int i) { int j; if((i<1)||(i>https://www.360docs.net/doc/be18853780.html,st+1)) { cout<<"error3"<

最小生成树模型与实验

最小生成树模型与实验

第六章 最小生成树模型与实验 树是图论中的一个重要概念,由于树的模型简单而实用,它在企业管理、线路设计等方面都有很重要的应用。 §6.1树与树的性质 上章已讨论了图和树的简单基本性质。为使更清楚明了,现在使用实例来说明。 例6.1 已知有五个城市,要在它们之 间架设电话线,要求任何两个城市都可以互相 通话(允许通过其它城市),并且电话线的根 数最少。 用五个点54321,,,,v v v v v 代表五个城市,如果 在某两个城市之间架设电话线,则在相应的两个点之间联一条边,这样一个电话线网就可以用一个图来表示。为了任何两个城市都可以通话,这样的图必须是连通的。其次,若图中有圈的话,从圈上任意去掉一条边,余下的图仍是连通的,这样可以省去一根电话线。因而,满足要求的电话线网所对应的图必定是不含圈的连通图。图6.1的表达式满足要求的一个电话线网。 定义6.1 一个无圈的连通图称为树. 例6.2 某大学的组织机构如下所示: v 5v 4v 图

教务处 研究处 校行政办公室 研究生院 财务科 行政科 理工学院 人事学院 外语学院 …… 如果用图表示,该工厂的组织机构图就是一个树。上章给出了一些树的性质,为使能进一步研究这部分知识,先再列出常用一些树和生成树的性质。 树的性质: (1) 树必连通,但无回路(圈); (2) n 个顶点的树必有1-n 条边; (3) 树中任意两点间,恰有一条初等链; (4) 树连通,但去掉任一条边,必变为不连通; (5) 树无回路(圈),但不相邻顶点连一条边,恰得一回路(圈)。 生成树与最小树 定义6.2 设图),(11E V G =是图},{E V G =的生成子图,如果1G 是一棵树,记),(1E V T =,则称T 是G 的一棵生成树。 定理6.1 图G 有生成树的充分必要条件是图G 的连通的。 数学物理文科 理校教学校长

数据结构实验-二叉树的操作

******************************* 实验题目:二叉树的操作 实验者信息:班级13007102,姓名庞文正,学号1300710226 实验完成的时间3:00 ****************************** 一、实验目的 1,掌握二叉树链表的结构和二叉树的建立过程。 2,掌握队列的先进先出的运算原则在解决实际问题中的应用。 3,进一步掌握指针变量、指针数组、动态变量的含义。 4,掌握递归程序设计的特点和编程方法。 二、实验内容 已知以二叉链表作存储结构,试编写按层次遍历二叉树的算法。(所谓层次遍历,是指从二叉树的根结点开始从上到下逐层遍历二叉树,在同一层次中从左到右依次访问各个节点。)调试程序并对相应的输出作出分析;修改输入数据,预期输出并验证输出的结果。加深对算法的理解。 三、算法设计与编码 1.本实验用到的理论知识 总结本实验用到的理论知识,实现理论与实践相结合。总结尽量简明扼要,并与本次实验密切相关,最好能加上自己的解释。 本算法要采用一个循环队列que,先将二叉树根结点入队列,然后退队列,输出该结点;若它有左子树,便将左子树根结点入队列;若它有右子树,便将右子树根结点入队列,直到队列空为止。因为队列的特点是先进先出,从而达到按层次顺序遍历二叉的目的。2.算法概要设计 给出实验的数据结构描述,程序模块、功能及调用关系 #include #include #define M 100 typedef struct node //二叉链表节点结构 {int data; //数据域 struct node *lchild,*rchild; //左孩子右孩子链 }bitree; bitree *que[M]; //定义一个指针数组,说明队列中的元素bitree 指针类型 int front=0, rear=0; //初始化循环列队 bitree *creat() //建立二叉树的递归算法 {bitree *t; int x; scanf("%d",&x); if(x==0) t=NULL; //以x=0 表示输入结束 else {t=malloc(sizeof(bitree)); //动态生成节点t,分别给节点t 的数据域,t->data=x; //左右孩子域赋值,给左右孩子赋值时用到 t->lchild=creat(); // 了递归思想 t->rchild=creat(); }

数据结构实验报告全集

数据结构实验报告全集 实验一线性表基本操作和简单程序 1.实验目的 (1)掌握使用Visual C++ 上机调试程序的基本方法; (2)掌握线性表的基本操作:初始化、插入、删除、取数据元素等运算在顺序存储结构和链表存储结构上的程序设计方法。 2.实验要求 (1)认真阅读和掌握和本实验相关的教材内容。 (2)认真阅读和掌握本章相关内容的程序。 (3)上机运行程序。 (4)保存和打印出程序的运行结果,并结合程序进行分析。 (5)按照你对线性表的操作需要,重新改写主程序并运行,打印出文件清单和运行结果 实验代码: 1)头文件模块 #include >验目的 掌握顺序栈的基本操作:初始化栈、判栈空否、入栈、出栈、取栈顶数据元素等运算以及程序实现方法。 2.实验要求 (1)认真阅读和掌握和本实验相关的教材内容。 (2)分析问题的要求,编写和调试完成程序。 (3)保存和打印出程序的运行结果,并分析程序的运行结果。 3.实验内容 利用栈的基本操作实现一个判断算术表达式中包含圆括号、方括号是否正确配对的程序。具体完成如下:

(1)定义栈的顺序存取结构。 (2)分别定义顺序栈的基本操作(初始化栈、判栈空否、入栈、出栈等)。 (3)定义一个函数用来判断算术表达式中包含圆括号、方括号是否正确配对。其中,括号配对共有四种情况:左右括号配对次序不正确;右括号多于左括号;左括号多于右括号;左右括号匹配正确。 (4)设计一个测试主函数进行测试。 (5)对程序的运行结果进行分析。 实验代码: #include < > #define MaxSize 100 typedef struct { ??? int data[MaxSize]; ??? int top; }SqStack; void InitStack(SqStack *st) 验目的 (1)进一步掌握指针变量的用途和程序设计方法。 (2)掌握二叉树的结构特征,以及链式存储结构的特点及程序设计方法。 (3)掌握构造二叉树的基本方法。 (4)掌握二叉树遍历算法的设计方法。 3.实验要求 (1)认真阅读和掌握和本实验相关的教材内容。 (2)掌握一个实际二叉树的创建方法。 (3)掌握二叉链存储结构下二叉树操作的设计方法和遍历操作设计方法。 4.实验内容 (1)定义二叉链存储结构。

数据结构实验报告之树与二叉树

学生实验报告 学院:软通学院 课程名称:数据结构与算法 专业班级:软件142 班 姓名:邹洁蒙 学号: 0143990

学生实验报告 (二) 一、实验综述 1、实验目的及要求 目的:1)掌握树与二叉树的基本概念; 2)掌握二叉树的顺序存储,二叉链表的先序遍历中序遍历和后序遍历算法; 3)掌握树的双亲表示法。 要求:1)编程:二叉树的顺序存储实现; 2)编程:二叉链表的先序遍历中序遍历和后序遍历实现; 3)编程:树的双亲表示法实现。 2、实验仪器、设备或软件 设备:PC 软件:VC6 二、实验过程(编程,调试,运行;请写上源码,要求要有注释) 1.编程:二叉树的顺序存储实现 代码: BiTree::BiTree()//建立存储空间 { data = new int[MAXSIZE]; count = 0; } void BiTree::AddNode(int e)//加结点 { int temp = 0; data[count] = e; count++;//从编号0开始保存 }

运行截图: 2.编程:二叉链表的先序遍历中序遍历和后序遍历实现代码: void InOrderTraverse(BiTree* Head)//中序遍历 { if (Head) { InOrderTraverse(Head->LeftChild); cout << Head->data<<" "; InOrderTraverse(Head->RightChild); } } void PreOrderTraverse(BiTree* Head)//先序遍历 { if (Head) { cout << Head->data << " "; PreOrderTraverse(Head->LeftChild); PreOrderTraverse(Head->RightChild); } } void PostOrderTraverse(BiTree* Head)//后序遍历 { if (Head) { PostOrderTraverse(Head->LeftChild); PostOrderTraverse(Head->RightChild); cout << Head->data << " "; } } 运行截图:

数据结构上机实验线性表单链表源代码

#include template class LinearList { public: virtual bool IsEmpty()const=0; virtual int Length()const=0; virtual bool Find(int i,T& x)const=0; virtual int Search(T x)const=0; virtual bool Insert(int i,T x)=0; virtual bool Update(int i,T x)=0; virtual bool Delete(int i)=0; virtual void Output(ostream& out)const=0; protected: int n; }; #include "linearlist" template class SeqList:public LinearLisr { public: SeqList(int mSize); ~SeqList(){delete [] elements;} bool IsEmpty()const; bool Find(int i,T& x)const; int Length()const; int Search(T x)const; bool Insert(int i,T x); bool Update(int i,T x); bool Delete(int i); void Output(ostream& out)const; private: int maxLength; T *elements; }; template SeqList::SeqList(int mSize) { maxLength=mSize;

数据结构课程设计报告(最小生成树完整版)

武 夷 学 院 课程设计报告 课程名称: 数据结构 设计题目: 最小生成树的应用 学生班级: 09计科2班 学生姓名: 蒋家权,陈相财,吴继伟,梁丽春 指导教师: 林丽惠 完成日期: 2011-1-19

课程设计项目研究报告 目录 一、问题分析和任务定义....................................................................................... - 1 - 二、实现本程序需要解决的问题如下................................................................... - 1 - 三、测试数据........................................................................................................... - 2 - 四、算法思想........................................................................................................... - 3 - 五、模块划分........................................................................................................... - 4 - 六、算法设计与分析............................................................................................... - 7 - 七、源程序............................................................................................................. - 11 - 八、测试数据......................................................................................................... - 14 - 九、课程设计项目进度表及任务分配表及任务分配表..................................... - 16 - 十、设计心得......................................................................................................... - 17 -十、参考书目......................................................................................................... - 18 -

数据结构实验报告—二叉树

算法与数据结构》课程实验报告

一、实验目的 1、实现二叉树的存储结构 2、熟悉二叉树基本术语的含义 3、掌握二叉树相关操作的具体实现方法 二、实验内容及要求 1. 建立二叉树 2. 计算结点所在的层次 3. 统计结点数量和叶结点数量 4. 计算二叉树的高度 5. 计算结点的度 6. 找结点的双亲和子女 7. 二叉树前序、中序、后序遍历的递归实现和非递归实现及层次遍历 8. 二叉树的复制 9. 二叉树的输出等 三、系统分析 (1)数据方面:该二叉树数据元素采用字符char 型,并且约定“ #”作为二叉树输入结束标识符。并在此基础上进行二叉树相关操作。 (2)功能方面:能够实现二叉树的一些基本操作,主要包括: 1. 采用广义表建立二叉树。 2. 计算二叉树高度、统计结点数量、叶节点数量、计算每个结点的度、结点所在层次。 3. 判断结点是否存在二叉树中。 4. 寻找结点父结点、子女结点。 5. 递归、非递归两种方式输出二叉树前序、中序、后序遍历。 6. 进行二叉树的复制。 四、系统设计 (1)设计的主要思路 二叉树是的结点是一个有限集合,该集合或者为空,或者是由一个根节点加上两棵分别称为左子树和右子树、互不相交的二叉树组成。根据实验要求,以及课上老师对于二叉树存储结构、基本应用的讲解,同时课后研究书中涉及二叉树代码完成二叉树模板类,并将所需实现各个功能代码编写完成,在建立菜单对功能进行调试。 (2)数据结构的设计 二叉树的存储结构有数组方式和链表方式。但用数组来存储二叉树有可能会消耗大量的存储空间,故在此选用链表存储,提高存储空间的利用率。根据二叉树的定义,二叉

数据结构实验(七种排序算法的实现)题目和源程序

1、直接插入排序 2、希尔排序 3、2-路归并排序 4、折半插入排序 5、冒泡排序 6、快速排序 7、堆排序 /*---------------------------------------- * 07_排序.cpp -- 排序的相关操作 * 对排序的每个基本操作都用单独的函数来实现 * 水上飘2011年写 ----------------------------------------*/ // ds07.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "stdio.h" #include #include using namespace std; #define MAXSIZE 20 typedefintKeyType; typedefstruct{ KeyType key; //关键字项 KeyType data; //数据项 }RedType; //记录类型 typedefstruct{ RedTypearr[MAXSIZE+1]; //arr[0]闲置或用作哨兵单元int length; //顺序表长度 }SqList; //顺序表类型typedefSqListHeapType; //对顺序表L做一趟希尔插入排序 //前后记录位置的增量是dk //r[0]只是暂存单元 //当j<=0时,插入位置已找到 voidshellInsert(SqList&L, intdk) {

int i, j; for (i = dk + 1; i <= L.length; i++) { if (L.arr[i].key 0 &&L.arr[0].key = high + 1; j--) L.arr[j + 1] = L.arr[j];//记录后移 L.arr[high + 1] = L.arr[0];//插入 }//for }//BInsertSort //直接插入排序

数据结构实验二叉树

实验六:二叉树及其应用 一、实验目的 树是数据结构中应用极为广泛的非线性结构,本单元的实验达到熟悉二叉树的存储结构的特性,以及如何应用树结构解决具体问题。 二、问题描述 首先,掌握二叉树的各种存储结构和熟悉对二叉树的基本操作。其次,以二叉树表示算术表达式的基础上,设计一个十进制的四则运算的计算器。 如算术表达式:a+b*(c-d)-e/f 三、实验要求 如果利用完全二叉树的性质和二叉链表结构建立一棵二叉树,分别计算统计叶子结点的个数。求二叉树的深度。十进制的四则运算的计算器可以接收用户来自键盘的输入。由输入的表达式字符串动态生成算术表达式所对应的二叉树。自动完成求值运算和输出结果。四、实验环境 PC微机 DOS操作系统或 Windows 操作系统 Turbo C 程序集成环境或 Visual C++ 程序集成环境 五、实验步骤 1、根据二叉树的各种存储结构建立二叉树; 2、设计求叶子结点个数算法和树的深度算法; 3、根据表达式建立相应的二叉树,生成表达式树的模块; 4、根据表达式树,求出表达式值,生成求值模块; 5、程序运行效果,测试数据分析算法。 六、测试数据 1、输入数据:2.2*(3.1+1.20)-7.5/3 正确结果:6.96 2、输入数据:(1+2)*3+(5+6*7); 正确输出:56 七、表达式求值 由于表达式求值算法较为复杂,所以单独列出来加以分析: 1、主要思路:由于操作数是任意的实数,所以必须将原始的中缀表达式中的操作数、操作符以及括号分解出来,并以字符串的形式保存;然后再将其转换为后缀表达式的顺序,后缀表达式可以很容易地利用堆栈计算出表达式的值。 例如有如下的中缀表达式: a+b-c 转换成后缀表达式为: ab+c- 然后分别按从左到右放入栈中,如果碰到操作符就从栈中弹出两个操作数进行运算,最后再将运算结果放入栈中,依次进行直到表达式结束。如上述的后缀表达式先将a 和b 放入栈中,然后碰到操作符“+”,则从栈中弹出a 和b 进行a+b 的运算,并将其结果d(假设为d)放入栈中,然后再将c 放入栈中,最后是操作符“-”,所以再弹出d和c 进行d-c 运算,并将其结果再次放入栈中,此时表达式结束,则栈中的元素值就是该表达式最后的运算结果。当然将原始的中缀表达式转换为后缀表达式比较关键,要同时考虑操作符的优先级以及对有括号的情况下的处理,相关内容会在算法具体实现中详细讨论。

数据结构上机实验源文件

数据结构 第一、二次上机:#include #include #include #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 #define list_init_size 100 //线性表存储空间的初始分配量 #define LISTINCREMENT 10 //线性表存储空间的分配增量 typedef int Status; typedef intElemType; typedef struct{ ElemType *elem; //存储空间基址int length; //当前长度intlistsize; //当前分配的存储容量(以sizeof(ElemType)为单位)}SqList;

Status InitList_Sq(SqList&L){ //构造一个空的线性表L L.elem =(ElemType * )malloc(list_init_size*sizeof(ElemType)); if(!L.elem )exit(OVERFLOW);//存储分配失败L.length =0; //空表长度为0 L.listsize =list_init_size;//初始存储容量return OK; }//Initlist_Sq Status ListInsert_Sq(SqList&L,inti,ElemType e){ //在顺序线性表L中第i个位置之前插入新的元素e,//i的合法值为1<=i<=ListLength_Sq(L)+1 ElemType *p,*q,*newbase; //定义指针if(i<1||i>L.length +1) return ERROR; //i值不合法if(L.length>=L.listsize ){ //当前存储空间已满,增加分配newbase=(ElemType * )realloc(L.elem ,(L.listsize

最小生成树的算法

最小生成树的算法 王洁 引言: 求连通图的最小生成树是数据结构中讨论的一个重要问题.在现实生活中,经常遇到如何得到连通图的最小生成树,求最小生成树不仅是图论的基本问题之一 ,在实际工作中也有很重要的意义,,人们总想寻找最经济的方法将一个终端集合通过某种方式将其连接起来 ,比如将多个城市连为公路网络 ,要设计最短的公路路线;为了解决若干居民点供水问题 ,要设计最短的自来水管路线等.而避开这些问题的实际意义 ,抓住它们的数学本质 ,就表现为最小生成树的构造。下面将介绍几种最小生成树的算法。 一,用“破圈法”求全部最小生成树的算法 1 理论根据 1.1 约化原则 给定一无向连通图 G =(V ,E )( V 表示顶点,E 表示边),其中 V={ 1v , 2v ,3v …… n v },E= { 1e , 2e , 3e …… n e }对于 G 中的每条边 e ∈ E 都赋予权ω(i e )>0,求生成树 T = (V ,H ),H ? E ,使生成树所有边权最小,此生成树称为最小生成树. (1) 基本回路 将属于生成树 T 中的边称为树枝,树枝数为n -1,不属于生成树的边称为连枝.将任一连枝加到生成树上后都会形成一条回路.把这种回路称为基本回路,记为()cf e 。 基本回路是由 T 中的树枝和一条连枝构成的回路. (2) 基本割集 设无向图 G 的割集 S (割集是把连通图分成两个分离部分的最少支路集合) ,若 S 中仅包含有T 中的一条树枝,则称此割集为基本割集,记为()S e 。 基本割集是集合中的元素只有一条是树枝,其他的为连枝. (3) 等长变换 设T=(V,H),为一棵生成树,e ∈ H, 'e ∈ E, 'e ? H,当且仅当'e ∈()cf e ,也就是说 e ∈()S e ,则'T =T ⊕{e, ' e }也是一棵生成树。当()e ω='()e ω时,这棵生成树叫做等长变换。 等长变换就是从基本回路中选取与树枝等权边,并与此树枝对换后形成的生成树. 根据以上定理得出2个结论:①若在某个回路C 中有一条唯一的最长边,则任何一棵最小生成树都不含这条边;②若在某个边 e 的割集中有一条唯一最短边,则每棵生成树中都必须含这条边.由上面结论可以得到唯一性:若图 G 中的生成树T = (V ,H )是唯一的一棵最小生成树,当且仅当任意一连枝e ∈ H, ' e ∈ E 都是其基本回路中唯一最长边,任意一条树边 e 都是其基本割集()S e 中的唯一最短边.

相关文档
最新文档