图的可执行代码(创建、遍历、最小生成树)
在学数据结构时,由于老师为了简化代码,多采用伪代码的形式讲课,包括许多教材也是用伪代码,因此我觉得写一套图的基本操作的代码更有助于学习。(创建的图为无向图)
废话少说,上代码
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 256
#define MAXEDGE 1000
#define INIFINITY 65535//极大值
#define Status int
#define OK 1
#define TRUE 1
#define FALSE 0
typedef int Boolean;//布尔类型
typedef char VerType;//顶点类型
typedef char ElemType;
Boolean visited[MAXSIZE];//访问标志数组
typedef struct ArcNode
{
int adjvex;//弧尾下标
int weight;//权重
struct ArcNode *next;
} ArcNode;
typedef struct
{
VerType data;//顶点
ArcNode *FirstArc;//第一条边
} VNode, AdjList[MAXSIZE]; //邻接表
typedef struct
{
int vexnum;//顶点数
int arcnum;//边数
AdjList vertices;//邻接表数组
} ALGraph;
typedef struct
{
int begin;
int end;
int weight;
} Edge;//边集数组
typedef struct QNode
{
ElemType data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct
{
QueuePtr front;
QueuePtr rear;
} LinkQueue; //队列
void InitQueue(LinkQueue *Q);//初始化队列
void EnQueue(LinkQueue *Q, ElemType e);//入队列操作
void DeleteQueue(LinkQueue *Q, int *e);//出队列操作
int EmptyQueue(LinkQueue Q);//判断队列是否为空
int LocateVex(ALGraph *G, VerType V);//找到V在邻接表中的下标
void CreatALGraph(ALGraph *G);//创建图
void DFS(ALGraph G, int i);//深度优先遍历
void DFSTraverse(ALGraph G);
void BFSTraverse(ALGraph G);//广度优先遍历
int getweight(ALGraph G, int start, int end);//找到权重
void MiniSpanTree_Prim(ALGraph G);//Prim算法
Edge *get_edges(ALGraph G);//获取边集数组
void Edges_sort(int len, Edge *edges);//边集数组排序
int Find(int *parent, int f);
void MiniSpanTree_Kruskal(ALGraph G);//Kruskal算法
int main()
{
ALGraph G;
CreatALGraph(&G);
//MiniSpanTree_Kruskal(G);
//BFSTraverse(G);
//DFSTraverse(G);
return 0;
}
void InitQueue(LinkQueue *Q)//初始化一个空队列
{
Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode));
if(!Q->front)
{
exit(0);
}
else
{
Q->front->next = NULL;
}
}
void EnQueue(LinkQueue *Q, ElemType e)//入队列操作
{
QueuePtr p;
p = (QueuePtr)malloc(sizeof(QNode));
if(p == NULL)
{
exit(0);
}
p->data = e;
p->next = NULL;
Q->rear ->next = p;
Q->rear = p;
}
void DeleteQueue(LinkQueue *Q, int *e)//出队列操作
{
QueuePtr p;
if(Q->front == Q->rear)
{
return ;
}
p = Q->front->next;
*e = p->data;
Q->front->next = p->next;
if(Q->rear == p)
{
Q->rear = Q->front;
}
free(p);
}
int EmptyQueue(LinkQueue Q)
{
return (Q.front == Q.rear ? 1 : 0);
}
int LocateVex(ALGraph *G, VerType V)
{
int i;
for(i = 0; i < G->vexnum; i++)
{
if(V == G->vertices[i].data)
break;
}
return i;
}
void CreatALGraph(ALGraph *G)//创建无向图
{
printf("请输入顶点个数\n");
scanf("%d", &G->vexnum);
printf("请输入边的个数\n");
scanf("%d", &G->arcnum);
fflush(stdin);
for(int i = 0; i < G->vexnum; i++)
{
scanf("%c", &G->vertices[i].data);
G->vertices[i].FirstArc = NULL;
}
fflush(stdin);
for(int k = 0; k < G->arcnum; k++)
{
char V1, V2;
int w;
scanf("%c%c%d", &V1, &V2, &w);
fflush(stdin);
int i = LocateVex(G, V1);
int j = LocateVex(G, V2);
ArcNode *e = (ArcNode*)malloc(sizeof(ArcNode));
e->weight = w;
e->adjvex = j;
e->next = G->vertices[i].FirstArc;
G->vertices[i].FirstArc = e;
ArcNode *t = (ArcNode*)malloc(sizeof(ArcNode));
t->weight = w;
t->adjvex = i;
t->next = G->vertices[j].FirstArc;
G->vertices[j].FirstArc = t;
}
}
//深度优先遍历
void DFS(ALGraph G, int i)
{
ArcNode *p;
visited[i] = TRUE;
printf("%c ", G.vertices[i].data);
p = G.vertices[i].FirstArc;
while(p)
{
if(visited[p->adjvex] != TRUE)
{
DFS(G, p->adjvex);
}
p = p->next;
}
}
void DFSTraverse(ALGraph G)
{
for(int i = 0; i < G.vexnum; i++)
{
visited[i] = FALSE;
}
for(int i = 0; i < G.vexnum; i++)
{
if(!visited[i])
{
DFS(G, i);
}
}
}
void BFSTraverse(ALGraph G)//广度优先遍历
{
int i, j;
ArcNode*p;
LinkQueue Q;
InitQueue(&Q);
for(i = 0; i < G.vexnum; i++)
{
visited[i] = FALSE;
}
for(i = 0; i < G.vexnum; i++)
{
if(!visited[i])
{
printf("%c ", G.vertices[i].data);
visited[i] = TRUE;
EnQueue(&Q, i);
while(!EmptyQueue(Q))
{
DeleteQueue(&Q, &j);
p = G.vertices[j].FirstArc;
while(p)
{
if(!visited[p->adjvex])
{
printf("%c ", G.vertices[p->adjvex].data);
visited[p->adjvex] = TRUE;
EnQueue(&Q, p->adjvex);
}
p = p->next;
}
}
}
}
}
//最小生成树prim算法
int getweight(ALGraph G, int start, int end)
{
ArcNode *p;
p = G.vertices[start].FirstArc;
if(start == end)
{
return 0;
}
else
{
while(p)
{
if(end == p->adjvex)
{
return p->weight;
}
p = p->next;
}
return INIFINITY;
}
}
void MiniSpanTree_Prim(ALGraph G)//prim算法
{
int min, i, j, k;
int weight;
int adjvex[MAXSIZE];
int lowcost[MAXSIZE];
lowcost[0] = 0;
adjvex[0] = 0;
//初始化操作
for(int i = 0; i < G.vexnum; i++)
{
lowcost[i] = getweight(G, 0, i);
adjvex[i] = 0;
}
//构造最小生成树
for(i = 1; i < G.vexnum; i++)
{
min = INIFINITY;
j = 1;
k = 0;
//遍历全部顶点
while(j < G.vexnum)
{
if(lowcost[j] != 0 && lowcost[j] < min)
{
min = lowcost[j];
k = j;
}
j++;
}
printf("(%c,%c)\n", G.vertices[adjvex[k]].data, G.vertices[k].data); //打印当前顶点中权值最小的
lowcost[k] = 0;
for(j = 1; j < G.vexnum; j++)
{
weight = getweight(G, k, j);
if(lowcost[j] != 0 && weight < lowcost[j])
{
lowcost[j] = weight;
adjvex[j] = k;
}
}
}
}
Edge *get_edges(ALGraph G)//获取边集数组
{
int i, j;
int index = 0;
Edge *edges = (Edge*)malloc(G.arcnum * sizeof(Edge));
for(i = 0; i < G.arcnum; i++)
{
ArcNode*p = G.vertices[i].FirstArc;
while(p)
{
j = p->adjvex;
if(i < j)
{
edges[index].begin = i;
edges[index].end = j;
edges[index].weight = p->weight;
index++;
}
p = p->next;
}
}
return edges;
}
void Edges_sort(int len, Edge *edges) //边集数组的排序
{
int i, j;
for(i = 0; i < len - 1; i++)
{
for(j = 0; j < len - 1 - i; j++)
{
if(edges[j].weight > edges[j + 1].weight)
{
Edge temp;
temp = edges[j];
edges[j] = edges[j];
edges[j] = temp;
}
}
}
}
int Find(int *parent, int f)
{
while(parent[f] > 0)
{
f = parent[f];
}
return f;
}
void MiniSpanTree_Kruskal(ALGraph G)
{
int i, n, m;
Edge *edges = get_edges(G);//边集数组
Edges_sort(G.arcnum, edges);
int parent[MAXSIZE];
for(i = 0; i < G.vexnum; i++)
{
parent[i] = 0;
}
for(i = 0; i < G.arcnum; i++)
{
n = Find(parent, edges[i].begin);
m = Find(parent, edges[i].end);
if(n != m)
{
parent[n] = m;
printf("(%d,%d),%d\n", edges[i].begin, edges[i].end, edges[i].weight);
}
}
}