- 浏览: 2049915 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (795)
- java (263)
- 聚类搜索引擎 (9)
- 经验之谈 (67)
- DSP (3)
- C++ (140)
- Linux (37)
- SNMP (6)
- Python (6)
- 数据库 (61)
- 网络 (20)
- 算法 (15)
- 设计模式 (4)
- 笔试题 (38)
- 散文 (35)
- 数据结构 (9)
- 银行知识 (0)
- 榜样 (9)
- Lucene (15)
- Heritrix (6)
- MetaSeeker (0)
- netbeans (12)
- php (3)
- 英语 (8)
- DB2 (0)
- java基础 (5)
- mongodb & hadoop (4)
- Javascript (7)
- Spring (4)
- ibatis & myibatis (1)
- velocity (1)
- 微服务 (0)
- paddle (1)
- 第三方 (0)
- 知识沉淀 (1)
- 建模 (0)
最新评论
-
0372:
标示对java很陌生!
中文乱码解决的4种方式 -
梦留心痕:
Java中\是转意字符, 可是你的这句话我没看懂,只要把得到的 ...
java中如何忽略字符串中的转义字符--转载 -
yanjianpengit:
[b][/b]
java为什么非静态内部类里面不能有静态成员 -
springdata-jpa:
可以参考最新的文档:如何在eclipse jee中检出项目并转 ...
eclipse 如何把java项目转成web项目 -
qq1130127172:
,非常好。
(转)SpringMVC 基于注解的Controller @RequestMapping @RequestParam..
*********************************************************************************************************
*
* 程序完成的功能:输入并建立无向图的邻接矩阵,
* 用 Prim 算法、Kruskal 算法以及去边法生成该图的最小代价生成树
*
* 作者:郭赞
*
* 完成时间:2008年11月15日
*
* 程序说明:最大顶点数目初始为 10
* 可选择自动生成邻接矩阵,也可自己输入
* 一个顶点和自己之间的权值为 0
* 没有直接连接的顶点之间的权值为 无穷大,即所能允许的最大值 Max_Num
*
***********************************************************************************************************
#include <iostream>
#include <iomanip>
#include <cstdlib>
using namespace std;
#define Max_Size 10 //最大允许的顶点个数
#define Max_Num 65535 //系统允许的最大数
#define Wid 6 //输出数据的宽度
typedef char ElemType; //顶点的数据类型
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
边的基本定义,w 为权值 *
typedef struct ArcCell{
int w;
} Arc, AdjMatrix[ Max_Size ][ Max_Size ];
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
对图的定义,vex[]中存储顶点,VexNum、ArcNum为顶点个数和边的条数*
typedef struct {
ElemType Vex[ Max_Size ];
AdjMatrix Arcs;
int VexNum;
int ArcNum;
} Graph;
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
对边集数组的定义,在 prim算法,及去边法 del中使用 *
typedef struct {
int fromvex;
int endvex;
int weight;
} Edge;
************************************************************
各函数的函数头
************************************************************
int CreatUDN ( Graph &G ); //建立邻接矩阵
void AutoCreat ( Graph &G ); //建立默认邻接矩阵
int LocatVex ( Graph G, ElemType V ); //确定顶点在Vex[]中的位置
void OutPut ( Graph G ); //输出邻接矩阵中的各条边
int GetChoice (); //输入选择
void Prim ( Graph G );
void Kru ( Graph G );
void Del ( Graph G ); //去边法
int SortEdge ( Graph G, Edge sort[] );
int Findpath ( Edge e[], int len, int from, int end , int mark );
void copy ( Edge hold[], Edge S[], int len);
*******************************************************************************
主函数,实现程序功能
*******************************************************************************
int main()
{
Graph G;
int choice = 0;
if ( !CreatUDN ( G ) ) {
cout << "创建邻接矩阵失败" <<endl;
return 1;
}
OutPut ( G );
while( choice != 4) {
switch ( choice = GetChoice () ) {
case 1 : Prim ( G ); break;
case 2 : Kru ( G ); break;
case 3 : Del ( G ); break;
case 4 : break;
default :
cout << "错误的选择!!!\a" <<endl;
break;
}
}
return 0;
}
*******************************************************************************
函数:建立邻接矩阵,成功返回 1
**调用者:main *
int CreatUDN ( Graph &G )
{
int i = 0, j = 0, k = 0, weight = 0;
char choice = 'Y';
ElemType v1, v2;
cout << "需要为你自动创建邻接矩阵吗 Y/N" << endl;
cin >> choice;
fflush ( stdin );
//自动创建默认邻接矩阵
if ( choice == 'Y' || choice == 'y') {
AutoCreat ( G );
return 1;
}
//读入顶点,创建顶点间的权值为默认值
cout << "请输入顶点个数:" << endl;
G.VexNum = cin.get()- '0';
cout << "请输入各顶点数据:" <<endl;
for ( i = 0; i <= G.VexNum-1; i++ )
cin >> G.Vex[ i ];
for ( i = 0; i <= G.VexNum-1; i++ )
for ( j = 0; j <= G.VexNum-1; j++ )
{
if ( i == j )
G.Arcs[ i ][ j ].w = 0;
else
G.Arcs[ i ][ j ].w = Max_Num;
}
//创建各条边
fflush(stdin);
cout << "请输入边的条数:" << endl;
G.ArcNum = cin.get()-'0';
cout << "请输入各边的数据(V1 V2 权值):" <<endl;
for ( k = 0; k <= G.ArcNum-1; k++ ) {
cin >> v1 >> v2 >> weight;
//定位输入边的两个顶点的位置
i = LocatVex( G , v1 );
j = LocatVex( G , v2 );
//输入的边的顶点数据有错误
if( i == -1 || j == -1 ) {
cout << "没有找到所要输入的边" <<endl;
k--;
}
G.Arcs[ i ][ j ].w = weight;
G.Arcs[ j ][ i ].w = weight;
}
return 1;
}
* 函数:在顶点数组 V[ ]中寻找所输入的数据 V,
找到返回所在位置,否则返回 -1
**调用者:手工创建邻接矩阵 CreatUDN *
int LocatVex ( Graph G, ElemType V )
{
int i = 0;
for ( i = 0; i <= G.VexNum-1; i++ )
if ( G.Vex[ i ] == V )
return i;
return -1;
}
*******************************************************************************
函数:自动建立邻接矩阵
顶点分别为 a b c .....
权值自动生成
**调用者:main *
void AutoCreat ( Graph &G )
{
G.VexNum = Max_Size;
for ( int i = 0; i <= G.VexNum-1; i++) {
G.Vex[ i ] = 'A' + i;
G.Arcs[ i ][ i ].w = 0;
}
//随机生成各条边之间的权值
for ( int i = 0; i <= G.VexNum-1; i++)
for ( int j = i+1; j <= G.VexNum-1; j++) {
G.Arcs[ j ][ i ].w = G.Arcs[ i ][ j ].w = rand() % 50;
//两点之间没有直接连接,权值为无穷大
if ( G.Arcs[ j ][ i ].w == 0)
G.Arcs[ j ][ i ].w = G.Arcs[ i ][ j ].w = Max_Num;
}
}
*******************************************************************************
函数:输入选择
**调用者:main *
int GetChoice ()
{
int choice = 0;
cout << "请选择用何种算法求最小代价生成树:\n1-Prim 算法\n2-Kruskal 算法\n3-去边法\n4-退出" <<endl;
cin >> choice;
return choice;
}
*******************************************************************************
函数:输出邻接矩阵,以矩阵的格式输出
**调用者:main *
void OutPut ( Graph G )
{
int i = 0, j = 0;
cout << "邻接矩阵为:" <<endl;
cout << setw ( Wid ) << " ";
for ( i = 0; i <= G.VexNum-1; i++)
cout << setw( Wid ) << G.Vex[ i ];
cout <<endl;
for ( i = 0; i <= G.VexNum-1; i++ ) {
cout << setw( Wid ) << G.Vex[ i ];
for ( j = 0; j <= G.VexNum-1; j++ ) {
if ( G.Arcs[ i ][ j ].w == Max_Num )
cout << setw( Wid ) << "*" ;
else
cout << setw( Wid ) << G.Arcs[ i ][ j ].w ;
}
cout << endl;
}
}
*******************************************************************************
函数:prim算法求最小生成树
**调用者:main *
void Prim ( Graph G )
{
// CT 中在第k个的时候,前 k-1个为已经放入最小树的顶点,后面的为没放入的
Edge CT[ Max_Size ] ;
Edge temp;
int i = 0, j = 0, k = 0, w = 0, t = 0;
//对应第0次的值,即和第一个顶点间的权值放入CT
for ( i = 1; i < G.VexNum; i++) {
CT [ i-1 ].fromvex = 0;
CT [ i-1 ].endvex = i;
CT [ i-1 ].weight = G.Arcs[ 0 ][ i ].w;
}
for ( k = 1; k < G.VexNum; k++) {
//找到和已放入最小树的顶点的集合之间的权值最小的边
int min = Max_Num;
int m = k-1;
for ( j = k-1; j < G.VexNum-1; j++)
if ( CT[ j ].weight < min) {
min = CT[ j ].weight;
m = j;
}
//把最短边调换到 k-1位置
temp = CT[ k-1 ];
CT[ k-1 ] = CT[ m ];
CT[ m ] = temp;
//把新加入最小树的顶点值赋给 j
j = CT [ k -1 ].endvex;
//为下次求最小的边做准备,使树到数外各顶点之间的权值保持在最小
for ( i = k; i < G.VexNum-1; i++) {
t = CT[ i ].endvex;
w = G.Arcs[ j ][ t ].w;
//如果新加入的 j到某个顶点的权值小于目前的最小值,
//将最小值更改为 j 到这个顶点的值,同时更改到这个顶点的树内顶点为 j
if ( w < CT[ i ].weight) {
CT[ i ].weight = w;
CT[ i ].fromvex = j;
}
}
}
for ( i = 0; i < G.VexNum-1; i++ )
if ( CT[ i ].weight == Max_Num ) {
cout << "没有最小生成树" <<endl<<endl;
return ;
}
for ( i = 0; i < G.VexNum-1; i++ ) {
cout << setw( Wid ) << G.Vex[ CT[ i ].fromvex ]
<< setw( Wid ) << G.Vex [ CT[ i ].endvex ] << setw( Wid ) << CT[ i ].weight <<endl;
}
}
*******************************************************************************
函数:kruskal算法求最小生成树
**调用者:main *
void Kru ( Graph G )
{
//标记每个顶点所在的集合
int mark [ Max_Size ] = { 0 };
int i = 0, j = 0, k = 0, temp1 = 0, temp2 = 0, sum = 0;
int min = Max_Num, fromvex = 0, endvex = 0, t = 0;
//将所有顶点分属不同集合
for ( i = 0; i <= G.VexNum-1; i++ )
mark[ i ] = i;
for ( t = 1; t <= G.VexNum-1; t++ ) {
//找到权值最小的那条边,并且首尾顶点不在同一个集合
min = Max_Num;
for ( i = 0; i <= G.VexNum-1; i++ )
for ( j = i+1; j <= G.VexNum-1; j++ )
if ( mark[ i ] != mark[ j ] && G.Arcs[ i ][ j ].w < min ) {
min = G.Arcs[ i ][ j ].w;
fromvex = i;
endvex = j;
}
if ( min != Max_Num ) {
cout << setw( Wid ) << G.Vex[ fromvex ]
<< setw( Wid ) << G.Vex [ endvex ] << setw( Wid ) << min <<endl;
sum ++;
}
//将首尾顶点所在的两个顶点集合合并为一个集合
temp1 = mark [ endvex ];
temp2 = mark [ fromvex ];
for ( k = 0; k <= G.VexNum-1; k++) {
if ( mark [ k ] == temp1 )
mark [ k ] = temp2;
}
}
if ( sum != G.VexNum-1 )
cout << "没有最小生成树" <<endl<<endl;
}
*******************************************************************************
函数:去边法求最小生成树
**调用者:main *
void Del ( Graph G )
{
Edge S[ Max_Size * Max_Size ], hold[ Max_Size * Max_Size ];
int i = 0, j = 0, len = 0, temp = 0, sum = 0;
//将 G 中的有效边放入Sort中,并且将其由大到小排序,返回边的条数
len = SortEdge( G, S);
//从最大权值边开始,依次检测能否去掉
for ( i = 0; i <= len-1; i++ ) {
temp = S[ i ].weight;
//去掉这条边
S[ i ].weight = Max_Num;
//做一份S的拷贝hold
copy ( hold, S, len);
//去掉后图不在连通,回复
if ( ! Findpath ( hold, len, hold[ i ].fromvex, hold[ i ].endvex, i ) )
S[ i ].weight = temp;
}
for ( i = 0; i<= len-1; i++ )
if ( S[ i ].weight != Max_Num ) {
cout << setw( Wid ) << G.Vex[ S[ i ].fromvex ]<< setw( Wid )
<< G.Vex[ S[ i ].endvex ] << setw( Wid ) << S[ i ].weight <<endl;
sum++;
}
if ( sum != G.VexNum-1 )
cout << "没有最小生成树" <<endl<<endl;
}
* 函数:排序,将 G 中的有效边放入Sort中,
并且由大到小排序,返回边的条数
**调用者:去边法 Del *
int SortEdge ( Graph G, Edge sort[] )
{
int len = 0, i = 0, j = 0, pass = 0;
Edge Hold;
//将图中的有效边放入sort中,并计算出条数
for ( i = 0; i <= G.VexNum-1; i++ )
for ( j = i+1; j <= G.VexNum-1; j++ )
if ( G.Arcs[ i ][ j ].w != Max_Num ) {
sort[ len ].fromvex = i;
sort[ len ].endvex = j;
sort[ len ].weight = G.Arcs[ i ][ j ].w;
len++;
}
//冒泡排序,从大到小
for ( pass = 0; pass <= len-2; pass++ )
for ( i = pass+1; i <= len-1; i++ )
if ( sort[ pass ].weight < sort[ i ].weight ) {
Hold = sort[ pass ];
sort[ pass ] = sort[ i ];
sort[ i ] = Hold;
}
return len;
}
* 函数:判断两点间是否有路径,有返回 1
**调用者:去边法 Del *
int Findpath ( Edge e[], int len, int from, int end, int mark)
{
int i = 0, temp = 0;
//此边已经使用过
e[ mark ].weight = Max_Num;
//找到路径
if ( from == end )
return 1;
//依次搜索每条边,找到和此顶点相连接的有效边
//继续以找到边的另一个顶点为基准搜索
for ( i = 0; i < len; i++ )
if ( e[ i ].weight != Max_Num ) {
if ( e[ i ].fromvex == from )
if ( Findpath ( e, len, e[ i ].endvex, end, i ))
return 1;
if ( e[ i ].endvex == from )
if ( Findpath ( e, len, e[ i ].fromvex, end, i )) {
return 1;
}
}
return 0;
}
* 函数:把S拷进 hold
**调用者:去边法 Del *
void copy ( Edge hold[], Edge S[], int len)
{
for ( int i = 0; i < len; i++ )
hold[ i ] = S[ i ];
}
发表评论
-
DLL中导出函数的声明有两种方式:
2012-11-12 16:42 1873DLL中导出函数的声明有两种方式: 一种方式是:在函数声明中 ... -
k-means算法的C++实现
2011-04-05 11:38 2349k-means算法的C++实现: http://www.ku ... -
main()中的参数
2010-10-31 10:41 1546所有的应用程序都是从以main函数作为入口, 而mai ... -
static作用
2010-10-26 19:15 2398转自(from http://www.cnb ... -
mmap函数
2010-10-25 22:41 1918mmap函数的使用方法 UNIX ... -
C语言中三种内存分配方式
2010-10-25 20:23 01.malloc 原型:extern void *ma ... -
位拷贝和值拷贝
2010-10-23 15:37 1607为了便于说明我们以String类为例: 首先定义String ... -
(转帖)把类的析构函数写成虚函数的用意
2010-10-23 15:10 1706#include <iostream.h> cl ... -
动态规划/贪心算法----0/1背包问题AND普通背包问题
2010-10-23 14:03 6834两个背包问题都是比较典型的问题,对这两种算法的理解有很好的帮助 ... -
netstat, nslookup, finger, ping命令
2010-10-22 17:13 1547Netstat用于显示与IP、TCP ... -
C++返回值
2010-10-22 16:53 1559C++函数返回值: (1)正常情况下,函数的参数要复制一份在 ... -
switch语句后的表达式的值
2010-10-22 16:23 1851一般格式: switch (表达式) { case 常量 ... -
C++四种强制类型转换
2010-10-19 11:45 1583显式类型转换又被称之 ... -
C++四种强制类型转化的区别
2010-10-19 11:43 1363先介绍const_cast和reinterpret_cast: ... -
Visual C++线程同步技术剖析:临界区,时间,信号量,互斥量
2010-10-18 14:24 1839使线程同步 在程序中使用多线程时,一般很少有多个线程能在其 ... -
(转)临界区,互斥量,信号量,事件的区别
2010-10-18 14:22 1778四种进程或线程同步互斥的控制方法1、临界区:通过对多线程的串行 ... -
(转)在C++中实现同步锁,类似synchronize(object){....}
2010-10-18 13:49 1891在做C++的项目中发现, ... -
C++线程同步
2010-10-18 13:46 1624线程同步是多 ... -
C++多线程编程
2010-10-18 10:56 1760今天我给大家讲一讲C++ ... -
关于C++对函数传参与函数返回值进行引用传递的详解
2010-10-16 22:51 4070关于C++对函数传参与函数返回值进行引用传递的详解 ...
相关推荐
C语言实现Prim算法时,可以使用邻接矩阵或优先队列(如二叉堆)来存储边的权重和查找最短边。邻接矩阵适合表示稠密图,而优先队列更适合稀疏图。 ### Kruskal算法 Kruskal算法同样基于贪心策略,但它的核心是按照...
在Matlab中实现Prim算法和Kruskal算法可以使用邻接矩阵表示图,分别保存为文件Graph1.m和Graph2.m。然后,在主程序finallyprim中直接调用这些文件,并使用sprintf格式化字符串的方法,避免了编程的人每次根据输入图...
输入无向图的邻接矩阵,使用Prim 算法、Kruskal 算法和去边法三种算法求该图的最小代价生成树,并分析各自的时间复杂度。
本项目将深入探讨如何用C++通过邻接矩阵来存储图,并实现两种经典算法:Prim算法和Kruskal算法,用于构建最小生成树。 首先,我们来看一下邻接矩阵的存储方式。邻接矩阵是一个二维数组,数组的大小通常是n×n,其中...
虽然示例代码中没有给出完整的Kruskal算法实现,但是可以推测其大致流程应该包括定义边结构体、创建图、读取图的信息、排序边以及检查环路等步骤。 #### 邻接矩阵表示法 在这个示例中,图是以邻接矩阵的形式存储的...
prim算法 Kruskal算法分别实现最小生成树
Prim算法更适合处理稠密图,即边的数量接近于顶点数量的平方,因为它主要以顶点为中心扩展;而Kruskal算法则适用于稀疏图,即边的数量远小于顶点数量的平方,因为它主要考虑边的顺序。在实际应用中,根据图的特性...
Kruskal算法的正确性则可以通过反证法来证明,若在某一步加入的边会形成环,则说明已经找到了一个更小的生成树,这与已知的最小生成树是最小的矛盾,因此Kruskal算法每次选择的边都不会形成环,保证了算法的正确性。...
定义采用邻接矩阵存储的图结构封装DFS、BFS算法
PRIM算法与Kruskal算法一样,都是解决最小生成树问题的经典方法,但它们在选择边的方式上有所不同,Kruskal算法是按照边的权重从小到大选择,而PRIM算法是从节点出发逐步扩展。 总结来说,邻接矩阵在图数据结构中...
但是,Prim算法的时间复杂度为O(n^2),而Kruskal算法的时间复杂度为O(ElogE),其中E为图中的边数。因此,在大规模图中,Kruskal算法的效率更高。 六、 结论 Prim算法和Kruskal算法都是常用的最小生成树算法,它们...
(1)、实验题目:给定一个地区的n 个城市间的距离网,用Prim算法或Kruskal算法建立最小生成树,并得到的最小生成树的代价。 (2)、实验要求: 1、城市间的距离网采用的邻接矩阵表示,邻接矩阵的存储结构定义采用...
Prim算法适合稠密图,因为它每次迭代都考虑了所有相邻顶点,而Kruskal算法则更适合稀疏图,因为它的主要时间消耗在于边的排序。在实现上,Prim算法通常使用优先队列优化查找最小边的过程,而Kruskal算法依赖于并查集...
- 在C++实现中,Prim算法通常使用优先队列(如二叉堆)来快速找到最小权重的边,以及邻接矩阵或邻接表来存储图的信息。 3. **Kruskal算法**: - Kruskal算法也是贪心算法,但其策略是从图中最小的边开始选择,并...
在MATLAB中,可以使用邻接矩阵或邻接表数据结构来实现Prim算法。具体步骤包括: - 初始化:选择一个起始顶点,将其加入最小生成树。 - 循环:对于当前树中每个顶点,找出与非树顶点的最短边,将对应的顶点加入树中...
// 该函数使用邻接矩阵存储结构,通过Prim算法构建最小生成树 } ``` ##### 2.2.2 邻接表存储 ```c void MiniSpanTree_PRIM(ALGraph G, VertexType u) { // 代码实现省略,参见给定文件 // 该函数使用邻接表存储...
prim算法求最小生成树
- 图的表示:可能使用邻接矩阵或邻接表来存储图的结构。 - Prim算法的实现:从一个顶点开始,逐步扩展最小生成树。 - Kruskal算法的实现:先对所有边进行排序,然后检查每条边是否构成环路。 - 辅助数据结构:如优先...