邻接表实现图论的各个算法

本文通过邻接表详细讲解了图论中的深度宽度遍历、拓扑排序、单源最短路径Dijkstra算法及最小生成树Prim算法的实现。通过对比邻接表与邻接矩阵的构造和析构,强调了邻接表在存储和操作上的优势。
摘要由CSDN通过智能技术生成

/*在这个代码里面,我主要实现的利用邻接表来存储图论,定义了一个类,里面有一个私有的node **a;这个表示的是一维的指针数组,但是在邻接矩阵实现里面也有一个int *aa,这个是动态生成二维数组,注意两者的类的构造函数和析构函数的区别,是个重点!

主要实现算法:深度宽度遍历,拓扑排序,单源最短路径dijkstra,最小生成树(prim)等等

#include<iostream>
#include<queue>
using namespace std;
const int INF = 123123123;
enum resultcode{success,failure,notpresent,overflow,duplicate};
struct node{
	int adjvex;
	node *next;
	int w;
	node(){
		next = NULL;
	}
	node(int adj, int ww, node *ne)
	{
		next = ne;
		w = ww;
		adjvex = adj;
	}
};
class graph{
private:
	int n, e;
	node** a;
	void dfs(int v, bool *visited);
	void bfs(int v, bool *visited);
	void countindegree(int *indegree);
public:
	graph(int size);
	~graph();
	resultcode insert(int u, int v, int w);
	resultcode remove(int u, int v);
	bool exist(int u, int v);
	void bfs();
	void dfs();
	void toposort(int *order);
	bool toposort1(int *order);
	int prim(int k, int *nearest, int *lowcost);
	//void floyd(int **d, int **path);floyd是采用邻接矩阵的方法实现,这个难实现
	void dijsktra(int k, int *d, int *path);//书上dijskstra是采用邻接矩阵来实现的
};
graph::graph(int size)
{
	n = size;
	e = 0;
	a = new node*[n];
	for (int i = 0; i < n; i++)
	{
		a[i] = NULL;
	}
}
graph::~graph()
{
	node *p,*q;
	for (int i = 0; i < n; i++)
	{
		p = a[i];
		q = p;
		while (p)
		{
			p = p->next;
			delete q;
			q = p;
		}
	}
	delete[]a;
}
bool graph::exist(int u, int v)
{
	if (u<0 || v<0 || u>n - 1 || v>n - 1 || u == v)
		return false;
	node *p = a[u];
	while (p&&p->adjvex != v)
		p = p->next;
	if (!p)
		return false;
	else
		return true;
}
resultcode graph::insert(int u, int v, int w)
{
	if (u<0 || v<0 || u>n - 1 || v>n - 1 || u == v)
		return failure;
	if (exist(u, v))
		return duplicate;
	node *p = new node(v, w, a[u]);//头插法
	a[u] = p;
	e++;
	return success;
}
resultcode graph::remove(int u, int v){
	if (u<0 || v<0 || u>n - 1 || v>n - 1 || u == v)
		return failure;
	node *p = a[u];
	node *q = NULL;
	while (p&&p->adjvex != v)
	{
		q = p;
		p = p->next;
	}
	if (p == NULL)
		return notpresent;
	if (q)//非表头
	{
		q->next = p->next;
	}
	else
		a[u] = a[u]->next;
	delete p;
	e--;
	return success;
}
void graph::dfs(int v, bool *visited)
{
	visited[v] = true;
	cout << v << " ";
	for (node *p = a[v]; p; p = p->next)
	{
		if (!visited[p->adjvex])
			dfs(p->adjvex, visited);
	}
}
void graph::dfs(){
	bool *visited = new bool[n];
	for (int i = 0; i < n; i++)
	{
		visited[i] = false;
	}
	for (int i = 0; i < n; i++)
	{
		if (!visited[i])
			dfs(i, visited);
	}
	delete[]visited;
}
void graph::bfs(int v, bool *visited)
{
	visited[v] = true;
	cout << v << " ";
	queue<int> q;
	q.push(v);
	while (!q.empty())
	{
		int t = q.front();
		q.pop();
		for (node *p = a[t]; p; p = p->next)
		{
			if (!visited[p->adjvex]){
				visited[p->adjvex] = true;
				cout << p->adjvex << " ";
				q.push(p->adjvex);
			}
		}
	}
}
void graph::bfs(){
	bool *visited = new bool[n];
	for (int i = 0; i < n; i++)
	{
		visited[i] = false;
	}
	for (int i = 0; i < n; i++)
	{
		if (!visited[i])
			bfs(i, visited);
	}
	delete []visited;
}
void graph::countindegree(int *indegree)
{
	for (int i = 0; i < n; i++)
	{
		for (node *p = a[i]; p; p = p->next)
		{
			indegree[p->adjvex]++;
		}
	}
}
void graph::toposort(int *order)
{
	int *indegree = new int[n];
	for (int i = 0; i < n; i++)
		indegree[i] = 0;
	countindegree(indegree);
	int top = -1;
	for (int i = 0; i < n; i++)
	{
		if (indegree[i] == 0)
		{
			indegree[i] = top;
			top = i;
		}
	}
	for (int i = 0; i < n; i++)
	{
		if (top == -1)
		{
			cout << "存在环路" << endl;
			return;
		}
		int j = top;
		top = indegree[top];
		order[i] = j;
		cout << j << " ";
		for (node *p = a[j]; p; p = p->next)
		{
			int k = p->adjvex;
			indegree[k]--;
			if (!indegree[k])
			{
				indegree[k] = top;
				top = k;
			}
		}
	}
	delete[]indegree;
}
bool graph::toposort1(int *order)
{
	int *indegree = new int[n];
	for (int i = 0; i < n; i++)
		indegree[i] = 0;
	countindegree(indegree);
	queue<int> q;
	for (int i = 0; i < n; i++)
	{
		if (indegree[i] == 0)
			q.push(i);
	}
	int cnt = 0;
	while (!q.empty())
	{
		int t = q.front();
		q.pop();
		order[cnt++] = t;
		cout << t << " ";
		for (node *p = a[t]; p; p = p->next)
		{
			indegree[p->adjvex]--;
			if (indegree[p->adjvex] == 0)
				q.push(p->adjvex);
		}
	}
	delete[]indegree;
	if (cnt != n)
		return false;
	else
		return true;
}
int  graph::prim(int k, int *nearest, int *lowcost)
{
	int ans = 0;
	bool *mark = new bool[n];
	node *p;
	for (int i = 0; i < n; i++)
	{
		mark[i] = false;
		nearest[i] = -1;
		lowcost[i] = INF;
	}
	mark[k] = true;
	nearest[k] = k;
	lowcost[k] = 0;
	for (int i = 1; i < n; i++)
	{
		for (p = a[k]; p; p = p->next)
		{
			if (!mark[p->adjvex] && lowcost[p->adjvex]>p->w)
			{
				lowcost[p->adjvex] = p->w;
				nearest[p->adjvex] = k;
			}
		}
		int MIN = INF;
		for (int j = 0; j < n; j++)
		{
			if (!mark[j] && lowcost[j] < MIN)
			{
				MIN = lowcost[j];
				k = j;
			}
		}
		ans += MIN;
		mark[k] = true;
	}
	delete[]mark;
	return ans;
}
void graph::dijsktra(int k, int *d, int *path)
{
	bool *mark = new bool[n];
	for (int i = 0; i < n; i++)
	{
		d[i] = INF;
		path[i] = -1;
	}
	for (int i = 0; i < n; i++)
	{
		mark[i] = false;
		node *p = a[k];
		for (; p; p = p->next)
		{
			int j = p->adjvex;
			d[j] = p->w;
			path[j] = k;
		}
	}
	mark[k] = true;
	d[k] = 0;
	for (int i = 1; i < n; i++)
	{
		node *p = a[k];
		for (; p; p = p->next)
		{
			if (mark[p->adjvex] == false && d[p->adjvex]>d[k] + p->w)
			{
				d[p->adjvex] = d[k] + p->w;
				path[p->adjvex] = k;
			}
		}
		int MIN = INF;
		for (int j = 0; j < n; j++)
		{
			if (mark[j] == false && d[j] < MIN)
			{
				MIN = d[j];
				k = j;
			}
		}
		mark[k] = true;
	}
	delete[]mark;
}
int main()
{
	/*graph g(6);
	g.insert(0, 1, 6);//检查插入
	g.insert(0, 2, 1);//检查插入
	g.insert(0, 3, 5);
	g.insert(1, 0, 6);
	g.insert(1, 4, 3);
	g.insert(1, 2, 5);
	g.insert(2, 1, 5);
	g.insert(2, 3, 5);
	g.insert(2, 0, 1);
	g.insert(2, 4, 6);
	g.insert(2, 5, 4);
	g.insert(4, 1, 3);
	g.insert(4, 2, 6);
	g.insert(4, 5, 6);
	g.insert(3, 0, 5);
	g.insert(3, 2, 5);
	g.insert(3, 5, 2);
	g.insert(5, 4, 6);
	g.insert(5, 2, 4);
	g.insert(5, 3, 2);
	int *near = new int[6];
	int *low = new int[6];
	cout << g.prim(0, near, low) << endl;
	delete[]near;
	delete[]low;*/
	/*graph g(7);
	g.insert(0, 1, 1);//检查插入
	g.insert(3, 0, 4);
	g.insert(1, 3, 2);
	g.insert(1, 2, 9);
	g.insert(3, 2, 5);
	g.insert(4, 1, 3);
	g.insert(5, 4, 8);
	g.insert(5, 3, 3);
	g.insert(6, 5, 3);
	g.insert(6, 4, 6);*/
	/*graph g(9);
	g.insert(0, 7, 1);//检查插入
	g.insert(0, 2, 1);
	g.insert(1,4,3);
	g.insert(1, 3, 2);
	g.insert(1, 2, 9);
	g.insert(2, 3, 4);
	g.insert(3, 6, 5);
	g.insert(3, 5, 8);
	g.insert(4, 5, 3);
	g.insert(7, 8, 3);
	g.insert(8, 6, 3);*/
	/*if (g.del(1, 4))
	{
	cout << "成功删除" << endl;
	}
	else
	{
	cout << "删除失败" << endl;
	}//检查删除
	if (g.del(2, 0))
	{
	cout << "成功删除" << endl;
	}
	else
	{
	cout << "删除失败" << endl;
	}*/
	/*if (g.exist(6, 5))
	cout << "存在" << endl;
	else
	cout << "不存在" << endl;
	if (g.exist(2, 0))
	cout << "存在" << endl;
	else
	cout << "不存在" << endl;*/
	/*cout << "接下来是宽度遍历" << endl;
	g.bfs();
	cout << endl;
	cout << "接下来是深度遍历" << endl;
	g.dfs();
	cout << endl;
	//拓扑序列
	int *order = new int[9];
	cout << "拓扑序列" << endl;
	g.toposort(order);
	cout << endl;
	delete []order;*/
	graph g(6);
	g.insert(0, 1, 50);//检查插入
	g.insert(0, 2, 10);//检查插入
	g.insert(0, 4, 70);
	g.insert(1, 4, 10);
	g.insert(1, 2, 15);
	g.insert(2, 3, 15);
	g.insert(2, 0, 20);
	g.insert(4, 3, 30);
	g.insert(3, 1, 20);
	g.insert(3, 4, 35);
	g.insert(5, 3, 3);
	int *d = new int[6];
	int *path = new int[6];
	g.dijsktra(0, d, path);
	for (int i = 0; i < 6; i++)
	{
		cout << d[i] << endl;
	}
	system("pause");
	return 0;
}

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值