建图的三种方式---邻接矩阵,邻接表,链式前向星

邻接矩阵

# include
using namespace std;
const int maxn = 1e3;
int graph[maxn][maxn];
void init(int n,int m) {
	//邻接矩阵
	for (int i = 1;i <= n;i++) {//图中的点从1开始
		for (int j = 1;j <= n;j++) {
			graph[i][j] = 0;
		}
	}
}
void build(int n, int m) {
	//邻接矩阵的建立
	for (int i = 0;i < m;i++) {
		int x1, y1, c1;
		cin >> x1 >> y1 >> c1;
		graph[x1][y1] = c1;//有向图
		//graph[x1][y1] = graph[y1][x1] = c1;//无向图
	}
}
void print(int n, int m) {
	//邻接矩阵的遍历输出
	for (int i = 1;i <= n;i++) {//图中的点从1开始
		for (int j = 1;j <= n;j++) {
			if(graph[i][j]!=0)//为零则是无边的
			cout << i << "->" << j << "==" << graph[i][j] << endl;
		}
	}
}
int main() {
	int n, m;
	cin >> n >> m;
	init(n, m);
	build(n,m);
	print(n, m);
}

局限性:

  • 仅限于点数小于一千时,否则二维数组的内存会爆。
  • 不可存重边的权值,除非该数组存放是是几条重边

邻接表

链式前向星

# include

using namespace std;
const int maxn = 1e4;
//链式前向星
struct edge {
	int to;//存放下一个与之相连的结点
	int next;//存放上一个与之相连结点的下标(在存放的过程中不断更新)
	int val;//权值
	

}Edge[maxn];
int head[maxn];                    //存放当前与下标相连的最后面的那个点的下标
void init(int n,int m) {
	for (int i = 0;i < maxn;i++) {//此处很重要!!!!!
		Edge[i].next = -1;        //因为放的是下标,所有包含0那么此时初始化就需要从-1开始
		head[i] = -1;
	}
}int cnt = 0;
void add_(int x1,int y1, int c1) {

		Edge[cnt].to = y1;
		Edge[cnt].val = c1;
		Edge[cnt].next = head[x1];//与x1相连的上一个结点的位置
		head[x1] = cnt++;//更新与x1相连结点的位置
}
void print(int n, int m) {
	for (int i = 1;i <= n;i++) {
		for (int j = head[i];j != -1;j = Edge[j].next) {
			cout << i << "->" << Edge[j].to << "==" << Edge[j].val << endl;
		}
	}
}
int main() {
	int n, m;
	cin >> n >> m;
	init(n, m);
	for (int i = 0;i < m;i++) {
		int x1, y1, c1;
		cin >> x1 >> y1 >> c1;
		add_(x1,y1,c1);
	}
	
	print(n, m);
}
/*
粗俗的理解:相当于用静态的结构体数组模拟了vector的动态进程
vector是比较慢的,每一次内存大了需要进行动态的扩容,很耗时
head数组用来存放最终结点最后连接的那个邻接点的下标(记住存放的是下标,这也为后面访问一系列邻接点提供了头)
Edge结构体数组,中to是存放目前结点所连接的下一个结点,val存放的是这条边所带的权值,next 存放的是这个点在目前结点之前所连接的结点的下标,而这个下标是不断的在head中存放的,(因为在建图的过程中,head数组里面不断放入的是该节点的上一个邻接点的位置)
*/

你可能感兴趣的:(暑训,数据结构)