邻接表和邻接矩阵、树的遍历 (DFS和BFS)

文章目录


前言

如果大家还不太熟悉DFSBFS的,可以去看看我前两篇博客,我在浅谈了一下DFSBFS。这篇博客我将讲一下树与图的遍历(DFS和BFS)。这篇博客还会学到稠密图,稀疏图,邻接矩阵,邻接表与树 存储的关系


一、邻接表与邻接矩阵

1.稠密图与稀疏图

图的储存方式分两种:邻接表邻接矩阵。 了解邻接矩阵邻接表之前我们要先学会稠密图、稀疏图

百度百科来说:稠密图、稀疏图。

稀疏图:有很少条边或弧(边的条数|E|远小于|V|²)的图称为稀疏图(sparse graph)。

稠密图:有很多条边或弧  (边的条数|E|接近|V|²)  的图称为稠密图(dense graph)。

简单来说:我们假设某个图的点的个数 为 N, 边的个数为 M, 当  M << N ^ 2 (平方)(当边数远小于点的平方)时称为 稀疏图,当 M ≈ N ^ 2 (当边数约等于点的平方)时称为 稠密图, 如果图为稀疏图的时候,我们一般用邻接表储存,稠密图的时候,一般用邻接矩阵存储。

2.邻接矩阵的存储方式

邻接矩阵:邻接矩阵的储存方式是用一个二维数组g[a][b](a -> b的权值)来表示图的边的信息,a, b都是点, g[a][b] 表示a到b的距离。

图解:(图片来源于百度百科)

 代码:

//运用在最短路或者最小生成树中邻接矩阵的代码方式
while(m --){ //m条边 
	int a, b, w;
	cin >> a >> b >> w;
	g[a][b] = min(g[a][b], w); //取最小的边
}

3.邻接表的存储方式

邻接表:邻接表的储存方式是用单链表来存储,在单链表中,头结点存储的是a, 链表存储的可能是b, c , d。例如:a -> b -> c -> d表示a能到b、a能到c、a能到d

链表结构ne[ ]数组:next指针,e[ ]: a能到的点, w[ ]: a到b的距离。

图解:(图片来源于百度百科) 

代码:

//idx 表示当前节点 
void add(int a, int b, int c){
	e[idx] = b; 
	w[idx] = c;
	ne[idx] = h[a];
	h[a] = idx ++;
}

while(m --){ //m表示边数 
	int a, b, c;
	cin >> a >> b >> c;
	add(a, b, c);
} 

二、树的遍历

1.DFS 

如果对dfs还不太懂的话可以了解一下这个:DFS (深度优先算法)_1234_6的博客-CSDN博客

代码如下:

void dfs(int u){
    st[u] = true;//已经遍历到了
    for(int i = h[u]; i != -1; i = ne[i]){ //遍历链表
        int j = e[i];
        if(!st[j]){
            dfs(j); //递归
            //进行相应的操作
        }
    }
}

2.BFS

如果对bfs还不太懂的话可以了解一下这个:BFS(广度优先算法)_1234_6的博客-CSDN博客

int bfs(){
	queue<int>q;
	q.push(1);
	while(q.size()){
		int t = q.front();
		q.pop();
		for(int i = h[t]; i != -1; i = ne[i]){ //遍历链表
			int j = e[i];
			q.push(j); //入队
		}
	}
}


总结

这篇博客我们了解了BFS和DFS的树的遍历,接下来我们要讲的最短路问题(Dijkstra,Bellman, Spfa, Floyd)算法。

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
邻接矩阵邻接表是两种常见的图的存储方式。其中邻接矩阵是一个二维数组,用于表示图中各个节点之间的关系;邻接表则是由链表组成的数组,用于表示每个节点的邻居节点。 下面分别介绍如何用C语言实现邻接矩阵邻接表的深度优先遍历和广度优先遍历。 1. 邻接矩阵的深度优先遍历 ```c #define MAX_VERTEX_NUM 100 // 最大顶点数 int visited[MAX_VERTEX_NUM]; // 记录节点是否被访问过 void DFS_Matrix(int matrix[][MAX_VERTEX_NUM], int vertex, int n) { visited[vertex] = 1; // 标记节点已被访问 printf("%d ", vertex); // 输出节点值 for (int i = 0; i < n; i++) { if (matrix[vertex][i] && !visited[i]) { // 如果节点i与vertex相邻且未被访问 DFS_Matrix(matrix, i, n); // 递归访问节点i } } } ``` 2. 邻接矩阵的广度优先遍历 ```c #define MAX_VERTEX_NUM 100 // 最大顶点数 int visited[MAX_VERTEX_NUM]; // 记录节点是否被访问过 void BFS_Matrix(int matrix[][MAX_VERTEX_NUM], int vertex, int n) { int queue[MAX_VERTEX_NUM], front = 0, rear = 0; // 定义队列 visited[vertex] = 1; // 标记节点已被访问 printf("%d ", vertex); // 输出节点值 queue[rear++] = vertex; // 将节点加入队列 while (front < rear) { // 队列不为空时循环 int v = queue[front++]; // 取出队首节点 for (int i = 0; i < n; i++) { if (matrix[v][i] && !visited[i]) { // 如果节点i与v相邻且未被访问 visited[i] = 1; // 标记节点已被访问 printf("%d ", i); // 输出节点值 queue[rear++] = i; // 将节点加入队列 } } } } ``` 3. 邻接表的深度优先遍历 ```c #define MAX_VERTEX_NUM 100 // 最大顶点数 int visited[MAX_VERTEX_NUM]; // 记录节点是否被访问过 void DFS_List(LinkedList list[], int vertex) { visited[vertex] = 1; // 标记节点已被访问 printf("%d ", vertex); // 输出节点值 Node *p = list[vertex].head; // 取出节点的邻居链表 while (p) { // 遍历邻居链表 if (!visited[p->data]) { // 如果邻居节点未被访问 DFS_List(list, p->data); // 递归访问邻居节点 } p = p->next; } } ``` 4. 邻接表的广度优先遍历 ```c #define MAX_VERTEX_NUM 100 // 最大顶点数 int visited[MAX_VERTEX_NUM]; // 记录节点是否被访问过 void BFS_List(LinkedList list[], int vertex) { int queue[MAX_VERTEX_NUM], front = 0, rear = 0; // 定义队列 visited[vertex] = 1; // 标记节点已被访问 printf("%d ", vertex); // 输出节点值 queue[rear++] = vertex; // 将节点加入队列 while (front < rear) { // 队列不为空时循环 int v = queue[front++]; // 取出队首节点 Node *p = list[v].head; // 取出节点的邻居链表 while (p) { // 遍历邻居链表 if (!visited[p->data]) { // 如果邻居节点未被访问 visited[p->data] = 1; // 标记节点已被访问 printf("%d ", p->data); // 输出节点值 queue[rear++] = p->data; // 将节点加入队列 } p = p->next; } } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值