数据结构实验3--图以邻接表为存储结构的初始化,遍历,迪杰斯特拉算法求最短路径(实验内容3~4~5)

本例图的画法:

运行结果:

在这里插入图片描述

源文件:

#include "邻接表宽度优先遍历的queue.h"
//邻接表的初始化
Status Init(LGraph* lg, int nSize)
{
	int i;
	lg->numofDot = nSize;
	lg->numofEdge = 0;
	lg->a = (ENode**)malloc(nSize * sizeof(ENode*));
	if (!lg->a)
	{
		return ERROR;

	}
	else
	{
		for (i = 0; i < lg->numofDot; i++)
			lg->a[i] = NULL;
		return OK;
	}
}

//邻接表的撤销
void Destroy(LGraph* lg)
{
	int i;
	ENode* p, * q;
	for (i = 0; i < lg->numofDot; i++)
	{
		p = lg->a[i];
		q = p;
		while (p)
		{
			p = p->nextArc;
			free(q);
			q = p;
		}
	}
	free(lg->a);
}

//边的搜索
Status Exist(LGraph* lg, int u, int v)
{
	ENode* p;
	if (u<0 || v<0 || u>lg->numofDot - 1 || v>lg->numofDot - 1 || u == v)
	{
		return ERROR;

	}
	p = lg->a[u];
	while (p && p->adjVex != v)
	{
		p = p->nextArc;
	}
	if (!p)
	{
		return ERROR;
	}
	else
	{
		return OK;
	}
}

//边的插入
Status Insert(LGraph* lg, int u, int v, ElemType w)
{
	ENode* p;
	if (u<0 || v<0 || u>lg->numofDot - 1 || v>lg->numofDot - 1 || u == v)
		return ERROR;
	if (Exist(lg, u, v))
	{
		return Duplicate;
	}
	p = (ENode*)malloc(sizeof(ENode));
	p->adjVex = v;
	p->w = w;
	p->nextArc = NULL;
	p->nextArc = lg->a[u];  //将新的边节点插入单链表的最前面
	lg->a[u] = p;
	lg->numofEdge++;
	return OK;
}

//边的删除
Status Remove(LGraph* lg, int u, int v)
{
	ENode* p, * q;
	if (u<0 || v<0 || u>lg->numofDot - 1 || v>lg->numofDot - 1 || u == v)
		return ERROR;
	p = lg->a[u], q = NULL;
	while (p && p->adjVex != v)
	{
		q = p;
		p = p->nextArc;
	}
	if (!p)
		return NotPresent;
	if (q)
		q->nextArc = p->nextArc;
	free(p);
	lg->numofEdge--;
	return OK;
}

//图的邻接表的深度优先遍历
void DFS(int v, int visited[], LGraph g)
{
	ENode* w;
	printf("%d ", v);
	visited[v] = 1;
	for (w = g.a[v]; w; w = w->nextArc)
	{
		if (!visited[w->adjVex])
			DFS(w->adjVex, visited, g);
	}
}

void DFSGraph(LGraph g)
{
	int i;
	int* visited = (int*)malloc(g.numofDot * sizeof(int));
	for (i = 0; i < g.numofDot; i++)
	{
		visited[i] = 0;
	}
	for (i = 0; i < g.numofDot; i++)
	{
		if (!visited[i])
		{
			DFS(i, visited, g);
		}
	}
	free(visited);
}

//图的邻接表的宽度优先遍历
void BFS(int v, int visited[], LGraph g)
{
	ENode* w;
	Queue q;
	queuecreate(&q, g.numofDot); //初始化队列
	visited[v] = 1;
	printf("%d ", v);
	EnQueue(&q, v);
	while (!queueIsEmpty(&q))
	{
		queueFront(&q, &v);
		DeQueue(&q);
		for (w = g.a[v]; w; w = w->nextArc)
		{
			if (!visited[w->adjVex])
			{
				visited[w->adjVex] = 1;
				printf("%d ", w->adjVex);
				EnQueue(&q, w->adjVex);
			}
		}
	}
}
void BFSGrapg(LGraph g)
{
	int i;
	int* visited = (int*)malloc(g.numofDot * sizeof(int));
	for (i = 0; i < g.numofDot; i++)
	{
		visited[i] = 0;
	}
	for (i = 0; i < g.numofDot; i++)
	{
		if (!visited[i])
		{
			BFS(i, visited, g);
		}
	}
	free(visited);
}

// 徐氏自创的迪杰斯特拉算法
void dijkstra(LGraph lg)
{
	ENode* p;
	int i, j, min, index;
	double allLength = 0;
	double* ahead = (double*)malloc(lg.numofDot * sizeof(double));  //记录离起点最短路径的顶点集合
	double* after = (double*)malloc(lg.numofDot * sizeof(double));  //记录还未求出最短路径的顶点集合(包括其离起点的距离)
	int u;
	printf("请输入起点u = \t");
	scanf_s("%d", &u);
	for (i = 0; i < lg.numofDot; i++)  //两数组的初始化
	{
		ahead[i] = INF;
		after[i] = INF;
	}

	for (p = lg.a[u]; p; p = p->nextArc) //将与起点有路径关系的点的权重放入after[]数组中
	{
		if (p != NULL)
		{
			after[p->adjVex] = p->w;
		}
	}

	for (int n = 1; n < lg.numofDot; n++)
	{
		min = INF;
		for (i = 0; i < lg.numofDot; i++)  //每次循环找出after[]中最小的的路径权重
		{
			if (min > after[i] && after[i] != -1&&i!=u)
			{
				min = after[i];
			}
		}
		for (index = 0; index < lg.numofDot; index++)
		{
			if (index == u)
				continue;
			if (after[index] == min)
				break;
		}
		ahead[index] = min;  //添加进ahead中
		after[index] = -1;  //已被添加,设为-1表示此元素已完成求最短路径

		while (lg.a[index])  //每次将某个点加入到ahead中后个点到起点的路径权重的算法
		{
			if (after[lg.a[index]->adjVex] > ahead[index] + lg.a[index]->w)
			{
				after[lg.a[index]->adjVex] = ahead[index] + lg.a[index]->w;
			}
			lg.a[index] = lg.a[index]->nextArc;
		}
	}
	for (i = 0; i < lg.numofDot; i++)
	{
		if (i != u)
		{
			if (ahead[i] != INF)
			{
				printf("\n起点到%d的距离为:%lf", i, ahead[i]);
				allLength += ahead[i];
			}
			else
			{
				printf("\n起点到%d的距离为:∞", i);
			}

		}
	}
	printf("\n由此点出发去各地的最短总路径为: %lf", allLength);
	free(ahead);
	free(after);
}
void main()
{
	LGraph lg;
	int nSize, nEdge;
	int u, v, w;
	int judge = 0;
	printf("请输入图的总结点数:\t");
	scanf_s("%d", &nSize);
	printf("请输入图的总边数:\t");
	scanf_s("%d", &nEdge);
	Init(&lg, nSize);
	for (int i = 0; i < nEdge; i++)
	{
		printf("请输入边的指向(u->v)和权重,格式:  u  v   w  :\t");
		scanf_s("%d %d %d", &u, &v, &w);
		int judge = Insert(&lg, u, v, w);
		switch (judge)
		{
		case 0:
			printf("\n输入的u或v有问题,插入失败,请重试");
			break;
		case 5:
			printf("\n此边已存在,插入失败,请重试");
			break;
		default:
			break;
		}
	}
	printf("\n邻接表的深度优先遍历为:\n");
	DFSGraph(lg);
	printf("\n邻接表的宽度优先遍历为:\n");
	BFSGrapg(lg);
	dijkstra(lg);
}

邻接表宽度优先遍历的queue.h

#pragma once
#include "邻接表的基础结构.h"

typedef struct Queue
{
	int front;
	int rear;
	int maxSize;
	int* element;
}Queue;
void queuecreate(Queue* Q, int mSize)
{
	Q->maxSize = mSize;
	Q->element = (int*)malloc(sizeof(int) * mSize);
	Q->front = Q->rear = 0;
}
void queueDestory(Queue* Q)
{
	Q->maxSize = 0;
	Q->front = Q->rear = -1;
	free(Q->element);
}
BOOL queueIsEmpty(Queue* Q)
{
	return Q->front == Q->rear;
}
BOOL queueIsFull(Queue* Q)
{
	return (Q->rear + 1) % Q->maxSize == Q->front;
}
BOOL queueFront(Queue* Q, int* x)
{
	if (queueIsEmpty(Q))
		return false;
	*x = Q->element[(Q->front + 1) % Q->maxSize];
	return true;
}
BOOL EnQueue(Queue* Q, int x)
{
	if (queueIsFull(Q))
		return false;
	Q->rear = (Q->rear + 1) % Q->maxSize;
	Q->element[Q->rear] = x;
	return true;
}
BOOL DeQueue(Queue* Q)
{
	if (queueIsEmpty(Q))
		return false;
	Q->front = (Q->front + 1) % Q->maxSize;
	return true;
}
void queueClear(Queue* Q)
{
	Q->front = Q->rear = 0;
}


邻接表的基础结构.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define ERROR 0 ;
#define OK 1;
#define Overflow 2;
#define Underflow 3;
#define NotPresent 4;
#define Duplicate 5;
typedef int Status;
typedef double ElemType;
typedef bool BOOL;
#define INF 2147483647
typedef struct eNode
{
	int adjVex; //与任意顶点u相邻接的顶点
	ElemType w;
	struct eNode* nextArc;
}ENode;
typedef struct lGraph
{
	int numofDot;   //图的当前顶点数
	int numofEdge;  //图的当前边数
	ENode** a; //指向一维数组指针
}LGraph;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值