图论(一)--图的建立

基于算法导论图算法-图的建立

  • 问题描述
  • 问题分析
  • 源代码
  • 结果截图

    问题描述

    随机创建一个100个顶点,大约2000条边的有向图以及大约1000条边的无向图,并可以输出每个点的入度和出度(使用邻接表表示)

    问题分析

    本问题我通过首先创建一个随机邻接矩阵,并将其存入文件中,然后从文件中读取信息建立图结构(与ACM题目吻合)

    难点在于图的数据结构(我使用C/C++进行实现)

    源代码

#pragma once
#include
#include
#include
#include 
using namespace std;

typedef int Vertex;

struct Node;
typedef struct Node *PtrToNode, *List;
struct Node {
    Vertex    adjvex;
    int weight;
    PtrToNode next;//指向下一个结点的指针
};

struct VertexRecord {
    //ElementType  Element;
    int in_degree;//入度 
    int out_degree;//出度 
    List  adjto;//指向第一个邻接结点的指针
};
struct GraphRecord {
    int      vexnum;
    struct VertexRecord *vertices;//数组
};
typedef struct GraphRecord *Graph;

const int VertexNum = 20;
const int INF = 0x3f3f3f3f;

void CreateRandomDirectGraph();//生成有向图的矩阵
Graph CreateDirectGraph();//根据随机产生的有向图矩阵生成有向图的链表表示
void CreateRandomUndirectGraph();//生成有向图的矩阵
Graph CreateUndirectGraph();//根据随机产生的有向图矩阵生成有向图的链表表示
void print_graph(Graph G);//打印图结构
void print_VertexDegree(Graph G);//打印图各顶点的度数
void print_EdgeWeight(Graph G);//打印图的各边的权值

int matrix[VertexNum + 1][VertexNum + 1];
double random(double start, double end);
double random(double start, double end)//产生start~end之间的随机数 
{
    return start + (end - start)*rand() / (RAND_MAX + 1.0);
}

void CreateRandomDirectGraph()
{   
    FILE *fp;
    fp = fopen("F:/C++/DirectGraph_100.txt", "w");
    srand(unsigned(time(0)));
    int x;
    for (int i = 0; i < VertexNum;i++) {
        for (int j = 0; j < VertexNum; j++) {
            x = (int)random(0, 20);//产生0~20的随机数,如果小于5则有边(题目要求20个顶点,大约100条边)
            if (i!=j&&x < 5) matrix[i][j] = 1;
            else matrix[i][j] = 0;
            fprintf(fp,"%d\n", matrix[i][j]);
        }
    }
    fclose(fp);
}

Graph CreateDirectGraph() {
    FILE *fp;
    fp = fopen("F:/C++/DirectGraph_100.txt", "r");
    //图的初始化 
    Graph G;
    PtrToNode ptr;
    G = (struct GraphRecord*)malloc(sizeof(struct GraphRecord));
    G->vexnum = VertexNum;
    G->vertices = (struct VertexRecord*)malloc(sizeof(struct VertexRecord)*VertexNum);
    for (int i = 0; i < VertexNum; i++) {
        G->vertices[i].adjto = NULL;
        G->vertices[i].in_degree = 0;
        G->vertices[i].out_degree = 0;
    }

    int flag;
    srand(unsigned(time(0)));
    int Edge_weight;
    //图的构建 
    for (int i = 0; i < VertexNum; i++) {
        for (int j = 0; j < VertexNum; j++) {
            fscanf(fp, "%d", &flag);
            if (flag) {
                Edge_weight = (int)random(1, 20);//随机产生边的权值 
                ptr = (struct Node*)malloc(sizeof(struct Node));
                ptr->adjvex = j;
                ptr->weight = Edge_weight;
                G->vertices[i].out_degree++;//出度
                G->vertices[j].in_degree++;//入度
                ptr->next = G->vertices[i].adjto;
                G->vertices[i].adjto = ptr;
            }
        }
    }
    fclose(fp);
    return G;
}

void CreateRandomUndirectGraph()//与creatRandomDirectGrap方法一致,随机产生邻接矩阵 
{
    FILE *fp;
    fp = fopen("F:/C++/UndirectGraph_100.txt", "w");
    srand(unsigned(time(0)));
    int x;
    for (int i = 0; i < VertexNum; i++) {
        for (int j = 0; j < VertexNum; j++) {
            x = (int)random(0, 20);
            if (i != j&&x < 5) matrix[i][j] = 1;
            else matrix[i][j] = 0;
            fprintf(fp, "%d\n", matrix[i][j]);
        }
    }
    fclose(fp);
}

Graph CreateUndirectGraph() {
    FILE *fp;
    fp = fopen("F:/C++/UndirectGraph_100.txt", "r");
    //图的初始化 
    Graph G;
    PtrToNode ptr1, ptr2;
    G = (struct GraphRecord*)malloc(sizeof(struct GraphRecord));
    G->vexnum = VertexNum;
    G->vertices = (struct VertexRecord*)malloc(sizeof(struct VertexRecord)*VertexNum);
    for (int i = 0; i < VertexNum; i++) {
        G->vertices[i].adjto = NULL;
        G->vertices[i].in_degree = 0;
        G->vertices[i].out_degree = 0;
    }

    int flag;
    srand(unsigned(time(0)));
    int Edge_weight;

    //图的构建 
    for (int i = 0; i < VertexNum; i++) {
        for (int j = i + 1; j < VertexNum; j++) {
            fscanf(fp, "%d", &flag);
            if (flag) {
                Edge_weight = (int)random(1, 20);//随机产生边的权值 
                ptr1 = (struct Node*)malloc(sizeof(struct Node));
                ptr1->adjvex = j;
                ptr1->weight = Edge_weight;
                G->vertices[i].out_degree++;//出度
                G->vertices[j].in_degree++;//入度
                ptr1->next = G->vertices[i].adjto;
                G->vertices[i].adjto = ptr1;

                ptr2 = (struct Node*)malloc(sizeof(struct Node));
                ptr2->adjvex = i;
                ptr2->weight = Edge_weight;
                G->vertices[j].out_degree++;//出度
                G->vertices[i].in_degree++;//入度
                ptr2->next = G->vertices[j].adjto;
                G->vertices[j].adjto = ptr2;

            }
        }
    }
    fclose(fp);
    return G;
}

void print_graph(Graph G) {//打印图结构 
    PtrToNode ptr;
    int count = 0;
    for (int i = 0; i < G->vexnum; i++) {
        printf("顶点%d:", i);
        ptr = G->vertices[i].adjto;
        while (ptr != NULL) {
            printf(" %d", ptr->adjvex);
            ptr = ptr->next;
            count++;
        }
        printf("\n");
    }
    printf("顶点的数量为:%d,有向边的数量(一条无向边按照两条有向边计算)为:%d\n", VertexNum, count);
}

void print_VertexDegree(Graph G) {
    for (int i = 0; i < G->vexnum; i++) {
        printf("顶点%d的入度为:%d,出度为:%d\n", i, G->vertices[i].in_degree, G->vertices[i].out_degree);
    }
}

void print_EdgeWeight(Graph G) {
    PtrToNode ptr;
    for (int i = 0; i < G->vexnum; i++) {
        ptr = G->vertices[i].adjto;
        while (ptr != NULL) {
            printf("边<%d,%d>的权值为:%d\n", i,ptr->adjvex, ptr->weight);
            ptr = ptr->next;
        }
    }
}

int main() {
    //有向图的随机生成(20个顶点,100左右的边,可以进行修改)
    //CreateRandomDirectGraph();
    //Graph G = CreateDirectGraph();

    //无向边的随机生成(20个顶点,50左右的边)
    CreateRandomUndirectGraph();
    Graph G = CreateUndirectGraph();

    print_graph(G);//打印图
    printf("打印各顶点入度和出度:\n");
    print_VertexDegree(G);//打印顶点度数
    printf("打印每条边的权值:\n");
    print_EdgeWeight(G);//打印边权

    return 0;   
} 
  • 结果截图(为了展示全貌,减少顶点数和边数进行展示)
    图论(一)--图的建立_第1张图片

你可能感兴趣的:(算法)