1、邻接链表法
基本思想:
示例:
2、数据结点定义
3、算法实现
数据类型声明
/*
* 邻接链表法,数据结构定义
*/
typedef struct _struct_lgraph
{
int count; //存储结点数目
LVertex **data; //一个指针数组,记录与顶点相关的数据描述
Linklist **la; //一个指针数组,记录每个结点的链表地址
}TLGraph;
/*
* 链表数据结点定义
*/
typedef struct _struct_listnode
{
LinklistNode header;
int v; //保存与该结点相连的另一结点编号
int w; //保存该边的权值
}TListnode;
创建邻接链表:
/*
* 创建并返回有n个顶点的图
* 参数:
data: 存放各顶点数据地址的指针数组
n: 该图顶点的数目
* 返回值:
如果成功,返回该图的有效地址;
如果失败,返回NULL;
*/
LGraph* LGraph_Create(LVertex** v, int n)
{
TLGraph *tgraph = NULL;
if((v != NULL) && ( n > 0))
{
tgraph = (TLGraph*)malloc(sizeof(TLGraph));
if(tgraph != NULL)
{
tgraph->count = n;
//申请空间存放结点描述信息的地址
tgraph->data = (LVertex**)malloc(sizeof(LVertex*) * n);
//申请空间,并初始化为0,存放每个结点的链表地址
tgraph->la = (Linklist**)calloc(n, sizeof(Linklist*));
if((tgraph->data != NULL)&&(tgraph->la != NULL))
{
for(int i = 0; i < tgraph->count; i++)
{
tgraph->data[i] = v[i]; //保存结点描述信息
}
int condition = 1;
//为每个结点创建链表,并将地址保存在la地址数组中
for(int i = 0; (i < tgraph->count) && (condition); i++)
{
condition = condition && ((tgraph->la[i] = List_Create()) != NULL);
}
}
else
{
//如果上述操作出现错误,则将所有资源释放,切记要销毁每个结点的链表
if(tgraph->la != NULL)
{
for(int i = 0; i < tgraph->count; i++)
{
List_Destroy(tgraph->la[i]);
}
}
free(tgraph->data);tgraph->data = NULL;
free(tgraph->la);tgraph->la = NULL;
free(tgraph);tgraph = NULL;
}
}
}
return tgraph;
}
添加和删除边:
/*
在graph所指图中的v1和v2之间加上边,且边的权为w
* 参数:
graph: 指向图的指针
v1: 顶点1
v2: 顶点2
w: 两顶点之间边的权值
* 返回值:
如果成功,返回非0值
如果失败,返回0
*/
int LGraph_AddEdge(LGraph* graph, int v1, int v2, int w)
{
TLGraph *tgraph = (TLGraph*)graph;
TListnode *node = NULL;
int iret = (tgraph != NULL);
iret = iret && ( 0 <= v1) && (v1 < tgraph->count);
iret = iret && (0 <= v2) && (v2 < tgraph->count);
iret = iret && (w > 0);
iret = iret && ((node = (TListnode*)malloc(sizeof(TListnode))) != NULL);
if(iret)
{
node->v = v2;
node->w = w;
List_Insert(tgraph->la[v1], (LinklistNode*)node, List_Length(tgraph->la[v1]));
}
return iret;
}
/*
将graph所指图中v1和v2之间的边删除,返回权值
* 参数:
graph: 指向图的指针
v1: 顶点1
v2: 顶点2
* 返回值:
如果成功,返回两顶点之间边的权值,该值非负
如果失败,返回-1
*/
int LGraph_RemoveEdge(LGraph* graph, int v1, int v2)
{
TLGraph *tgraph = (TLGraph*)graph;
int iret = -1;
int condition = (tgraph != NULL);
condition = condition && (0 <= v1) && (v1 < tgraph->count);
condition = condition && (0 <= v2) && (v2 < tgraph->count);
if(condition)
{
if(tgraph->la != NULL)
{
TListnode *node = NULL;
for(int i = 0; i < List_Length(tgraph->la[v1]); i++)
{
node = (TListnode*)List_Get(tgraph->la[v1], i);
if(node != NULL)
{
if(node->v == v2)
{
iret = node->w;
List_Delete(tgraph->la[v1], i);
free(node);
node = NULL;
break;
}
}
}
}
}
return iret;
}
返回顶点度数(TD):
/*
将graph所指图中v顶点的度数
* 参数:
graph: 指向图的指针
v: 顶点
* 返回值:
如果成功,返回顶点v的度数,该值非负
如果失败,返回-1
*/
int LGraph_TD(LGraph* graph, int v)
{
TLGraph *tgraph = (TLGraph*)graph;
int iret = -1;
if((tgraph != NULL) && (0 <= v) && (v < tgraph->count))
{
if(tgraph->la != NULL)
{
iret = 0;
TListnode *node = NULL;
for(int i = 0; i < tgraph->count; i++)
{
for(int j = 0; i < List_Length(tgraph->la[i]); j++)
{
node = (TListnode*)List_Get(tgraph->la[i], j);
if(node != NULL)
{
if(node->v == v)
{
iret++;
}
}
}
}
iret += List_Length(tgraph->la[v]);
}
}
return iret;
}
4、小结
5、完整源码下载
github地址:稍后放出。。。