矩阵版本图的深度优先和广度优先遍历
2014-05-17 21:24
423 查看
链式队列头文件
链式队列实现文件
图的头文件
图的实现文件
测试文件
#ifndef _LINKQUEUE_H_ #define _LINKQUEUE_H_ typedef void LinkQueue; LinkQueue* LinkQueue_Create(); void LinkQueue_Destroy(LinkQueue* queue); void LinkQueue_Clear(LinkQueue* queue); int LinkQueue_Append(LinkQueue* queue, void* item); void* LinkQueue_Retrieve(LinkQueue* queue); void* LinkQueue_Header(LinkQueue* queue); int LinkQueue_Length(LinkQueue* queue); #endif
链式队列实现文件
#include <malloc.h> #include <stdio.h> #include "LinkQueue.h" typedef struct _tag_LinkQueueNode TLinkQueueNode; struct _tag_LinkQueueNode{ TLinkQueueNode* next; void* item; }; typedef struct _tag_LinkQueue{ TLinkQueueNode* front; TLinkQueueNode* rear; int length; }TLinkQueue; LinkQueue* LinkQueue_Create() { TLinkQueue* ret = (TLinkQueue*)malloc(sizeof(TLinkQueue)); if (ret != NULL){ ret->front = NULL; ret->rear = NULL; ret->length = 0; } return ret; } void LinkQueue_Destroy(LinkQueue* queue) { LinkQueue_Clear(queue); free(queue); } void LinkQueue_Clear(LinkQueue* queue) { while (LinkQueue_Length(queue) > 0){ LinkQueue_Retrieve(queue); } } int LinkQueue_Append(LinkQueue* queue, void* item) { TLinkQueue* sQueue = (TLinkQueue*)queue; TLinkQueueNode* node = (TLinkQueueNode*)malloc(sizeof(TLinkQueueNode)); int ret = (sQueue != NULL) && (item != NULL) && (node != NULL); if (ret){ node->item = item; if (sQueue->length > 0){ sQueue->rear->next = node; sQueue->rear = node; node->next = NULL; } else{ sQueue->front = node; sQueue->rear = node; node->next = NULL; } sQueue->length++; } if (!ret){ free(node); } return ret; } void* LinkQueue_Retrieve(LinkQueue* queue) { TLinkQueue* sQueue = (TLinkQueue*)queue; void* ret = NULL; TLinkQueueNode* node = NULL; if ((sQueue != NULL) && (sQueue->length > 0)){ node = sQueue->front; sQueue->front = node->next; ret = node->item; free(node); sQueue->length--; if (0 == sQueue->length){ sQueue->front = NULL; sQueue->rear = NULL; } } return ret; } void* LinkQueue_Header(LinkQueue* queue) { TLinkQueue* sQueue = (TLinkQueue*)queue; void* ret = NULL; if ((sQueue != NULL) && (sQueue->length > 0)){ ret = sQueue->front->item; } return ret; } int LinkQueue_Length(LinkQueue* queue) { TLinkQueue* sQueue = (TLinkQueue*)queue; int ret = -1; if (sQueue != NULL){ ret = sQueue->length; } return ret; }
图的头文件
/*************************************************************** *版权所有 (C)2014,练习。 * *文件名称: *内容摘要: *其它说明: *当前版本: *作 者: *完成日期: * *修改记录1: //修改历史记录,包括修改日期、版本号、修改人及修改内容等 * 修改日期: * 版本号: * 修改人: * 修改内容: ***************************************************************/ #ifndef __MGRAPH_H__ #define __MGRAPH_H__ /************************************************************** 相关宏定义 **************************************************************/ /************************************************************** 相关结构体定义 **************************************************************/ typedef void MGraph;//图的结构体定义,数据封装形式 typedef void MVertex;//顶点的结构体定义,数据封装形式 typedef void (MGraph_printf)(MVertex*);//重命名一个函数类型用来打印信息 /************************************************************** 创建一个顶点数为n的图,并返回其地址 **************************************************************/ MGraph* MGraph_Create(MVertex** v, int n); /************************************************************** 销毁graph指向的图 **************************************************************/ void MGraph_Destroy(MGraph* graph); /************************************************************** 将graph指向的图清空(清空的是顶点之间的边,而不是顶点本身) **************************************************************/ void MGraph_Clear(MGraph* graph); /************************************************************** 在graph所指的图中v1和v2之间加上边,且边的权为w **************************************************************/ int MGraph_AddEdge(MGraph* graph, int v1, int v2, int w); /************************************************************** 将graph所指图中v1和v2之间的边删除,返回权值 **************************************************************/ int MGraph_RemoveEdge(MGraph* graph, int v1, int v2); /************************************************************** 将graph所指图中v1和v2之间的边的权值返回 **************************************************************/ int MGraph_GetEdge(MGraph* graph, int v1, int v2); /************************************************************** 将graph所指图中v顶点的度返回 **************************************************************/ int MGraph_TD(MGraph* graph, int v); /************************************************************** 将graph所指图中的顶点数返回 **************************************************************/ int MGraph_VertexCount(MGraph* graph); /************************************************************** 将graph所指图中的边数返回 **************************************************************/ int MGraph_EdgeCount(MGraph* graph); /************************************************************** **************************************************************/ void MGraph_DFS(MGraph* graph, int v, MGraph_printf* pFunc); /************************************************************** **************************************************************/ void MGraph_BFS(MGraph* graph, int v, MGraph_printf* pFunc); /************************************************************** 将graph所指图中的顶点之间的关系打印出来 **************************************************************/ void MGraph_Display(MGraph* graph, MGraph_printf* pFunc); #endif
图的实现文件
/*************************************************************** *版权所有 (C)2014,公司名称。 * *文件名称: *内容摘要: *其它说明: *当前版本: *作 者: *完成日期: * *修改记录1: //修改历史记录,包括修改日期、版本号、修改人及修改内容等 * 修改日期: * 版本号: * 修改人: * 修改内容: * *修改记录2: //修改历史记录,包括修改日期、版本号、修改人及修改内容等 * 修改日期: * 版本号: * 修改人: * 修改内容: ***************************************************************/ /************************************************************** 头文件引用 **************************************************************/ #include <stdio.h> #include <malloc.h> #include "MGraph.h" #include "LinkQueue.h" /************************************************************** 全局变量定义 **************************************************************/ typedef struct _tag_MGraph{ int count;//顶点数量 MVertex** v;//描述顶点相关数据的指针 int** matrix;//(邻阶矩阵)描述顶点之间的边的关系的指针 }TMGraph; static void recursive_dfs(TMGraph* graph, int v, int visited[], MGraph_printf* pFunc) { int i = 0; pFunc(graph->v[v]); visited[v] = 1;//1表示已经访问过 printf(","); for (i = 0; i < graph->count; i++){//(改为矩阵版本的图以后只需要访问二维矩阵的某一行) if ((!visited[i]) && (graph->matrix[v][i] != 0)){ recursive_dfs(graph, i, visited, pFunc); } } } /********************************************************************** *功能描述: *输入参数: *输出参数: *返回值: *其它说明:需要用到队列 *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYLLDD XXX Name YYY ***********************************************************************/ static void recursive_bfs(TMGraph* graph, int v, int visited[], MGraph_printf* pFunc) { LinkQueue* queue = LinkQueue_Create(); if (queue != NULL) { LinkQueue_Append(queue, graph->v + v);//插入的是地址,因为队列里面不能插入0,所以插入地址,后面访问的时候求 //相对地址来代表实际的数据,graph->v是基地址 visited[v] = 1;//表示已经访问过 while (LinkQueue_Length(queue) > 0)//递归结束的条件,全部遍历过 { int i = 0; v = (MVertex**)LinkQueue_Retrieve(queue) - graph->v;//将队列里面的数据取出,即访问刚刚插入的节点 pFunc(graph->v[v]); printf(","); for (i = 0; i < graph->count; i++)//依次访问下一层(改为矩阵版本的图以后只需要访问二维矩阵的某一行) { if ((!visited[i]) && (graph->matrix[v][i] != 0))//如果没有访问过则加入队列以便访问 { LinkQueue_Append(queue, graph->v +i);//插入地址 visited[i] = 1;//标记已经访问 } } } } LinkQueue_Destroy(queue);//有创建必然伴随着销毁 } /********************************************************************** *功能描述: *输入参数: *输出参数: *返回值: *其它说明: *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYMMDD XXX Name YYY ***********************************************************************/ MGraph* MGraph_Create(MVertex** v, int n) { TMGraph* ret = NULL; if ((v != NULL) && (n > 0)){//有穷非空所以n大于0 ret = (TMGraph*)malloc(sizeof(TMGraph));//申请一个头节点对象 if (ret != NULL){ int* p = NULL; ret->count = n; ret->v = (MVertex**)malloc(sizeof(MVertex*)* n);//申请顶点书据相关的指针空间 ret->matrix = (int**)malloc(sizeof(int*)* n);//动态申请二维数组 p = (int*)calloc(n * n, sizeof(int));//为了避免二重循环,使用calloc使其自动初始化数据空间 if ((ret->v != NULL) && (ret->matrix != NULL) && (p != NULL)){ int i = 0; for (i = 0; i < n; i++){ ret->v[i] = v[i];//保存顶点的数据指针 ret->matrix[i] = p + n*i;//建立一维指针数组到数据空间的链接 } } else{//申请不成功要释放空间 free(p); free(ret->v); free(ret->matrix); free(ret); ret = NULL; } } } return ret; } /********************************************************************** *功能描述: *输入参数: *输出参数: *返回值: *其它说明: *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYMMDD XXX Name YYY ***********************************************************************/ void MGraph_Destroy(MGraph* graph) { TMGraph* tGraph = (TMGraph*)graph; if (tGraph != NULL){ free(tGraph->v);//释放顶点相关的数据空间 free(tGraph->matrix[0]);//必须先释放数据空间 free(tGraph->matrix);//再释放一维指针数组空间 free(tGraph);//最后释放头节点(图本身) } } /********************************************************************** *功能描述:清空的是边,而不是顶点 *输入参数: *输出参数: *返回值: *其它说明: *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYMMDD XXX Name YYY ***********************************************************************/ void MGraph_Clear(MGraph* graph) { TMGraph* tGraph = (TMGraph*)graph; if (tGraph != NULL){ int i = 0, j = 0; for (i = 0; i < tGraph->count; i++){ for (j = 0; j < tGraph->count; j++){ tGraph->matrix[i][j] = 0; } } } } /********************************************************************** *功能描述: *输入参数: *输出参数: *返回值: *其它说明: *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYMMDD XXX Name YYY ***********************************************************************/ int MGraph_AddEdge(MGraph* graph, int v1, int v2, int w) { TMGraph* tGraph = (TMGraph*)graph; int ret = (tGraph != NULL); ret = ret && (v1 >= 0) && (v1 < tGraph->count); ret = ret && (v2 >= 0) && (v2 < tGraph->count); ret = ret && (w >= 0); if (ret){ tGraph->matrix[v1][v2] = w; } return 0; } /********************************************************************** *功能描述: *输入参数: *输出参数: *返回值: *其它说明: *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYMMDD XXX Name YYY ***********************************************************************/ int MGraph_RemoveEdge(MGraph* graph, int v1, int v2) { TMGraph* tGraph = (TMGraph*)graph; int ret = MGraph_GetEdge(graph, v1, v2);//代码复用 if (ret != 0){ tGraph->matrix[v1][v2] = 0; } return ret; } /********************************************************************** *功能描述: *输入参数: *输出参数: *返回值: *其它说明: *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYMMDD XXX Name YYY ***********************************************************************/ int MGraph_GetEdge(MGraph* graph, int v1, int v2) { TMGraph* tGraph = (TMGraph*)graph; int condition = (tGraph != NULL); int ret = 0; condition = condition && (v1 >= 0) && (v1 < tGraph->count); condition = condition && (v2 >= 0) && (v2 < tGraph->count); if (condition){ ret = tGraph->matrix[v1][v2]; } return ret; } /********************************************************************** *功能描述: *输入参数: *输出参数: *返回值: *其它说明: *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYMMDD XXX Name YYY ***********************************************************************/ int MGraph_TD(MGraph* graph, int v) { TMGraph* tGraph = (TMGraph*)graph; int condition = (tGraph != NULL); int ret = 0; condition = condition && (v >= 0) && (v < tGraph->count); if (condition){ int i = 0; for (i = 0; i < tGraph->count; i++){ if (tGraph->matrix[v][i] != 0){ ret++; } if (tGraph->matrix[i][v] != 0){ ret++; } } } return ret; } /********************************************************************** *功能描述: *输入参数: *输出参数: *返回值: *其它说明: *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYMMDD XXX Name YYY ***********************************************************************/ int MGraph_VertexCount(MGraph* graph) { TMGraph* tGraph = (TMGraph*)graph; int ret = 0; if (tGraph != NULL){ ret = tGraph->count; } return ret; } /********************************************************************** *功能描述: *输入参数: *输出参数: *返回值: *其它说明: *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYMMDD XXX Name YYY ***********************************************************************/ int MGraph_EdgeCount(MGraph* graph) { TMGraph* tGraph = (TMGraph*)graph; int ret = 0; if (tGraph != NULL){ int i = 0, j = 0; for (i = 0; i < tGraph->count; i++){ for (j = 0; j < tGraph->count; j++){ if (tGraph->matrix[i][j] != 0){ ret++; } } } } return ret; } /********************************************************************** *功能描述: *输入参数: *输出参数: *返回值: *其它说明: *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYLLDD XXX Name YYY ***********************************************************************/ void MGraph_DFS(MGraph* graph, int v, MGraph_printf* pFunc) { TMGraph* tGraph = (TMGraph*)graph; int condition = (tGraph != NULL); int* visited = NULL; condition = condition && (v >= 0) && (v < tGraph->count); condition = condition && (pFunc != NULL); condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL); if (condition){ int i = 0; recursive_dfs(tGraph, v, visited, pFunc);//表示当V还有相邻的节点未访问时继续深度遍历相邻节点 for (i = 0; i < tGraph->count; i++){//表示当v的所有相邻节点已经被访问过,但是图中还有其他节点虽然不与V相邻, //但还未访问过 if (!visited[i]){ recursive_dfs(tGraph, i, visited, pFunc); } } } free(visited); } /********************************************************************** *功能描述: *输入参数: *输出参数: *返回值: *其它说明: *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYLLDD XXX Name YYY ***********************************************************************/ void MGraph_BFS(MGraph* graph, int v, MGraph_printf* pFunc) { TMGraph* tGraph = (TMGraph*)graph; int condition = (tGraph != NULL); int* visited = NULL; condition = condition && (v >= 0) && (v < tGraph->count); condition = condition && (pFunc != NULL); condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL); if (condition){ int i = 0; recursive_bfs(tGraph, v, visited, pFunc);//表示当V还有相邻的节点未访问时继续深度遍历相邻节点 for (i = 0; i < tGraph->count; i++){//表示当v的所有相邻节点已经被访问过,但是图中还有其他节点虽然不与V相邻, //但还未访问过 if (!visited[i]){ recursive_bfs(tGraph, i, visited, pFunc); } } } free(visited); } /********************************************************************** *功能描述: *输入参数: *输出参数: *返回值: *其它说明: *修改日期 版本号 修改人 修改内容 * ------------------------------------------------------------------------------------------------------ * YYYYMMDD XXX Name YYY ***********************************************************************/ void MGraph_Display(MGraph* graph, MGraph_printf* pFunc) { TMGraph* tGraph = (TMGraph*)graph; if ((tGraph != NULL) && (pFunc != NULL)){ int i = 0; int j = 0; for (i = 0; i < tGraph->count; i++){ printf("%d:", i); pFunc(tGraph->v[i]); printf(" "); } printf("\n"); for (i = 0; i < tGraph->count; i++){ for (j = 0; j < tGraph->count; j++){ if (tGraph->matrix[i][j] != 0){ printf("<"); pFunc(tGraph->v[i]); printf(","); pFunc(tGraph->v[j]); printf(",%d", tGraph->matrix[i][j]); printf(">"); printf(" "); } } } printf("\n"); } }
测试文件
#include <stdio.h> #include <stdlib.h> #include "MGraph.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ void print_data(MVertex* v) { printf("%s", (char*)v); } int main(int argc, char *argv[]) { MVertex* v[] = { "A", "B", "C", "D", "E", "F" }; MGraph* graph = MGraph_Create(v, 6); MGraph_AddEdge(graph, 0, 1, 1); MGraph_AddEdge(graph, 0, 2, 1); MGraph_AddEdge(graph, 0, 3, 1); MGraph_AddEdge(graph, 1, 5, 1); MGraph_AddEdge(graph, 1, 4, 1); MGraph_AddEdge(graph, 2, 1, 1); MGraph_AddEdge(graph, 3, 4, 1); MGraph_AddEdge(graph, 4, 2, 1); MGraph_Display(graph, print_data); MGraph_DFS(graph, 0, print_data); printf("\n"); MGraph_BFS(graph, 0, print_data); printf("\n"); MGraph_Destroy(graph); system("PAUSE"); return 0; }
相关文章推荐
- [置顶] 图:图的邻接矩阵创建、深度优先遍历和广度优先遍历详解
- 图的邻接矩阵存储:深度、广度优先遍历
- 链表版本图的深度优先和广度优先遍历
- 图(邻接矩阵)的深度、广度优先遍历
- 数据结构--图的理解:深度优先和广度优先遍历及其 Java 实现
- 深度优先搜索遍历与广度优先搜索遍历
- 深度优先与广度优先遍历文件
- C语言以邻接表为存储结构的图的构造以及广度优先,深度优先遍历
- 图的遍历:深度优先、广度优先
- 图的邻接矩阵表示以及深度、广度优先遍历
- 图------有向网的建立、深度优先遍历,广度优先遍历
- 图的遍历-(深度优先&广度优先)
- 二叉树的深度和广度优先遍历 - Java实现-2
- 广度优先遍历文件夹和深度递归遍历文件夹
- Java数据结构----图--深度优先遍历BFS和广度优先遍历DFS
- JS 中的广度与深度优先遍历
- 图——广度优先遍历和深度优先遍历——邻接表表示法
- leetcode 329. Longest Increasing Path in a Matrix 矩阵中寻找最长递增序列 + 一个典型的深度优先遍历DFS的做法
- 图的邻接矩阵存储 深度优先遍历 广度优先遍历 C语言实现
- 图的理解:深度优先和广度优先遍历及其 Java 实现