与邻接链表图非常相似,相对而言多了前向边的处理
使用 C语言 十字链表 实现了: 添加边,删除边,查找边的功能
#include <stdio.h>
#include <stdlib.h>
typedef int bool;
#define false 0;
#define true 1;
typedef struct Edge {
double weight;
int source;
int dest;
struct Edge * linkPre;
struct Edge * linkNex;
} Edge;
typedef struct CrossListMap {
int n;
int * data;
struct Edge ** headPre;
struct Edge ** headNex;
} CrossListMap;
void InitMap(struct CrossListMap * map, int n);
void DestroyMap(struct CrossListMap * map);
struct Edge * AddEdge(struct CrossListMap * map,
unsigned int source/*0~n-1*/,
unsigned int dest/*0~n-1*/,
double weight);
bool RemoveEdge(struct CrossListMap * map,
unsigned int source/*0~n-1*/,
unsigned int dest/*0~n-1*/);
struct Edge * GetEdge(struct CrossListMap * map,
unsigned int source/*0~n-1*/,
unsigned int dest/*0~n-1*/);
void print1(struct CrossListMap * map);
void print2(struct CrossListMap * map);
// 初始化有 n 个节点的图
void InitMap(struct CrossListMap * map, int n) {
map->n = n;
map->data = (int*)malloc(n*sizeof(int));
map->headPre = (struct Edge**)malloc(n*sizeof(struct Edge*));
map->headNex = (struct Edge**)malloc(n*sizeof(struct Edge*));
for(int i=0; i<n; i++) {
map->headPre[i] = NULL;
map->headNex[i] = NULL;
}
}
void DestroyMap(struct CrossListMap * map) {
free(map->data);
for(int i=0; i<map->n; i++) {
struct Edge* nex;
for (struct Edge* e=map->headNex[i]; e!=NULL; e=nex) {
nex = e->linkNex;
free(e);
}
}
free(map->headPre);
free(map->headNex);
}
struct Edge * AddEdge(struct CrossListMap * map,
unsigned int source/*0~n-1*/,
unsigned int dest/*0~n-1*/,
double weight)
{
if(map->n < source || map->n < dest || map == NULL) return NULL;
struct Edge * edge = (struct Edge *)malloc(sizeof(struct Edge));
edge->weight = weight;
edge->source = source;
edge->dest = dest;
//-------------部分一 后向边的处理-------------
struct Edge * nex1 = map->headNex[source];
struct Edge * nex2 = nex1;
// 查找插入位置
while (nex2 != NULL) {
if(dest < nex2->dest)
break;
else if(dest == nex1->dest)
return NULL;
nex1 = nex2;
nex2 = nex2->linkNex;
}
// 插入新的边为第一条边
if (nex1 == NULL || dest < nex1->dest) {
map->headNex[source] = edge;
} else {
nex1->linkNex = edge;
}
edge->linkNex = nex2;
//-------------部分二 前向边的处理-------------
struct Edge * pre1 = map->headPre[dest];
struct Edge * pre2 = pre1;
// 查找插入位置
while (pre2 != NULL) {
if(source < pre2->source)
break;
else if(source == pre1->source)
return NULL;
pre1 = pre2;
pre2 = pre2->linkPre;
}
// 插入新的边为第一条边
if (pre1 == NULL || source < pre1->source) {
map->headPre[dest] = edge;
} else {
pre1->linkPre = edge;
}
edge->linkPre = pre2;
return edge;
}
bool RemoveEdge(struct CrossListMap * map,
unsigned int source/*0~n-1*/,
unsigned int dest/*0~n-1*/) {
if(map->n < source || map->n < dest || map == NULL) return false;
//-------------部分一 后向边的处理-------------
struct Edge * nex1 = map->headNex[source];
struct Edge * nex2 = nex1;
while(nex2 != NULL && nex2->dest < dest && nex2->linkNex != NULL) {
nex1 = nex2;
nex2 = nex2->linkNex;
}
if(nex2 == NULL || nex2->dest != dest) return false;
if(nex1 == nex2) {
map->headNex[source] = nex2->linkNex;
} else {
nex1->linkNex = nex2->linkNex;
}
//-------------部分二 前向边的处理-------------
struct Edge * pre1 = map->headPre[dest];
struct Edge * pre2 = pre1;
while(pre2 != NULL && pre2->source < source && pre2->linkPre != NULL) {
pre1 = pre2;
pre2 = pre2->linkPre;
}
if(pre2 == NULL || pre2->source != source) return false;
if(pre1 == pre2) {
map->headPre[dest] = pre2->linkPre;
} else {
pre1->linkPre = pre2->linkPre;
}
free(nex2);
return true;
}
struct Edge * GetEdge(struct CrossListMap * map,
unsigned int source/*0~n-1*/,
unsigned int dest/*0~n-1*/)
{
if(map->n < source || map->n < dest || map == NULL) return NULL;
struct Edge * edge = map->headNex[source];
while(edge != NULL && edge->dest < dest && edge->linkNex != NULL) {
edge = edge->linkNex;
}
if(edge == NULL || edge->dest != dest) return NULL; // 不存在从 source 到 dest 这条边
return edge;
}
void print(struct CrossListMap * map) {
for (int i=0; i<map->n; i++)
for (struct Edge * e=map->headNex[i]; e!=NULL; e=e->linkNex)
printf("from: %d to: %d, weight: %.1lf\n", e->source, e->dest, e->weight);
}
void print2(struct CrossListMap * map) {
for (int i=0; i<map->n; i++)
for (struct Edge * e=map->headPre[i]; e!=NULL; e=e->linkPre)
printf("%d comes from: %d, weight: %.1lf\n", e->dest, e->source, e->weight);
}
int main(void)
{
CrossListMap map;
InitMap(&map, 4);
// 图,起点,终点,权值
AddEdge(&map, 0, 1, 3.0);
AddEdge(&map, 0, 2, 3.0);
AddEdge(&map, 2, 0, 4.0);
AddEdge(&map, 2, 3, 4.0);
AddEdge(&map, 3, 0, 5.0);
AddEdge(&map, 3, 1, 5.0);
AddEdge(&map, 3, 2, 5.0);
RemoveEdge(&map, 0, 1);
print(&map);
print2(&map);
struct Edge * searchEdge = GetEdge(&map, 0, 1);
if(searchEdge != NULL)
printf("Weight of edge 0 to 2 is %.1lf\n", searchEdge->weight);
DestroyMap(&map);
return 0;
}