高级算法分析与设计课程论文实验代码
Prim算法
#include <iostream>
#include <string>
#include <fstream>
#include <windows.h>
#include "MyTimer.h"
using namespace std;
#define MAXV 400 //最大顶点个数
typedef int InfoType;
typedef struct
{
int no; //顶点编号
InfoType info; //顶点其他信息
} VertexType; //顶点类型
typedef struct //图的定义
{
VertexType vexs[MAXV]; //存放顶点信息
int edges[MAXV][MAXV]; //邻接矩阵
int vexnum; //顶点数
int arcnum; //弧数
} MGraph; //图的邻接矩阵类型
//打印图
void print(MGraph g)
{
int i;
for (i = 0; i < g.vexnum; i++)
{
for (int j = 0; j < g.vexnum; j++)
{
if (g.edges[i][j] == INT_MAX)
cout << "∞"
<< " ";
else
cout << g.edges[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
//作为记录边的信息,这些边都是达到end的所有边中,权重最小的那个
struct Assis_array
{
int start; //边的终点
int end; //边的起点
int weight; //边的权重
};
//进行prim算法实现,使用的邻接矩阵的方法实现。
void Prim(MGraph g, int begin)
{
// close_edge这个数组记录到达某个顶点的各个边中的权重最大的那个边
Assis_array *close_edge = new Assis_array[g.vexnum];
int j;
//进行close_edge的初始化,更加开始起点进行初始化
for (j = 0; j < g.vexnum; j++)
{
if (j != begin - 1)
{
close_edge[j].start = begin - 1;
close_edge[j].end = j;
close_edge[j].weight = g.edges[begin - 1][j];
}
}
//把起点的close_edge中的值设置为-1,代表已经加入到集合U了
close_edge[begin - 1].weight = -1;
//访问剩下的顶点,并加入依次加入到集合U
for (j = 1; j < g.vexnum; j++)
{
int min = INT_MAX;
int k;
int index;
//寻找数组close_edge中权重最小的那个边
for (k = 0; k < g.vexnum; k++)
{
if (close_edge[k].weight != -1)
{
if (close_edge[k].weight < min)
{
min = close_edge[k].weight;
index = k;
}
}
}
//将权重最小的那条边的终点也加入到集合U
close_edge[index].weight = -1;
//输出对应的边的信息
cout << " (" << close_edge[index].start << ","
<< close_edge[index].end << "):"
<< g.edges[close_edge[index].start][close_edge[index].end]
<< endl;
//更新close_edge数组。
for (k = 0; k < g.vexnum; k++)
{
if (g.edges[close_edge[index].end][k] < close_edge[k].weight)
{
close_edge[k].weight = g.edges[close_edge[index].end][k];
close_edge[k].start = close_edge[index].end;
close_edge[k].end = k;
}
}
}
}
//创建图
void createGraph(MGraph &g)
{
int i, j, a;
// ifstream in("Sparse.txt");
ifstream in("Dense.txt");
in >> g.vexnum >> g.arcnum;
for (i = 0; i < g.vexnum; i++)
{
for (j = 0; j < g.vexnum; j++)
{
in >> a;
g.edges[i][j] = a == -1 ? INT_MAX : a;
}
}
}
int main()
{
MGraph g;
MyTimer mt;
createGraph(g);
print(g);
cout << "最小生成树为:" << endl;
mt.Start();
Prim(g, 1);
mt.End();
cout << "查找最小生成树用时" << mt.costTime << "微秒。" << endl;
system("pause");
return 0;
}
Kruskal算法
#include <iostream>
#include <fstream>
#include <windows.h>
#include "MyTimer.h"
using namespace std;
#define MaxSize 10000
#define MAXV 400 //最大顶点个数
typedef int InfoType;
typedef struct
{
int no; //顶点编号
InfoType info; //顶点其他信息
} VertexType; //顶点类型
typedef struct //图的定义
{
VertexType vexs[MAXV]; //存放顶点信息
int edges[MAXV][MAXV]; //邻接矩阵
int vexnum; //顶点数
int arcnum; //弧数
} MGraph; //图的邻接矩阵类型
typedef struct
{
int u; //边的起始顶点
int v; //边的终止顶点
int w; //边的权值
} Edge;
typedef struct node
{
int rank; //结点对应秩
int parent; //结点对应双亲下标
} UFSTree; //并查集树结点类型
void MAKE_SET(UFSTree t[], int n) //初始化并查集树
{
int i;
for (i = 0; i < n; i++) //顶点编号从0到n-1
{
t[i].rank = 0; //秩初始化为0
t[i].parent = i; //双亲初始化指向自已
}
}
int FIND_SET(UFSTree t[], int x) //在x所在子树中查找集合编号
{
if (x != t[x].parent) //双亲不是自已
return (FIND_SET(t, t[x].parent)); //递归在双亲中找x
else
return (x); //双亲是自已,返回x
}
void UNION(UFSTree t[], int x, int y) //将x和y所在的子树合并
{
x = FIND_SET(t, x);
y = FIND_SET(t, y);
if (t[x].rank > t[y].rank) // y结点的秩小于x结点的秩
t[y].parent = x; //将y连到x结点上,x作为y的孩子结点
else // y结点的秩大于等于x结点的秩
{
t[x].parent = y; //将x连到y结点上,y作为x的孩子结点
if (t[x].rank == t[y].rank) // x和y结点的秩相同
t[y].rank++; // y结点的秩增1
}
}
void sift(Edge E[], int low, int high) //筛选算法
{
int i = low, j = 2 * i; // E[j]是E[i]的左孩子
Edge temp = E[i];
while (j <= high)
{
if (j < high && E[j].w < E[j + 1].w) //若右孩子较大,把j指向右孩子
j++; // f变为2i+1
if (temp.w < E[j].w)
{
E[i] = E[j]; //将E[j]调整到双亲结点位置上
i = j; //修改i和j值,以便继续向下筛选
j = 2 * i;
}
else
break; //筛选结束
}
E[i] = temp; //被筛选结点的值放入最终位置
}
void HeapSort(Edge E[], int n)
{
int i;
Edge temp;
for (i = n / 2; i >= 1; i--) //循环建立初始堆
sift(E, i, n);
for (i = n; i >= 2; i--) //进行n-1次循环,完成推排序
{
temp = E[1]; //将第一个元素同当前区间内R[1]对换
E[1] = E[i];
E[i] = temp;
sift(E, 1, i - 1); //筛选R[1]结点,得到i-1个结点的堆
}
}
void Kruskal(MGraph g, Edge E[])
{
int i, j, k, u1, v1, sn1, sn2;
UFSTree t[MaxSize];
HeapSort(E, g.arcnum); // 采用堆排序对E数组按权值递增排序
MAKE_SET(t, g.vexnum); // 初始化并查集树t
k = 1; // k表示当前构造生成树的第几条边,初值为1
j = 1; // E中边的下标,初值为1
while (k < g.vexnum) // 生成的边数小于n时循环
{
u1 = E[j].u;
v1 = E[j].v; //取一条边的头尾顶点编号u1和v2
sn1 = FIND_SET(t, u1);
sn2 = FIND_SET(t, v1); //分别得到两个顶点所属的集合编号
if (sn1 != sn2) //两顶点属于不同的集合,该边是最小生成树的一条边
{
cout << " (" << u1 << "," << v1 << "):" << E[j].w << endl;
k++; //生成边数增1
UNION(t, u1, v1); //将u1和v1两个顶点合并
}
j++; //扫描下一条边
}
cout << endl;
}
//打印图
void print(MGraph g)
{
int i;
for (i = 0; i < g.vexnum; i++)
{
for (int j = 0; j < g.vexnum; j++)
{
if (g.edges[i][j] == INT_MAX)
cout << "∞"
<< " ";
else
cout << g.edges[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
void createGraph(MGraph &g, Edge E[])
{
int i, j, k, a;
// ifstream in("Sparse.txt");
ifstream in("Dense.txt");
in >> g.vexnum >> g.arcnum;
for (i = 0; i < g.vexnum; i++)
for (j = 0; j < g.vexnum; j++)
{
in >> a;
g.edges[i][j] = a == -1 ? INT_MAX : a;
}
k = 1; // e数组的下标从1开始计
for (i = 0; i < g.vexnum - 1; i++) //由g产生的边集e
for (j = i + 1; j < g.vexnum; j++)
if (g.edges[i][j] != 0 && g.edges[i][j] != INT_MAX)
{
E[k].u = i;
E[k].v = j;
E[k].w = g.edges[i][j];
k++;
}
}
int main()
{
int i, j, k;
MGraph g;
MyTimer mt;
Edge E[MaxSize];
createGraph(g, E);
print(g);
cout << "最小生成树为:" << endl;
mt.Start();
Kruskal(g, E);
mt.End();
cout << "查找最小生成树用时" << mt.costTime << "微秒" << endl;
system("pause");
return 0;
}
连通图邻接矩阵生成
#include <iostream>
#include <random>
using namespace std;
int main()
{
int a[100][100];
int b, count = 99;
uniform_int_distribution<unsigned> u(1, 20);
uniform_int_distribution<unsigned> v(0, 99);
default_random_engine e;
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 100; j++)
{
a[i][j] = -1;
}
}
for (int i = 0; i < 100; i++)
{
a[i][i] = 0;
}
for (int i = 0; i < 99; i++) //确保连通
{
a[i][i + 1] = u(e);
a[i + 1][i] = u(e);
}
for (int i = 0; count < 4000; i++) //生成随机边,重复直接覆盖
{
int k = v(e);
int j = v(e);
if (a[k][j] == -1)
{
int r = u(e);
a[k][j] = r;
a[j][k] = r;
count++;
}
}
for (int i = 0; i < 100; i++) //打印邻接矩阵
{
for (int j = 0; j < 100; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
cout << "边数:" << count;
system("pause");
return 0;
}