图的邻接链表实现


AdjacencyListGraph.h

#ifndef ADJACENCYLISTGRAPH_H
#define ADJACENCYLISTGRAPH_H


#define FALSE 0
#define TRUE  1

typedef void (* freefun)(void* data);

typedef int VertexType;

typedef int VertexDataType;

typedef enum
{
    TREE_EDGE,
    BACKE_EDGE,
    FORWARD_CROSS_EDGE,
    EDGE_BUTT
}EDGE_TYPE;

#define VERTEXDATATYPE_DEFAULT 0

/*the vertex is not alway int like 1, 2 ..., some time it could A, B..., 
  so define VERTEX_BASE here for other kind index base */
#define VERTEX_BASE  1  

typedef struct AdjNode
{
    VertexType      VertexIndex;
    int             weight;
    EDGE_TYPE       edgetype;
    void            *info;
    struct AdjNode  *next;

}AdjNode;


typedef struct VNode
{
    VertexDataType  data;
    VertexType      vertexIndex;
    int             edgenumber;
    AdjNode*   firstarc;
} VNode;

typedef struct ALGraph
{
    VNode* vertices;
    int     vexnum;  /*Vertex number*/
    int     edgenum;  /*edge number*/
    int     kind;
}AdjacencyListLGraph;




AdjacencyListLGraph*  AdjacencyListGraphCreate(int vertexnum,  int kind);
AdjNode* AdjacencyListGraphCreateNode(VertexType VertexIndex, int weight, void* info);
int AdjacencyListGraphAddEdge(AdjacencyListLGraph *Graph, VertexType SourceVertex, AdjNode* node);
int AdjacencyListGraphRelease(AdjacencyListLGraph **Graph, freefun freememfun);
void AdjacencyListGraphPrint(AdjacencyListLGraph *Graph);
int AdjacencyListGraphIsIndexValid(AdjacencyListLGraph *Graph, VertexType VertexIndex);
VNode* AdjacencyListGraphGetVNodeByVexInd(AdjacencyListLGraph *Graph, VertexType SourceVertex);
VertexType AdjacencyListGraphGetVertexInd(AdjNode* node);
AdjNode* AdjacencyListGraphGetAdjNodeFromVNode(VNode *vnode);
void AdjacencyListGraphSetEdgeType(AdjNode  *adjnode, EDGE_TYPE edgetype);
AdjacencyListLGraph * AdjacencyListGraphTransposition(AdjacencyListLGraph * legacyGraph);


#endif


AdjacencyListGraph.c


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




int AdjacencyListGraphIsIndexValid(AdjacencyListLGraph *Graph, VertexType VertexIndex)
{
    int VexIndex = VertexIndex - VERTEX_BASE;
    if((VexIndex >= 0) &&(VexIndex <= Graph->vexnum))
    {
        return TRUE;
    }

    return FALSE;
    
}

/*****************************************************************************
 * AdjacencyListGraphCreate
 *
 * create a AdjacencyListGraph.

   
 *@vertexnum:    The vertex number in a Graph
 *@kind:         The kind of Graph 

 return:         RETURN the AdjacencyListLGraph if success, else NULL
******************************************************************************/
AdjacencyListLGraph*  AdjacencyListGraphCreate(int vertexnum,  int kind)
{
    AdjacencyListLGraph* graph = NULL;
    int i;

    if(vertexnum <= 0)
    {
        printf("vertexnum(%d) is less than 1 %s, %d \n",vertexnum, __FILE__, __LINE__);

        return NULL;
    }

    graph = (AdjacencyListLGraph*)malloc(sizeof(AdjacencyListLGraph));
    if(NULL == graph)
    {
        printf("malloc failed %s, %d \n", __FILE__, __LINE__);

        return NULL;
    }

    graph->vertices = (VNode*)malloc(vertexnum * sizeof(VNode));
    if(NULL == graph->vertices)
    {
        printf("malloc failed %s, %d \n", __FILE__, __LINE__);

        free(graph);

        return NULL;        
    }

    for(i = 0; i < vertexnum; i++)
    {
        graph->vertices[i].data = VERTEXDATATYPE_DEFAULT;
        graph->vertices[i].firstarc = NULL;
        graph->vertices[i].edgenumber = 0;
        graph->vertices[i].vertexIndex = i + VERTEX_BASE;
    }

    graph->vexnum  = vertexnum;
    graph->edgenum = 0;
    graph->kind    = kind;

    return graph;
    
}

/*****************************************************************************
 * AdjacencyListGraphCreateNode
 *
 * create a AdjNode .

   
 *@VertexIndex:  The Vertex Index, it like 1, 2, 3.... or A, B, C(The VERTEX_BASE will be A).
 *@weight:       The weight of the Edge  
 *info:          The data stored in the adjnode. if no data, it could be NULL

 return:         RETURN the AdjNode if success, else NULL
******************************************************************************/
AdjNode* AdjacencyListGraphCreateNode(VertexType VertexIndex, int weight, void* info)
{

    AdjNode*  adjnode = NULL;

    adjnode = (AdjNode*)malloc(sizeof(AdjNode));
    if(NULL == adjnode)
    {
        printf("malloc failed %s, %d \n", __FILE__, __LINE__);

        return NULL;        
    }

    adjnode->VertexIndex = VertexIndex;
    adjnode->weight  = weight;
    adjnode->info = info;
    adjnode->edgetype = EDGE_BUTT;
    adjnode->next = NULL;

    return adjnode;
}


VertexType AdjacencyListGraphGetVertexInd(AdjNode* node)
{
     return node->VertexIndex;
}


/*****************************************************************************
 * AdjacencyListGraphAddEdge
 *
 * add the AdjNode to the Graph, .

   
 *@Graph:  the  Adjacency list graph which the adjnode added.
 *@SourceVertex: The source vertex index, it should base from 
 *node:          The adjnode added to the Graph.

 return:    TRUE if success, else FALSE
******************************************************************************/
int AdjacencyListGraphAddEdge(AdjacencyListLGraph *Graph, VertexType SourceVertex, AdjNode* node)
{

    VNode   *vnode;
    AdjNode *adjnode;
    int      srcindex = SourceVertex - VERTEX_BASE;

    if(NULL == Graph)
    {
        printf("input Graph is null %s, %d \n", __FILE__, __LINE__);

        return FALSE;
    }

    /*the sourceVertex is start from 1..., and vexnum is zero base*/

    
    if(FALSE == AdjacencyListGraphIsIndexValid(Graph, SourceVertex))
    {
        printf("input SourceVertex(%d) is equal or bigger than vexnum(%d) %s, %d \n",SourceVertex, Graph->vexnum,  __FILE__, __LINE__);

        return FALSE;       
    }

    vnode = &(Graph->vertices[srcindex]);

    /*no the first one*/
    if(NULL != vnode->firstarc)
    {
        adjnode = vnode->firstarc;
        node->next = adjnode;
        vnode->firstarc = node;
        vnode->edgenumber++;
    }
    else  /*if it is the first node in the list*/
    {
        vnode->firstarc = node;
        vnode->edgenumber++;
    }

    Graph->edgenum++;

    return TRUE;
    
}


/*****************************************************************************
 * AdjacencyListGraphRelease
 *
 * Free the Adjacency list graph memory. if the info in the AdjNode need free by
   user, user should define the freefun.

   
 *@Graph:  the  Adjacency list graph which need to free the memory
 *@freememfun: the user used this function to free the info in the AdjNode;
               if the user did not need to free this memory, it should be NULL,
               if the user use the function free to release the memory, it could
               use free as in it.

******************************************************************************/

int AdjacencyListGraphRelease(AdjacencyListLGraph **Graph, freefun freememfun)
{
    VNode    *vnode = NULL;
    AdjNode  *adjnode = NULL, *nextnode = NULL;
    int      i;

    if(NULL == (*Graph))
    {
        printf("input Graph is null %s, %d \n", __FILE__, __LINE__);

        return FALSE;         
    }

    /*go through the vertices, and free all the adjnode*/
    for(i = 0; i < (*Graph)->vexnum; i++)
    {
        vnode = &((*Graph)->vertices[i]);

        adjnode = vnode->firstarc;
        
        
        while(NULL != adjnode)
        {
            nextnode = adjnode->next;

            if((NULL != freememfun) &&(NULL != adjnode->info))
            {
                freememfun(adjnode->info);  /*free the info in the adjnode*/
            }

            free(adjnode); /*free the adjnode*/

            adjnode = nextnode;
            
        }
    }

    free((*Graph)->vertices);  /*free the vertex array*/

    free((*Graph)); /*free the graph*/

    (*Graph) = NULL;

    return TRUE;
    
}


void AdjacencyListGraphPrint(AdjacencyListLGraph *Graph)
{
    VNode    *vnode = NULL;
    AdjNode  *adjnode = NULL;
    int i;

    printf("Print the Graph \n");

    for(i = 0; i < Graph->vexnum; i++)
    {
        printf("\n %d -->", i+1);

        vnode = &(Graph->vertices[i]);

        adjnode = vnode->firstarc;

        while(NULL != adjnode)
        {
            

            printf("%d -->", adjnode->VertexIndex);

            adjnode = adjnode->next;
        }
        printf("NULL \n");
    }

    return;
    
}

VNode* AdjacencyListGraphGetVNodeByVexInd(AdjacencyListLGraph *Graph, VertexType SourceVertex)
{
    int      srcindex = SourceVertex - VERTEX_BASE;
    
    if(NULL == Graph)
    {
        printf("input Graph is null %s, %d \n", __FILE__, __LINE__);

        return FALSE;
    }

    
    if(FALSE == AdjacencyListGraphIsIndexValid(Graph, SourceVertex))
    {
        printf("input SourceVertex(%d) is equal or bigger than vexnum(%d) %s, %d \n",SourceVertex, Graph->vexnum,  __FILE__, __LINE__);

        return FALSE;       
    }


    return &(Graph->vertices[srcindex]);
}

AdjNode* AdjacencyListGraphGetAdjNodeFromVNode(VNode *vnode)
{
    return vnode->firstarc;
}


void AdjacencyListGraphSetEdgeType(AdjNode  *adjnode, EDGE_TYPE edgetype)
{
    adjnode->edgetype = edgetype;
}


/*****************************************************************************
 * AdjacencyListGraphTransposition
 *
 * Get the trasposition of a graph, for the transpositon graph, the destion node 
   and source should convertthe data from the legacy edge, 
   the *info is same for the legacy graph
   and transpsed graph, so for release transposition graph, the free fucntion
   should be NULL, AND and it should be release by legacy grahp. some other
   operation on the info should be carefully.

   
 *@legacyGraph: The original graph for transposing.

 return : the Transposition of graph if success, else NULL

******************************************************************************/
AdjacencyListLGraph * AdjacencyListGraphTransposition(AdjacencyListLGraph * legacyGraph)
{
    AdjacencyListLGraph *TranspostionGraph = NULL;
    int i;
    AdjNode* legacyAdjnode, *newAdjnode;
    VNode*   legacyvnode, *newvnode;
    VertexType  newVertexIndex;
    

    if(NULL == legacyGraph)
    {
        printf("input Graph is null %s, %d \n", __FILE__, __LINE__);

        return NULL;
    }

    TranspostionGraph  = AdjacencyListGraphCreate(legacyGraph->vexnum, legacyGraph->kind);
    if(NULL == TranspostionGraph)
    {
        printf("Creat Graph failed %s, %d \n", __FILE__, __LINE__);
        return NULL;
    }

    for(i = 0; i < legacyGraph->vexnum; i++)
    {
        legacyvnode = AdjacencyListGraphGetVNodeByVexInd(legacyGraph, i + VERTEX_BASE);
        legacyAdjnode = legacyvnode->firstarc;

        while(NULL != legacyAdjnode)
        {
            /*for the transpositon graph, the destion node and source should convert*/
            newVertexIndex =  i + VERTEX_BASE;  /*the source vertex become destion vertex*/
            /*other data from the legacy edge, the *info is same for the legacy graph
              and transpsed graph, so for release transposition graph, the free fucntion
              should be NULL, AND and it should be release by legacy grahp. some other
              operation on the info should be carefully.*/
            newAdjnode = AdjacencyListGraphCreateNode(newVertexIndex, 
                            legacyAdjnode->weight, legacyAdjnode->info);
            AdjacencyListGraphAddEdge(TranspostionGraph, legacyAdjnode->VertexIndex,
                                      newAdjnode);

            legacyAdjnode = legacyAdjnode->next;
        }
    }

    return TranspostionGraph;
 
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值