邻接表c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)

时间:2022-05-27 12:35:56

graph.c

#include <stdio.h>
#include
<stdlib.h>
#include
<limits.h>

#include
"aqueue.h"

#define MAX_NUM 100
typedef
char node_type;

typedef
struct arc_node
{
int pos;
int distance;
struct arc_node * next;
} Arc_node;
//保存Node节点的相邻节点信息

typedef
struct node
{
node_type info;
Arc_node
* next;
} Node;
//保存节点信息

typedef
struct graph
{
Node adjlist[MAX_NUM];
int vertexs, brim;
} Graph;
//邻接表

static Arc_node * make_node(const int pos, const int distance)
{
Arc_node
* new_node = (Arc_node *)malloc( sizeof(Arc_node) );
if ( new_node == NULL )
exit(
1);

new_node
->next = NULL;
new_node
->distance = distance;
new_node
->pos = pos;

return new_node;
}

void g_create(Graph * graph)
{
int num;
int i, j, k;
char c;
Arc_node
* tmp;

printf(
"输入节点个数:");
scanf(
"%d", &graph->vertexs);
getchar();
printf(
"输入顶点信息:");
for ( i = 0; i < graph->vertexs; i++ )
{
scanf(
"%c", &graph->adjlist[i].info);
graph
->adjlist[i].next = NULL;
getchar();
}
graph
->brim = 0;

for ( i = 0; i < graph->vertexs; i++ )
{
printf(
"输入与节点%c相邻的节点和权值,#号键结束\n", graph->adjlist[i].info);
for ( j = 0; j < graph->vertexs; j++ )
{
scanf(
"%c", &c);
if ( c == '#' )
{
getchar();
break;
}
scanf(
"%d", &num);
getchar();
for ( k = 0; k < graph->vertexs; k++ )
{
if ( graph->adjlist[k].info != c )
continue;
if ( graph->adjlist[k].next == NULL )
graph
->adjlist[k].next = make_node(i, num);
else
{
tmp
= graph->adjlist[k].next;
while ( tmp->next != NULL )
tmp
= tmp->next;
tmp
->next = make_node(i, num);
}
graph
->brim++;
}
}
}
graph
->brim /= 2;
}

static void dfs_graph(Graph * graph, bool visited[], const int i);
void g_depth_first_search(Graph * graph)
{
bool visited[graph->vertexs];
int i;

for ( i = 0; i < graph->vertexs; i++ )
visited[i]
= false;

visited[
0] = true;
dfs_graph(graph, visited,
0);
}

static void dfs_graph(Graph * graph, bool visited[], const int i)
{
Arc_node
* tmp;
printf(
"%c\t", graph->adjlist[i].info);

tmp
= graph->adjlist[i].next;
while ( tmp != NULL )
{
if ( !visited[tmp->pos] )
{
visited[tmp
->pos] = true;
dfs_graph(graph, visited, tmp
->pos);
}
tmp
= tmp->next;
}
}

void g_breadth_first_search(Graph * graph)
{
Queue queue;
bool visited[graph->vertexs];
int pos;
int i;
Arc_node
* tmp;

q_init(
&queue);
for ( i = 0; i < graph->vertexs; i++ )
visited[i]
= false;

visited[
0] = true;
q_push(
&queue, 0);
while ( !q_empty(&queue) )
{
pos
= q_front(&queue);
printf(
"%c\t", graph->adjlist[pos].info);
tmp
= graph->adjlist[pos].next;
while ( tmp != NULL )
{
if ( !visited[tmp->pos] )
{
visited[tmp
->pos] = true;
q_push(
&queue, tmp->pos);
}
tmp
= tmp->next;
}
q_pop(
&queue);
}
printf(
"\n");
}

static void init_prim(Graph * graph, Graph * prim_tree);
void g_prim(Graph * graph, Graph * prim_tree)
{
bool visited[graph->vertexs];
int i, j, k;
int power, pos;
Arc_node
* tmp;

for ( i = 0; i < graph->vertexs; i++ )
visited[i]
= false;
init_prim(graph, prim_tree);

visited[
0] = true;
for ( i = 0; i < graph->vertexs; i++ )
{
power
= INT_MAX;//limits.h
for ( j = 0; j < graph->vertexs; j++ )
{
if ( visited[j] )
{
tmp
= graph->adjlist[j].next;
while ( tmp != NULL )
{
if ( power > tmp->distance && !visited[tmp->pos] )
{
power
= tmp->distance;
pos
= tmp->pos;
k
= j;
}
tmp
= tmp->next;
}
}
}
if ( !visited[pos] )
{
if ( prim_tree->adjlist[k].next == NULL )
{
prim_tree
->adjlist[k].next = make_node(pos, power);
}
else
{
tmp
= prim_tree->adjlist[k].next;
while ( tmp->next != NULL )
tmp
= tmp->next;
tmp
->next = make_node(pos, power);
}
visited[pos]
= true;
}
}
}

static void init_prim(Graph * graph, Graph * prim_tree)
{
int i;

for ( i = 0; i < graph->vertexs; i++ )
{
prim_tree
->adjlist[i].info = graph->adjlist[i].info;
prim_tree
->adjlist[i].next = NULL;
}
prim_tree
->vertexs = graph->vertexs;
prim_tree
->brim = graph->brim;
}

//kruskal
typedef struct
{
int head;
int tail;
int power;
} Edge;
static void init_kruskal(Graph * graph, Graph * kruskal_tree);
static void my_sort(Edge * arr, int size);
void kruskal(Graph * graph, Graph * kruskal_tree)
{
int visited[graph->vertexs];
int i, j;
Edge edge[graph
->brim];
int v1, v2, vs1, vs2;
Arc_node
* cur, * tmp;

for ( i = 0; i < graph->vertexs; i++ )
visited[i]
= i;

for ( i = 0, j = 0; i < graph->vertexs; i++ )
{
cur
= graph->adjlist[i].next;
while ( cur != NULL )
{
if ( cur->pos > i )
{
edge[j].head
= i;
edge[j].tail
= cur->pos;
edge[j].power
= cur->distance;
j
++;
}
cur
= cur->next;
}
}

init_kruskal(graph, kruskal_tree);
my_sort(edge, graph
->brim);

for ( i = 0; i < graph->brim; i += 1 )
{
v1
= edge[i].head;
v2
= edge[i].tail;
vs1
= visited[v1];
vs2
= visited[v2];
if ( vs1 != vs2 )
{
if ( kruskal_tree->adjlist[v1].next == NULL )
{
kruskal_tree
->adjlist[v1].next = make_node(v2, edge[i].power);
}
else
{
tmp
= kruskal_tree->adjlist[v1].next;
while ( tmp->next != NULL )
tmp
= tmp->next;
tmp
->next = make_node(v2, edge[i].power);
}
for ( j = 0; j < graph->vertexs; j++ )
{
if ( visited[j] == vs2 )
visited[j]
= vs1;
}
}
}
}

static void init_kruskal(Graph * graph, Graph * kruskal_tree)
{
int i;

kruskal_tree
->vertexs = graph->vertexs;
kruskal_tree
->brim = graph->brim;

for ( i = 0; i < graph->vertexs; i++ )
{
kruskal_tree
->adjlist[i].info = graph->adjlist[i].info;
kruskal_tree
->adjlist[i].next = NULL;
}
}

static void my_sort(Edge * arr, int size)
{
int i, j;
Edge tmp;

for ( i = 0; i < size - 1; i++ )
{
for ( j = i + 1; j < size; j++ )
{
if ( arr[i].power > arr[j].power )
{
tmp.head
= arr[i].head;
tmp.tail
= arr[i].tail;
tmp.power
= arr[i].power;

arr[i].head
= arr[j].head;
arr[i].tail
= arr[j].tail;
arr[i].power
= arr[j].power;

arr[j].head
= tmp.head;
arr[j].tail
= tmp.tail;
arr[j].power
= tmp.power;
}
}
}
}

int main(void)
{
Graph graph;
Graph prim_tree;
Graph kruskal_tree;
Arc_node
* node;
int i;

g_create(
&graph);

printf(
"brim = %d\n", graph.brim);
for ( i = 0; i < graph.vertexs; i++ )
{
printf(
"%c\t", graph.adjlist[i].info);
node
= graph.adjlist[i].next;
while ( node != NULL )
{
printf(
"%d %d\t", node->distance, node->pos);
node
= node->next;
}
printf(
"\n");
}
printf(
"\n");

// g_depth_first_search(&graph);
// printf("\n");
// g_breadth_first_search(&graph);

kruskal(
&graph, &kruskal_tree);
printf(
"brim = %d\n", kruskal_tree.brim);
for ( i = 0; i < kruskal_tree.vertexs; i++ )
{
printf(
"%c\t", kruskal_tree.adjlist[i].info);
node
= kruskal_tree.adjlist[i].next;
while ( node != NULL )
{
printf(
"%d %d\t", node->distance, node->pos);
node
= node->next;
}
printf(
"\n");
}
printf(
"\n");

return 0;
}

aqueue.h

#ifndef _QUEUE_H
#define _QUEUE_H

#define MAXSIZE 10

typedef
struct queue
{
int * arr;
int front;
int rear;
} Queue;

void q_init(Queue * queue);//初始化
void q_push(Queue * queue, const int data);//入队
void q_pop(Queue * queue);//出队
bool q_empty(Queue * queue);//为空
bool q_full(Queue * queue);//为满
int q_size(Queue * queue);//队大小
int q_front(Queue * queue);//队头元素
int q_back(Queue * queue);//队尾元素
void q_destroy(Queue * queue);//销毁

#endif //_QUEUE_h

aqueue.c

#include <stdio.h>
#include
<stdlib.h>
#include
<assert.h>
#include
<stdbool.h>

#include
"aqueue.h"

void q_init(Queue * queue)
{
queue
->arr = (int *)malloc( sizeof(int) * MAXSIZE );//初始化数组
assert(queue->arr != NULL);
queue
->front = 0;
queue
->rear = 0;
}

void q_push(Queue * queue, const int data)
{
if ( q_full(queue) )
return;
queue
->arr[queue->rear++] = data;//入队,队尾+1
queue->rear = queue->rear % MAXSIZE;//如果队尾
}

void q_pop(Queue * queue)
{
if ( q_empty(queue) )
return;
queue
->front = ++queue->front % MAXSIZE;//front+1,对MAXSIZE取余
}

bool q_empty(Queue * queue)
{
return queue->front == queue->rear;
}

bool q_full(Queue * queue)
{
return queue->front == (queue->rear + 1) % MAXSIZE;
}

int q_size(Queue * queue)
{
return (queue->rear - queue->front) % MAXSIZE;
}

int q_front(Queue * queue)
{
assert(
!q_empty(queue) );
return queue->arr[queue->front];
}

int q_back(Queue * queue)
{
assert(
!q_empty(queue) );
return queue->arr[queue->rear - 1];
}

void q_destroy(Queue * queue)
{
free(queue->arr);
}