离散数学实验:度数列判断简单图化、连通图、欧拉图、欧拉回路

离散数学实验:度数列判断简单图化、连通图、欧拉图、欧拉回路 

可能存在问题,代码也不够简洁,希望有大家指正

/**************
By Vast Cosmic
2021.12.07
**************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> 
#define N 100

int m = 0;  //点个数、元素个数
int martix[N][N];     //图矩阵
int d_cpy[N];       //度数列备份
int euler[N];     //欧拉路
int e;             //边数

int main()
{
    void maxsort(int *d, int n);
    bool judge_gra(int *d,int n);
    bool Havel(int *d, int n);
    void gra_print(int *d, int n);
    bool gra_connect(int *d);
    bool judge_eula(int *d);
    void find_euler(int m);

    memset(martix, 0, sizeof(martix));   //图矩阵初始化
    memset(euler, 0, sizeof(euler));   //欧拉路初始化

    /*数列输入*/
    int d[N] = {0};
    printf("输入非负整数列元素个数:\n");
    scanf("%d", &m);
    printf("输入序列\n");
    for (int i = 0; i < m;i++)
        scanf("%d", &d[i]);

    if(judge_gra(d, m)==1)  //判断可图化
    {      
        printf("\n该数列可图化\n\n");

        if(Havel(d, m)==1)
            printf("该数列可简单图化,简单图如上\n");
        else
            printf("\n该数列不可简单图化\n");

        if(gra_connect(d_cpy)==1)       
        {
            printf("\n该图是连通图\n");
            if(judge_eula(d_cpy)==1)
            {
                printf("\n该图是欧拉图\n");
		        find_euler(m);
            }       
            else
                printf("\n该图不是欧拉图\n");
        }
		else
			printf("\n该图不是连通图\n");
    }
    else
        printf("\n该数列不可图化\n");

    system("pause");
    return 0;
}

/*判断可图化*/
bool judge_gra(int *d, int n)
{
    int sum = 0;
    while (n != 0)
    {
        sum += *d;
        n -= 1;
        d += 1;
    }
    d = &d[0];
    if(sum%2==0)
        return 1;
    else
        return 0;
}

/*判断简单图*/
bool Havel(int *d,int n)
{
    void gra_print(int *d, int n);
    void maxsort(int *d, int n);
    void printf_gra(int *d,int n);

    memset(d_cpy, 0, sizeof(d_cpy));
    for (int i = 0; i < n;i++)
        d_cpy[i] = d[i];
    m = n;  //记录简单图初始顶点的个数

    while (judge_gra(d, n) == 1)
    {
        maxsort(d, n);

        int control = d[0]; // 控制-1的循环个数
        for (int i = 0; i < control; i++)
        {
            d[i] = d[i + 1] - 1;
            if (d[i] < 0)
                return 0;
        }
        int j = 1;
        while (control + j != n)
        {
            d[control] = d[control + j];
            j += 1;
        }
        n -= 1;

        /* 全为0时退出 */
        int flag = 0;
        for (int i = 0; i < n; i++)
        {
            if (d[i] != 0)
                flag = 1;
        }
        if (flag == 0)
            break;
    }

    int sum = 0;
    for (int i = 0; i < m;i++)
        sum = sum + d_cpy[i];
    e = sum / 2;

    maxsort(d_cpy, m);
    gra_print(d_cpy, m);
    return 1;
}

void maxsort(int *d,int n)  //sort form big one to small one
{
    int temp = 0;
    for (int i = 0; i < n;i++)
    {
        for (int j = 1; j < n; j++)
        {
            if (d[j-1] < d[j])
            {
                temp = d[j - 1];
                d[j - 1] = d[j];
                d[j] = temp;
            }
        }
    }
}

void gra_print(int *d, int n)
{
    int check_gra(int *d, int n);   //简单图校验
    int ra, rb;  //两个随机数  
	int count = 0;    //count来记录当前生成的度数  
    srand(time(0));

    int sum = 0;
    for (int i = 0; i < n;i++)
        sum = sum + d[i];       //度数和

    int check = 0;
    while (check==0)
    {
        count = 0;
        memset(martix, 0, sizeof(martix));   //图矩阵初始化
        while (count < sum)          //随机顶点顺序胜生成图
        {
            ra = rand() % n;    
            rb = rand() % n;    
            while (ra == rb)         //避免生成自环
            {
                ra = rand() % n;  
                rb = rand() % n;
            }
            if (!martix[ra][rb])     //建立无向图邻接矩阵
            {
                martix[ra][rb] = martix[rb][ra] = 1;
                count+=2;
            }
        }
        if(check_gra(d_cpy, m) == 1)
            check = 1;
    }

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
            printf("  %d  ", martix[i][j]);
        printf("\n");
    }
}

int check_gra(int *d, int n)
{
    int n_gra_connect[N];
    memset(n_gra_connect, 0, sizeof(n_gra_connect));

    for (int i = 0; i < n;i++)          //统计生成的图的每个点的度数
        for (int j = 0; j < n;j++)
            if(martix[i][j]==1)
                n_gra_connect[i] += 1;

    maxsort(n_gra_connect, n);      //递减排序
    int flag = 1;                   //判断生成的简单图的度数列是否与原度数列相同
    for (int i = 0; i < n;i++)
        if(d[i]!=n_gra_connect[i])
            flag = 0;
    return flag;
}

bool visit[N];
void DFS(int x, int *d)
{
	visit[x] = true;
	for (int i = 0; i<m; i++)
	    if (!visit[i] && martix[x][i])  //下个未搜索的i,且martix为1(可达),否则下一个i
		    DFS(i,d);                   //继续搜索,
}
bool gra_connect(int *d)        //判断连通
{
    void DFS(int x, int *d);

    DFS(0, d);
    for (int i = 0; i < m; i++)
        if (!visit[i])  
            return 0;
    return 1;
}

bool judge_eula(int *d_cpy)
{
    int flag = 0;
    for (int i = 0; i < m;i++)
    {
        if (d_cpy[i]%2==0 && d_cpy[i] != 0)
            flag = 1;
        else
        {
            flag = 0;
            return 0;
        }
    }
    if(flag==1)
        return 1;
    else
        return 0;
}

void find_euler(int m)      //m为边数
{
    int euler_martix[m + 1][m + 1];
    memset(euler_martix, 0, sizeof(euler_martix));
    for (int i = 0; i < m;i++)
    {
        for (int j = 0; j < m;j++)
            euler_martix[i + 1][j + 1] = martix[i][j];      //复制矩阵,便于表示顶点
    }

    int start = m, visit = start, tmp = 0;   //从度数最小的点开始
	while(true)
	{
        int flag1 = 0, flag_brige = 0;

        for (int j = 1; j <= m; j++)         //遍历该点与其它所有点的邻接关系
        {
            if (euler_martix[visit][j] >= 2) //找到第一条非桥
            {
                flag_brige++;                //记录是否存在非桥
                euler_martix[visit][j]--;    //边是二元关系,两个点都要改变;包括了环的情况
                euler_martix[j][visit]--;
                printf(" %d,%d ", visit, j); //模拟走的道路
                visit = j;                   //更新当前点
                break;                       //找到就进入下一个点
            }
            if (euler_martix[visit][j] == 1 && flag1 == 0) //记录第一个与当前点存在一条边(不一定是割边)的点
            {
                flag1++;
                tmp = j;
            }
		}

        if (flag_brige == 0 && flag1 == 1)   //走桥
        {
            euler_martix[visit][tmp]--;
            euler_martix[tmp][visit]--;
            printf("V%d->", visit);
            visit = tmp;
        }
        if (flag_brige == 0 && flag1 == 0)   //当矩阵为零矩阵时结束
            break;      
    }
    printf("V%d\n",start);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值