图的存储结构(邻接矩阵法)

#include <malloc.h>
#include <stdio.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;
    
    printf(", ");
    
    for(i=0; i<graph->count; i++)
    {
        if( (graph->matrix[v][i] != 0) && !visited[i] )
        {
            recursive_dfs(graph, i, visited, pFunc);
        }
    }
}


static void bfs(TMGraph* graph, int v, int visited[], MGraph_Printf* pFunc)
{
    LinkQueue* queue = LinkQueue_Create();
    
    if( queue != NULL )
    {
        LinkQueue_Append(queue, graph->v + 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( (graph->matrix[v][i] != 0) && !visited[i] )
                {
                    LinkQueue_Append(queue, graph->v + i);
                    
                    visited[i] = 1;
                }
            }
        }
    }
    
    LinkQueue_Destroy(queue);
}


MGraph* MGraph_Create(MVertex** v, int n)  // O(n)n个结点和数据
{
    TMGraph* ret = NULL;
    
    if( (v != NULL ) && (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));//通过一级指针申请数据空间,并将申请空间中的元素初始化为0
            
            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 + i * n;
                }
            }
            else
            {
                free(p);
                free(ret->matrix);
                free(ret->v);
                free(ret);
                
                ret = NULL;
            }
        }
    }
    
    return ret;
}


void MGraph_Destroy(MGraph* graph) // O(1)
{
    TMGraph* tGraph = (TMGraph*)graph;
    
    if( tGraph != NULL )
    {
        free(tGraph->v);//释放v
        free(tGraph->matrix[0]);//释放数据空间
        free(tGraph->matrix);//释放指针空间
        free(tGraph);//释放tGraph结构体本身
    }
}


void MGraph_Clear(MGraph* graph) // O(n*n)将所有的边清空
{
    TMGraph* tGraph = (TMGraph*)graph;//强制类型转换,因此处数据封装
    
    if( tGraph != NULL )//将邻接矩阵中的元素全部清0
    {
        int i = 0;
        int j = 0;
        
        for(i=0; i<tGraph->count; i++)
        {
            for(j=0; j<tGraph->count; j++)
            {
                tGraph->matrix[i][j] = 0;
            }
        }
    }
}


int MGraph_AddEdge(MGraph* graph, int v1, int v2, int w) // O(1)
{
    TMGraph* tGraph = (TMGraph*)graph;
    int ret = (tGraph != NULL);
    
    ret = ret && (0 <= v1) && (v1 < tGraph->count);//顶点合法性检测
    ret = ret && (0 <= v2) && (v2 < tGraph->count);
    ret = ret && (0 <= w);//权值至少大于零
    
    if( ret )
    {
        tGraph->matrix[v1][v2] = w;//将邻接矩阵中的对应值赋值
    }
    
    return ret;
}


int MGraph_RemoveEdge(MGraph* graph, int v1, int v2) // O(1)
{
    int ret = MGraph_GetEdge(graph, v1, v2);
    
    if( ret != 0 )
    {
        ((TMGraph*)graph)->matrix[v1][v2] = 0;
    }
    
    return ret;//返回值为删除那条边的权值
}


int MGraph_GetEdge(MGraph* graph, int v1, int v2) // O(1)
{
    TMGraph* tGraph = (TMGraph*)graph;
    int condition = (tGraph != NULL);
    int ret = 0;
    
    condition = condition && (0 <= v1) && (v1 < tGraph->count);//合法性检测,判断删除的那条边上权值是否大于0
    condition = condition && (0 <= v2) && (v2 < tGraph->count);
    
    if( condition )
    {
        ret = tGraph->matrix[v1][v2];
    }
    
    return ret;
}


int MGraph_TD(MGraph* graph, int v) // O(n)
{
    TMGraph* tGraph = (TMGraph*)graph;
    int condition = (tGraph != NULL);
    int ret = 0;
    
    condition = condition && (0 <= v) && (v < tGraph->count);
    
    if( condition )
    {
        int i = 0;
        
        for(i=0; i<tGraph->count; i++)//只需遍历一次和顶点相关的边即可得出度数
        {
            if( tGraph->matrix[v][i] != 0 )//从第v行开始,表示出度不为零时
            {
                ret++;
            }
            
            if( tGraph->matrix[i][v] != 0 )//从第v列,表示入度
            {
                ret++;
            }
        }
    }
    
    return ret;
}


int MGraph_VertexCount(MGraph* graph) // O(1)
{
    TMGraph* tGraph = (TMGraph*)graph;
    int ret = 0;
    
    if( tGraph != NULL )
    {
        ret = tGraph->count;//头结点中的存储count
    }
    
    return ret;
}


int MGraph_EdgeCount(MGraph* graph) // O(n*n)
{
    TMGraph* tGraph = (TMGraph*)graph;
    int ret = 0;
    
    if( tGraph != NULL )
    {
        int i = 0;
        int j = 0;
        
        for(i=0; i<tGraph->count; i++)
        {
            for(j=0; j<tGraph->count; j++)
            {
                if( tGraph->matrix[i][j] != 0 )//邻接矩阵中边不为零的元素表示数目
                {
                    ret++;//如果图为无向图,则还需要以遍历结束后数目除以2即可
                }
            }
        }
    }
    
    return ret;
}


void MGraph_DFS(MGraph* graph, int v, MGraph_Printf* pFunc)//深度优先遍历
{
    TMGraph* tGraph = (TMGraph*)graph;
    int* visited = NULL;
    int condition = (tGraph != NULL);
    
    condition = condition && (0 <= v) && (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);
        
        for(i=0; i<tGraph->count; i++)
        {
            if( !visited[i] )
            {
                recursive_dfs(tGraph, i, visited, pFunc);
            }
        }
        
        printf("\n");
    }
    
    free(visited);
}


void MGraph_BFS(MGraph* graph, int v, MGraph_Printf* pFunc)//广度优先遍历
{
    TMGraph* tGraph = (TMGraph*)graph;
    int* visited = NULL;
    int condition = (tGraph != NULL);
    
    condition = condition && (0 <= v) && (v < tGraph->count);
    condition = condition && (pFunc != NULL);
    condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL);
    
    if( condition )
    {
        int i = 0;
        
        bfs(tGraph, v, visited, pFunc);
        
        for(i=0; i<tGraph->count; i++)
        {
            if( !visited[i] )
            {
                bfs(tGraph, i, visited, pFunc);
            }
        }
        
        printf("\n");
    }
    
    free(visited);
}


void MGraph_Display(MGraph* graph, MGraph_Printf* pFunc) // O(n*n)
{
    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");
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值