【代码】图的基本操作

图的基本操作


还是以书上的例子来演示图的基本操作,跟着敲一遍,试着理解每一行代码,多少会有收获滴,多敲敲就可以熟练运用啦

例:
以如下图所示的带权有向图为例,编写测试上述图操作函数的程序


代码实现:

注:
代码包含一个存放顶点的单链表头文件《ListVertex.h》和图的操作头文件《AdjMGraph.h》,一个测试源文件《main.cpp》

ListVertex.h:
#pragma once
#include<stdio.h>
#include<stdlib.h>
/*存放图的顶点的单向链表*/
typedef char DataType;
typedef struct  nodeVertex
{
    DataType data;        //数据域
    nodeVertex *next;     //指针域
}NodeVertex;
/*初始化链表*/
void initiateSeqList(NodeVertex **head)
{
    (*head) = (NodeVertex*)malloc(sizeof(NodeVertex));
    (*head)->next = NULL;
}
/*求链表长度*/
int listVertexLength(NodeVertex *head)
{
    NodeVertex *p = head;
    int i = 0;
    while (p->next != NULL)
    {
        i++;
        p = p->next;//编写的时候容易把这个语句忘掉,造成死循环,出不来结果
    }
    return i;
}
/*指定位置插入结点*/
void listVertexInsert(NodeVertex *head, int index, DataType vertex)
{
    NodeVertex *p = head;
    NodeVertex *q = (NodeVertex*)malloc(sizeof(NodeVertex));
    q->data = vertex;         //数据赋给新的结点
    q->next = NULL;           //新结点的指针域默认先置为空
    if (index < 0 || index > listVertexLength(p))  //防止报错
    {
        printf("参数不合法!插入失败!\n");
        return;
    }
    for (int i = 0; i < index; i++)        //遍历链表,直到指定位置index
        p = p->next;
    q->next = p->next;            //将p的下一个结点接在新结点后面
    p->next = q;                  //将新结点接在p后面
}
/*指定位置删除结点*/
void listVertexDelete(NodeVertex *head, int index, DataType* vertex)
{
    NodeVertex *p = head;
    if (index < 0 || index>=listVertexLength(p))  //防止报错
    {
        printf("参数不合法!插入失败!\n");
        return;
    }
    if (p->next == NULL)           //考虑空链表的情况
    {
        printf("链表已空!\n");
        return;
    }
    for (int i = 0; i < index; i++)  //遍历链表,直到指定位置
        p = p->next;
    if (p->next->next != NULL)       //如果要删除的不是最后一个结点,需要判断p->next->next是否为空,否则程序出错
        p->next = p->next->next;
    else
        p->next = NULL;              //如果要删除的是最后一个结点,直接把p的指针域置空
}
/*遍历输出结点*/
void listVertexPrint(NodeVertex *head)
{
    NodeVertex* p = head;
    while (p->next != NULL)
    {
        printf("%c ", p->next->data);
        p = p->next;
    }
    printf("\n");
}

AdjMGraph.h:
#pragma once
#include"ListVertex.h"
#define MaxVertices 100      //最大顶点数
#define MaxWeight 10000      //最大权值
/*图的结构体*/
typedef struct adjMGraph
{
    NodeVertex *VerTices;      //存放顶点
    int edge[MaxVertices][MaxVertices];//存边的二维数组
    int numOfEdges;            //边的条数
}AdjMGraph;
//初始化图
void adjMGraphInitiate(AdjMGraph *map, int n)
{
    int i, j;
    for (int i = 0; i < n; i++)         //初始化边
        for (int j = 0; j < n; j++)
            if (i == j)
                map->edge[i][j] = 0;    //自身到自身,没有边,默认权值为0
            else
                map->edge[i][j] = MaxWeight;
    map->numOfEdges = 0;                //初始化边数
    initiateSeqList(&(map->VerTices));  //单链表初始化
}
/*插入顶点*/
void InsetVertex(AdjMGraph *map, DataType vertex)
{
    listVertexInsert(map->VerTices, listVertexLength(map->VerTices), vertex);  //利用链表 在指定位置增加结点函数 插入顶点
}
/*插入边*/
void InsertEdge(AdjMGraph *map, int val1, int val2, int weight)    //i,j,权值
{
    //存放边的是一个二维数组,当i,j小于0或者i,j大于等于顶点个数,会出错
    if (val1 < 0 || val1 >= listVertexLength(map->VerTices) || val2 < 0 || val2 >= listVertexLength(map->VerTices))
    {
        printf("参数不合法!\n");
        return;
    }
    map->edge[val1][val2] = weight;     //赋边的权值
    map->numOfEdges++;                  //图中边的条数+1
}
/*删除边*/
void DeleteEdge(AdjMGraph *map, int val1, int val2)
{
    //同上,当i,j小于0或者i,j大于等于顶点个数,会出错
    if (val1 < 0 || val1 >= listVertexLength(map->VerTices) || val2 < 0||val2>=listVertexLength(map->VerTices)||val1==val2)
    {
        printf("参数不合法!\n");
        return;
    }
    //如果该边没有被赋过值(初始化的时候默认是MaxWeight),或者i==j时,没有这条边
    if (map->edge[val1][val2] == MaxWeight || val1 == val2)
    {
        printf("该边不存在!\n");
        return;
    }
    map->edge[val1][val2] = MaxWeight;      //若有这条边,重新恢复默认值MaxWeight
    map->numOfEdges--;                //边数-1
}
/*取第一个邻接顶点*/
int GetFirstVex(AdjMGraph map, int index)
/*在图中寻找index顶点的第一个邻接顶点*/
{
    int col;
    /*参数不合法*/
    if (index < 0 || index>listVertexLength(map.VerTices))
    {
        printf("参数不合法!\n");
        return -1;
    }
    for (col = 0; col < listVertexLength(map.VerTices); col++)           //在同行取得(邻接矩阵中),一定在结点集合内
        if (map.edge[index][col] > 0 && map.edge[index][col] < MaxWeight)//值肯定在0到maxweight之间,
            return col;
    return -1;
}
/*在图中寻找val1顶点的邻接顶点val2的下一个邻接顶点*/
int GetNextVex(AdjMGraph map, int val1, int val2)
{
    int col;
    if (val1 < 0 || val1 >= listVertexLength(map.VerTices) || val2 < 0 || val2 >= listVertexLength(map.VerTices))
    {
        printf("参数不合法!\n");
        return -1;
    }
    for (col = val2 + 1; col < listVertexLength(map.VerTices); col++)   //col赋初值为cal2+1,在同行取得(邻接矩阵中)
    {
        if (map.edge[val1][col] > 0 && map.edge[val1][col] < MaxWeight)
            return col;
        return -1;
    }
}
//边的结构体,有行、列、权值三个属性
struct RowColWeight
{
    int row;
    int col;
    int weight;
};
//在图中插入n个顶点信息V,和e条边信息E
void CreatGraph(AdjMGraph *map, DataType V[], int n, RowColWeight E[], int e)
{
    int i, k;
    adjMGraphInitiate(map, n);    //初始化图
    for (int i = 0; i < n; i++)   //增加n个顶点
        InsetVertex(map, V[i]);
    for (k = 0; k < e; k++)          //增加n条边
        InsertEdge(map, E[k].row,E[k].col, E[k].weight);
}
main.c:
#include"ListVertex.h"
#include"AdjMGraph.h"
int main()
{
    AdjMGraph g1;         //定义图
    DataType a[] = { 'A','B','C','D','E' };  //图的顶点集合
    RowColWeight row[] = { {0,1,10},{0,4,20},{1,3,30},{2,1,40},{3,2,50} };        //边的权值
    int p[9][9],q[9][9];
    int n = 5, e = 5;      //五个顶点和五条边
    int i, j, k;
    CreatGraph(&g1,a,n,row,e);    //创建有五个顶点,五条边的图
    //DeleteEdge(&g1, 0, 4);     //删除邻接矩阵i,j为0,4的边;
    printf("顶点集合为:");
    listVertexPrint(g1.VerTices);    //打印顶点集合(链表)
    printf("\n");
    printf("权值集合为:\n");
    for (i = 0; i < listVertexLength(g1.VerTices); i++)
    {
        for (j = 0; j < listVertexLength(g1.VerTices); j++)
            printf("%5d    ", g1.edge[i][j]);
        printf("\n");
    }
    system("pause");
    return 0;
}

运行结果:



代码编译器:Visual Studio 2017
ok

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值