图的可执行代码(创建、遍历、最小生成树)

图的可执行代码(创建、遍历、最小生成树)

在学数据结构时,由于老师为了简化代码,多采用伪代码的形式讲课,包括许多教材也是用伪代码,因此我觉得写一套图的基本操作的代码更有助于学习。(创建的图为无向图)

废话少说,上代码

#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);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/BWQ2019/article/details/106133781