数据结构c/c++-----------------图

原理

在这里插入图片描述
图是一些顶点的集合,这些顶点通过边来连接。我们采用邻接表法来实现
在这里插入图片描述
结构体定义
定义图之前,要定义好边和顶点的结构体,具体内容代码中有注释

#define MAX 10
bool visted[MAX];	// 记录顶点有无被访问

// 边的定义
typedef struct _EdgeNode
{
	int adjves;	// 连接的顶点
	int weight;	// 边的权重
	struct _EdgeNode* next;	// 下一条边
}EdgeNode;

// 顶点的定义
typedef struct _VertexNode 
{
	string data;	// 顶点数据
	struct _EdgeNode* first;	// 指向连接的第一条边
}VertexNode, AdjList;

// 图的定义
typedef struct _AdjListGraph
{
	AdjList* adjlist;
	int vex;	// 顶点数
	int edge;	// 边数
}AdjListGraph;

代码实现

初始化

bool initAdj(AdjListGraph& adj)
{
	adj.adjlist = new AdjList[MAX];
	adj.vex = adj.edge = 0;

	for (int i = 0; i < MAX; i++)
	{
		visted[i] = false;
	}

	return true;
}

创建图

我们通过控制台输入的方式来进行图的创建。
location函数是为了根据顶点的数据来找到图中对应的数组下标。
对于具体图的创建,采用的是前插法,可以看看代码。

// 根据数据找到图对应的数组下标
int location(AdjListGraph& adj, string c)
{
	for (int i = 0; i < adj.vex; i++)
	{
		if (adj.adjlist[i].data == c)
		{
			return i;
		}
	}
	return -1;
}

// 创建图
void greateAdj(AdjListGraph& adj)
{
	cout << "输入图的边数和顶点数" << endl;
	cin >> adj.edge >> adj.vex;

	cout << "请输入所有顶点数据" << endl;
	for (int i = 0; i < adj.vex; i++)
	{
		cin >> adj.adjlist[i].data;
		adj.adjlist[i].first = NULL;
	}

	int i1, i2, weigth;
	string a, b;

	for (int i = 0; i < adj.edge; i++)
	{
		cout << "输入两个相邻的顶点和权重" << endl;
		cin >> a >> b >> weigth;
		i1 = location(adj, a);
		i2 = location(adj, b);

		if (i1 != -1 && i2 != -1)
		{
			EdgeNode* node = new EdgeNode;
			node->adjves = i2;
			node->weight = weigth;
			node->next = adj.adjlist[i1].first;

			adj.adjlist[i1].first = node;
		}
		else
		{
			cout << "不存在对应顶点的数组下标" << endl;
			return;
		}

	}
}

深度遍历

visted数组是记录该顶点有无被访问。
深度遍历从一个点开始遍历,然后根据该点的边访问下一个顶点,一直下去,最后出现没有未访问的点返回上一个顶点,访问其他顶点。

void DFS(AdjListGraph& adj, int v)
{
	int next;

	if (visted[v]) return;

	cout << adj.adjlist[v].data << " ";
	visted[v] = true;

	EdgeNode* tmp = adj.adjlist[v].first;

	while (tmp)
	{
		next = tmp->adjves;
		tmp = tmp->next;

		if (visted[next] == false)
		{
			DFS(adj, next);
		}
	}
}

void DFS_Main(AdjListGraph& adj)
{
	for (int i = 0; i < adj.vex; i++)
	{
		if (visted[i] == false)
		{
			DFS(adj, i);
		}
	}
}

广度遍历

广度遍历借助了队列,现访问一个顶点,然后访问相邻的顶点,然后对每个相邻的点,在访问他们相邻的点,知道访问结束。

void BFS(AdjListGraph& adj, int v)
{
	queue<int> q;
	q.push(v);
	int cur;
	int next;

	while (!q.empty())
	{
		cur = q.front();

		q.pop();

		if (visted[cur] == false)
		{
			cout << adj.adjlist[cur].data << " ";
			visted[cur] = true;
		}

		EdgeNode* tmp = adj.adjlist[cur].first;
		while (tmp)
		{
			next = tmp->adjves;
			tmp = tmp->next;
			q.push(next);
		}


	}


}


void BFS_Main(AdjListGraph& adj)
{
	for (int i = 0; i < adj.vex; i++)
	{
		if (visted[i] == false)
		{
			BFS(adj, i);
		}
	}
}

最短路径

采用的深度遍历,对于每一种可能都试一下,然后选出最短的路径。

int min_weigth = 0x7FFFFFFF;	// 最大的int
int steps = 0;					// 步数
int path[MAX] = { 0 };		// 走过的路径
int short_path[MAX] = { 0 };	// 最短的路径

void DFS(AdjListGraph& G, int start, int end, int weights)
{
	if (start == end)
	{
		for (int i = 0; i < steps; i++)
		{
			cout << G.adjlist[path[i]].data << " ";
		}
		cout << "该路径的权重:" << weights << endl;

		if (weights < min_weigth)
		{
			min_weigth = weights;
			memcpy(short_path, path, sizeof(int) * steps);
		}
	}

	visted[start] = true;

	int cur = start;
	EdgeNode* tmp = G.adjlist[cur].first;
	while (tmp)
	{
		cur = tmp->adjves;
		int weight = tmp->weight;

		if (visted[cur] == false)
		{
			visted[cur] = true;
			path[steps++] = cur;
			DFS(G, cur, end, weight + weights);
			visted[cur] = false;
			path[--steps] = 0;
		}


		tmp = tmp->next;
	}


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值