数据结构学习记录

/* 看了其他大神关于这题的代码,都是自己写的,有的地方对于我这个初学数据结构的小白来说有点难理解,我这个主要是MOOC 浙大数据结构 课后所给的代码 修改 完成的,不懂的地方还可以去MOOC看网课理解哈哈。*/

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:
输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:
按照”{ v1​​v2​​…vk}”的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。
输入样例:

  1. 8 6
  2. 0 7
  3. 0 1
  4. 2 0
  5. 4 1
  6. 2 4
  7. 3 5`

输出样例:

  1. { 0 1 4 2 7 }
  2. { 3 5 }
  3. { 6 }
  4. { 0 1 2 7 4 }
  5. { 3 5 }
  6. { 6 }

原题地址

/*	参考资料
1 中国大学MOOC 浙大 数据结构 第六讲 图(上) 
2 DFS
	作者:拉风小宇 
	来源:CSDN 
	原文:https://blog.csdn.net/lafengxiaoyu/article/details/53493080 
	版权声明:本文为博主原创文章,转载请附上博文链接! 
3 BFS
	作者:拉风小宇 
	来源:CSDN 
	原文:https://blog.csdn.net/lafengxiaoyu/article/details/53502873 
	版权声明:本文为博主原创文章,转载请附上博文链接!*/

#include <stdio.h>
#include <stdlib.h>

/* 图的邻接矩阵表示法 */
 
#define MaxVertexNum 100    /* 最大顶点数设为100 */
#define INFINITY 65535        /* ∞设为双字节无符号整数的最大值65535*/
int Visited[MaxVertexNum];/* 标记V已访问 */
#define ERROR 0  
typedef int Vertex;         /* 用顶点下标表示顶点,为整型 */
typedef int WeightType;        /* 边的权值设为整型 */
//typedef char DataType;        /* 顶点存储的数据类型设为字符型 */
typedef int ElementType;
typedef int Position;

/* 边的定义 */
typedef struct ENode *PtrToENode;
struct ENode{
    Vertex V1, V2;      /* 有向边<V1, V2> */
    WeightType Weight;  /* 权重 */
};
typedef PtrToENode Edge;

/* 图结点的定义 */
typedef struct GNode *PtrToGNode;
struct GNode{
    int Nv;  /* 顶点数 */
    int Ne;  /* 边数   */
    WeightType G[MaxVertexNum][MaxVertexNum]; /* 邻接矩阵 */
    //DataType Data[MaxVertexNum];      /* 存顶点的数据 */
    /* 注意:很多情况下,顶点无数据,此时Data[]可以不用出现 */
};
typedef PtrToGNode MGraph; /* 以邻接矩阵存储的图类型 */



struct Node {
	int Data;
	struct Node *Next;
};
 
struct QNode {
	struct Node *rear;
	struct Node *front;
};
typedef struct QNode *Queue;


MGraph CreateGraph( int VertexNum );
void InsertEdge( MGraph Graph, Edge E );
MGraph BuildGraph();

void Visit(Vertex V);
int IsEmpty(Queue Q);
Queue CreateQueue();
int DeleteQ(Queue PtrQ);
void InsertQ(int item, Queue PtrQ);
bool IsEdge(MGraph Graph, Vertex V, Vertex W);

void BFS(MGraph Graph, Vertex S, void(*Visit)(Vertex));
void ListComponentsBFS(MGraph Graph);

void DFS(MGraph Graph, Vertex V, void(*Visit)(Vertex));
void ListComponentsDFS(MGraph Graph);

int main()
{
	MGraph Graph;
	Graph = BuildGraph();
	
	for (int i = 0; i < MaxVertexNum; i++) {
		Visited[i] = false; 
	}
	//printf("下面执行DFS\n");
	ListComponentsDFS( Graph );
	
	/* 	在执行完 ListComponentsDFS( Graph ); 后,需重置 Visited[i] 
		否则 ListComponentsBFS( Graph ); 执行不了。。。 */
	for (int i = 0; i < MaxVertexNum; i++) {
		Visited[i] = false; 
	} 
	//printf("下面执行BFS\n");
	ListComponentsBFS( Graph );
	
	return 0;
}

MGraph CreateGraph( int VertexNum )
{ /* 初始化一个有VertexNum个顶点但没有边的图 */
    Vertex V, W;
    MGraph Graph;
     
    Graph = (MGraph)malloc(sizeof(struct GNode)); /* 建立图 */
    Graph->Nv = VertexNum;
    Graph->Ne = 0;
    /* 初始化邻接矩阵 */
    /* 注意:这里默认顶点编号从0开始,到(Graph->Nv - 1) */
    for (V=0; V<Graph->Nv; V++)
        for (W=0; W<Graph->Nv; W++)  
            Graph->G[V][W] = INFINITY;
    //printf("图初始化完成\n");         
    return Graph; 
}
        
void InsertEdge( MGraph Graph, Edge E )
{
     /* 插入边 <V1, V2> */
     Graph->G[E->V1][E->V2] = E->Weight;    
     /* 若是无向图,还要插入边<V2, V1> */
     Graph->G[E->V2][E->V1] = E->Weight;
}
 
MGraph BuildGraph()
{
    MGraph Graph;
    Edge E;
    Vertex V;
    int Nv, Ne, i;
    //printf("输入顶点数\n"); 
    scanf("%d %d", &Nv, &Ne);   /* 读入顶点个数 */
    Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */
	Graph->Ne = Ne; 
    //printf("输入边数\n");
    //scanf("%d", &(Graph->Ne));   /* 读入边数 */
    if ( Graph->Ne != 0 ) { /* 如果有边 */ 
        E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */ 
        /* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */
        for (i=0; i<Graph->Ne; i++) {
        	//printf("输入一条边的两个端点\n");
            scanf("%d %d", &E->V1, &E->V2); 
            E->Weight = 1;
            /* 注意:如果权重不是整型,Weight的读入格式要改 */
            InsertEdge( Graph, E );
        }
    } 
 
    /* 如果顶点有数据的话,读入数据 */
    //for (V=0; V<Graph->Nv; V++) 
    //    scanf(" %c", &(Graph->Data[V]));
	//printf("图建立完成\n");
    return Graph;
}


void Visit(Vertex V)
{
	printf("正在访问顶点%d\n", V + 1);
} 
 
 
int IsEmpty(Queue Q) {
	return(Q->front == NULL);
};
 
Queue CreateQueue() {
	Queue PtrQ;
	PtrQ = (Queue)malloc(sizeof(struct QNode));
	struct Node *rear;
	struct Node *front;
	rear = (Node*)malloc(sizeof(struct Node));
	rear = NULL;
	front = (Node*)malloc(sizeof(struct Node));
	front = NULL;
	PtrQ->front = front;
	PtrQ->rear = rear;
	return PtrQ;
};
 
int DeleteQ(Queue PtrQ) {
	struct Node *FrontCell;
	int FrontElem;
 
	if (IsEmpty(PtrQ)) {
		printf("队列空");
		return ERROR;
	}
	FrontCell = PtrQ->front;
	if (PtrQ->front == PtrQ->rear)
		PtrQ->front = PtrQ->rear = NULL;
	else {
		PtrQ->front = PtrQ->front->Next;
	}
	FrontElem = FrontCell->Data;
	free(FrontCell);
	return FrontElem;
}
 
void InsertQ(int item, Queue PtrQ) {
	struct Node *FrontCell;
	FrontCell = (Node*)malloc(sizeof(struct Node));
	FrontCell->Data = item;
	FrontCell->Next = NULL;
 
	if (IsEmpty(PtrQ)) {
		PtrQ->front = FrontCell;
		PtrQ->rear = FrontCell;
	}
	else {
		PtrQ->rear->Next = FrontCell;
		PtrQ->rear = FrontCell;
	}
};
/* 邻接矩阵存储的图 - BFS */
 
/* IsEdge(Graph, V, W)检查<V, W>是否图Graph中的一条边,即W是否V的邻接点。  */
/* 此函数根据图的不同类型要做不同的实现,关键取决于对不存在的边的表示方法。*/
/* 例如对有权图, 如果不存在的边被初始化为INFINITY, 则函数实现如下:         */
bool IsEdge(MGraph Graph, Vertex V, Vertex W)
{
	return Graph->G[V][W]<INFINITY ? true : false;
}
 
/* 	Visited[]为全局变量,已经初始化为false 
	在main函数中执行 */

void BFS(MGraph Graph, Vertex S, void(*Visit)(Vertex))
{   /* 以S为出发点对邻接矩阵存储的图Graph进行BFS搜索 */
	Queue Q;
	Vertex V, W;
 
	Q = CreateQueue(); /* 创建空队列, MaxSize为外部定义的常数 */
	
	/* 访问顶点S:此处可根据具体访问需要改写 */
	//Visit(S);
	Visited[S] = true; /* 标记S已访问 */
	InsertQ(S, Q); /* S入队列 */
	printf("{");
	while (!IsEmpty(Q)) {
		V = DeleteQ(Q);  /* 弹出V */
		printf(" %d", V);
		for (W = 0; W<Graph->Nv; W++) /* 对图中的每个顶点W */
									  /* 若W是V的邻接点并且未访问过 */
			if (!Visited[W] && IsEdge(Graph, V, W)) {
				/* 访问顶点W */
				//Visit(W);
				Visited[W] = true; /* 标记W已访问 */
				InsertQ(W, Q); /* W入队列 */
			}
	} /* while结束*/
	printf(" }\n");
}

void ListComponentsBFS(MGraph Graph)
{
	int V;
	for (V=0; V<Graph->Nv; V++) {
		if (!Visited[V]) {
			BFS(Graph, V, Visit);
		}
	}
}

void DFS(MGraph Graph, Vertex V, void(*Visit)(Vertex))
{   /* 以V为出发点对邻接表存储的图Graph进行DFS搜索 */
	Vertex W;
 
	//Visit(V); /* 访问第V个顶点 */
	Visited[V] = true; /* 标记V已访问 */
	printf(" %d", V);
	for (W = 0; W<Graph->Nv;W++ ) /* 对V的每个邻接点W */
		if ((!Visited[W])&&(Graph->G[V][W]==1))    /* 若未被访问 */
			DFS(Graph, W, Visit);    /* 则递归访问之 */
}

void ListComponentsDFS(MGraph Graph)
{
	int V;
	for (V=0; V<Graph->Nv; V++) {
		if (!Visited[V]) {
			printf("{");
			DFS(Graph, V, Visit);
			printf(" }\n");
		}
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值