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;
}