图:graph,广度,深度,遍历图,邻接表(详细注释)

下面有图的深度,广度搜索 使用邻接表结构存取的
#include <stdio.h>
#include<stdlib.h>

#define maxnode 30
//注意c里面没有true和false c++有
#define m 20//队列长度

typedef struct st_arc
{
	int adjvex;//存放与之相连的边的id                                    
	int weight;//存放权重
	struct st_arc *nextarc;//指向下一个边结点
}arcnode,*arclink;

typedef struct
{
	int vertex;//顶点数据域  存什么自己看着办
	struct st_arc *firstarc;//指向第一个边节点
}vernode,adjlist[maxnode];//用向量定义图的邻接表表示的 头节点数组

typedef struct  
{
	adjlist glist;//邻接表数组
	int totalE;//边的个数
	int totaldot;//点的个数
	int kind;//图的种类标志
}ALGraph;


int queue[maxnode];


int output(ALGraph *graph)
{
	vernode * pgraphlist = graph->glist;//一指向邻接表头结点的 指针
	arclink temp ;//指向 点节点的临时指针
	for (int i=1;i<=graph->totaldot;i++)
	{
		printf("the no %d dot :",i);//第i个邻接链表的头 指向的一坨节点
		temp = pgraphlist[i].firstarc;//将头赋 给临时指针 以便输出整个邻接链表
		while(temp != NULL)
		{
			printf(" ->%d:权(%d):",temp->adjvex,temp->weight);
			temp = temp->nextarc;//在邻接表中移动临时指针 使之指向下一个 节点
		}
		printf("->NULL");
		printf("\n");
	}
	return 0;
}

void dfs(adjlist g,int k,int visited[])
{
	arclink p;
	int w;
	visited[k]=1;//设置已访问标志
	printf("%d  ",g[k].vertex);//输出 邻接表头节点信息,从第几个邻接表头结点开始搜索
	p=g[k].firstarc;//设置寻找序号为 k的第一个未访问过的邻结点的扫描指针
	while(p!=null)
	{
		w=p->adjvex;//取出邻结点序号 即 弧头的指向
		if (visited[w]==0)//若未访问过则递归调用, 继续以这为弧尾递归访问,访问过了,则检测下一边接点
			dfs(g,w,visited);
		p=p->nextarc;//p顺着边表next指针取出下一个边结点
	}
}

void trave_dfs(adjlist g,int n)//n为点的数量
{
	int i,visited[maxnode];
	for(i=1;i<=n;i++)
		visited[i]=0;//初始化全没访问过,我们标记其为false  就0吧 C里面没false
	for(i=1;i<=n;i++)	//每个点都检测
		if (visited[i]==0)//当这点未被访问过 则深度搜索
			dfs(g,i,visited);//深度随着邻接链表 搜
}

void bfs(adjlist g,int k,int visited[])
{
	int front=0,rear=1,w;//队头,队尾
	arclink temp;//临时指针
	visited[k] = 1;//设置已访问标志
	printf("%d\t",k);
	
	queue[rear] = k;//将顶点序号k入队
	
	while(front != rear)//当队列非空时循环这里还可递归实现
	{
		front = (front+1)%m;//m代表队列的长度  ,这里是循环队列
		w = queue[front];//取出队列中顶点序号w
		temp = g[w].firstarc;//指向表头节点
		while(temp != null)
		{
			if (visited[temp->adjvex] == 0)
			{
				visited[temp->adjvex] = 1;//设置已访问标志
				printf("%d\t",temp->adjvex);
				rear = (rear+1)%m;//队列指针后移
				queue[rear]=temp->adjvex;//将顶点j入队
			}
			temp = temp->nextarc;//顺边表指向下一个结点地址
		}
	}
}

void trave_bfs(adjlist g,int n)
{
	int i,visited[maxnode];//与上面dfs的一样
	for(i=1;i<=n;i++)
		visited[i]=0;
	for(i=1;i<=n;i++)
		if (visited[i]==0)
			bfs(g,i,visited);
}

int main()
{
	freopen("in.txt","r",stdin);
	ALGraph g;
	printf("please input the total dot of graph\n ");
    
    scanf("%d",&g.totaldot);
	//构造n个顶点0个边的图
	for(int i=1;i<=g.totaldot;i++)
	{
		//邻接表的头结点 信息存神马???
		scanf("%d",&g.glist[i].vertex);
		g.glist[i].firstarc = NULL;
	}

	//构造邻接表,, 开始输入无向图的弧头 弧尾 权
    printf("input the total bian of graph");
	scanf("%d",&g.totalE);
	int arctail,archead,weight;
	arcnode *p,*q;
	for (i=1;i<=g.totalE;i++)
	{
		printf("number %d \n",i);
		printf("input the arctail archead and the weight\n");
		scanf("%d %d %d",&arctail,&archead,&weight);
		
		p =(arcnode *)malloc(sizeof(arcnode));
		p->adjvex = archead;//与之相关连的arc头
		p->weight = weight;
		//这里是个倒链表  最后输入的最接近g[i].firstarc  每次先将新加 \
		入的节点指向前面的已经存在的节点,然后邻接表的头结点指向新加入的节点 \
		就像头结点一步一步的向右移动
		p->nextarc = g.glist[arctail].firstarc ;
		g.glist[arctail].firstarc  = p;//这里注意里面是arctail 比如你输入1 2 5 则这里应该在邻接表头节点1的位置加入弧节点的信息

		//由于这是无向图 所以要将这个弧头 放到弧尾作头结点的表中

		q =(arcnode *)malloc(sizeof(arcnode));
		q->adjvex = arctail;//与之相关连的arc尾
		q->weight = weight;//权值
		//这里是个倒链表  最后输入的最接近g[i].firstarc  每次先将新加 \
		入的节点指向前面的已经存在的节点,然后邻接表的头结点指向新加入的节点 \
		就像头结点一步一步的向右移动
		q->nextarc = g.glist[archead].firstarc ;//这里注意里面是archead 比如你输入1 2 5 则这里应该在邻接表头节点2的位置加入弧节点的信息
		g.glist[archead].firstarc  = q;	
	}
	//到这里为止无向图的邻接链表已经建好,要是有向图的话,上面选一个写就ok了
	output(&g);
    //深度搜索
	printf("dfs:\n");
	trave_dfs(g.glist,g.totaldot);//调用深度优先搜索
	printf("\n");
	//广度搜索
	printf("bfs:\n");
	trave_bfs(g.glist,g.totaldot);//调用广度优先搜索
	printf("\n");


	return 0;
} 
/*这里附上in.txt的数据
5
1
2
3
4
5

6
1 2 3
1 3 6
1 4 2
1 5 4
2 4 7
3 5 5*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
邻接表是一种常见的的表示方法,它将每个顶点和与之相连的边都储存在一个链表中。下面是用邻接表表示的C语言代码: ```c #include <stdio.h> #include <stdlib.h> // 定义的最大顶点数 #define MAXV 100 // 定义邻接表中的边结构体 typedef struct EdgeNode { int adjvex; // 相邻顶点编号 struct EdgeNode *next; // 指向下一条边的指针 } EdgeNode; // 定义邻接表中的顶点结构体 typedef struct VertexNode { int data; // 顶点的数据域 EdgeNode *firstedge; // 指向第一条边的指针 } VertexNode; // 定义邻接表结构体 typedef struct { VertexNode adjlist[MAXV]; // 邻接表 int n, e; // 顶点数和边数 } Graph; // 创建邻接表 void createGraph(Graph *G) { int i, j, k; EdgeNode *e; printf("请输入的顶点数和边数:"); scanf("%d %d", &G->n, &G->e); // 初始化邻接表 for (i = 0; i < G->n; i++) { printf("请输入第%d个顶点的数据域:", i + 1); scanf("%d", &G->adjlist[i].data); G->adjlist[i].firstedge = NULL; } // 建立边表 for (k = 0; k < G->e; k++) { printf("请输入第%d条边的两个顶点编号:", k + 1); scanf("%d %d", &i, &j); // 新建一条边 e = (EdgeNode *) malloc(sizeof(EdgeNode)); e->adjvex = j; e->next = G->adjlist[i].firstedge; G->adjlist[i].firstedge = e; // 若为无向,需建立反向边 e = (EdgeNode *) malloc(sizeof(EdgeNode)); e->adjvex = i; e->next = G->adjlist[j].firstedge; G->adjlist[j].firstedge = e; } } // 广度优先遍历 void BFS(Graph G, int v, int visited[]) { int queue[MAXV]; int front = 0, rear = 0; int w; EdgeNode *e; printf("%d ", G.adjlist[v].data); visited[v] = 1; queue[rear++] = v; while (front < rear) { v = queue[front++]; e = G.adjlist[v].firstedge; while (e) { w = e->adjvex; if (!visited[w]) { printf("%d ", G.adjlist[w].data); visited[w] = 1; queue[rear++] = w; } e = e->next; } } } int main() { Graph G; int visited[MAXV] = {0}; int v; createGraph(&G); printf("请输入起始遍历的顶点编号:"); scanf("%d", &v); printf("广度优先遍历结果为:"); BFS(G, v, visited); return 0; } ``` 以上代码实现了邻接表的创建和广度优先遍历。其中,`createGraph()`函数用于创建邻接表,`BFS()`函数用于进行广度优先遍历。具体实现过程可参考代码注释
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值