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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了邻接表c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)相关的知识,希望对你有一定的参考价值。

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

 

以上是关于邻接表c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)的主要内容,如果未能解决你的问题,请参考以下文章

图的遍历:深度优先遍历,广度优先遍历

用c语言编程 1创建图的邻接矩阵和邻接表 2验证图的深度优先、广度优先遍历算法 3验证最短路径

存储结构与邻接矩阵,深度优先和广度优先遍历及Java实现

c语言图的遍历,邻接表存储,深度,广度优先遍历

图的深度优先遍历DFS和广度优先遍历BFS(邻接矩阵存储)超详细完整代码进阶版

数据结构—无向图创建邻接矩阵深度优先遍历和广度优先遍历(C语言版)