C语言--离散数学实验--图的基本概念及其应用

简介: C语言--离散数学实验--图的基本概念及其应用

 目录

欧拉图的判定

实验内容

编辑

无向图的判断

算法展示

源码

有向图的判断

算法展示

源码

求欧拉路

算法展示

整体源码

对无向图的判断

对有向图的判断

二叉树的应用

源码

源码下载


实验目的

掌握判断欧拉图的方法;

掌握求最优二叉树的方法。

实验内容

判断一个图是不是欧拉图,如果是,求出所有欧拉回路;

最优二叉树在通信编码中的应用。要求输入一组通信符号的使用频率,求各通信符号对应的前缀码。

欧拉图的判定

实验内容

 一、欧拉图的判定

(1)用关系矩阵R=表示图。

(2)对无向图而言,若所有结点的度都是偶数,则该图为欧拉图。

(3)对有向图而言,若所有结点的入度等于出度,则该图为欧拉图。

(4)求欧拉路的方法:欧拉路经过每条边一次且仅一次。可用回溯的方法求得所有欧拉路。

image.gif编辑

本题采用分块编写,每一部分单独介绍,最后会有总写。

无向图的判断

对无向图的判断:

对无向图而言,若所有结点的度都是偶数,则该图为欧拉图。

算法展示

//算法如下
  for (int i = 0; i < n && flag; i++)
  {
    sum = 0;
    for (int j = 0; j < n; j++)
    {
      if (r[i][j])
        sum++;
    }
    if (sum % 2 == 0)
      flag = 0;
  }

image.gif

源码

#include <stdio.h>
int r[101][101];
int main()
{
  int flag = 1; 
  int sum;
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; i++)
  {
    for (int j = 0; j < n; j++)
    {
      scanf("%d", &r[i][j]);
    }
  }
  for (int i = 0; i < n && flag; i++)
  {
    sum = 0;
    for (int j = 0; j < n; j++)
    {
      if (r[i][j])
        sum++;
    }
    if (sum % 2 == 0)
      flag = 0;
  }
  if (flag == 0)
    printf("不是欧拉图\n");
  else
    printf("是欧拉图\n");
}

image.gif

有向图的判断

对有向图的判断:

对有向图而言,若所有结点的入度等于出度,则该图为欧拉图。

算法展示

//算法
  for (int i = 0; i < n && flag; i++)
  {
    sum1 = 0;
    sum2 = 0;
    for (int j = 0; j < n; j++)
    {
      if (r[i][j]) 
        sum1++;
    }
    for (int j = 1; j <= n; j++)
    {
      if (r[j][i])
        sum2++;
    }
    if (sum1 % 2 == 0|| sum2 % 2 == 0) 
      flag = 0;
  }

image.gif

源码

#include <stdio.h>
int r[101][101];
int main()
{
  int flag = 1;
  int sum1,sum2;
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; i++)
  {
    for (int j = 0; j < n; j++)
    {
      scanf("%d", &r[i][j]);
    }
  }
  for (int i = 0; i < n && flag; i++)
  {
    sum1 = 0;
    sum2 = 0;
    for (int j = 0; j < n; j++)
    {
      if (r[i][j]) 
        sum1++;
    }
    for (int j = 1; j <= n; j++)
    {
      if (r[j][i])
        sum2++;
    }
    if (sum1 % 2 == 0|| sum2 % 2 == 0) 
      flag = 0;
  }
  if (flag == 0)
    printf("不是欧拉图\n");
  else
    printf("是欧拉图\n");
}

image.gif

求欧拉路

求欧拉路的方法:欧拉路经过每条边一次且仅一次。可用回溯的方法求得所有欧拉路。

算法展示

int count = 0, cur = 0, r[N][N]; 
int sequence[M];
void try1(int k) 
{
  int i, pre = cur; 
  for (i = 0; i < N; i++)
    if (r[cur][i]) 
    {
      r[cur][i] = 0; cur = sequence[k] = i;
      if (k < M) try1(k + 1); 
      else prt1();
      r[pre][i] = 1; cur = pre;
    }
}

image.gif

整体源码

对无向图的判断

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
int n, a[100][100], m = 0, visit[100];
int cur = 0, s[100], vis[100][100];
void try1(int k)
{
    int i;
    if (cur == m + 1)
    {
        for (i = 0; i < cur; i++)
        {
            if (i == 0)
                printf("%d", s[i] + 1);
            else
                printf("->%d", s[i] + 1);
        }
        printf("\n");
    }
    else
    {
        for (i = 0; i < n; i++)
        {
            if (a[k][i] && !vis[k][i])
            {
                vis[k][i] = 1;
                vis[i][k] = 1;
                s[cur++] = i;
                try1(i);
                cur--;
                vis[k][i] = 0;
                vis[i][k] = 0;
            }
        }
    }
}
void dfs(int k)
{
    int i;
    visit[k] = 1;
    for (i = 0; i < n; i++)
    {
        if (a[k][i] && !visit[i])
        {
            dfs(i);
        }
    }
}
int fun()
{
    int i;
    dfs(0);
    for (i = 0; i < n; i++)
    {
        if (!visit[i])
            return 0;
    }
    return 1;
}
int main()
{
    int i, j;
    printf("请输入节点个数n:");
    scanf("%d", &n);
    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++)
            scanf("%d", &a[i][j]);
    printf("邻接矩阵为:\n");
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
            printf("%d ", a[i][j]);
        printf("\n");
    }
    if (fun() == 0)
    {
        printf("该图不是连通图\n");
        return 0;
    }
    printf("该图是连通图\n");
    int odd = 0;
    for (i = 0; i < n; i++)
    {
        int sum = 0;
        for (j = 0; j < n; j++)
        {
            if (a[i][j])
                sum++;
        }
        if (sum % 2)
            odd++;
    }
    if (odd == 0)
    {
        printf("该图是欧拉图。\n");
        printf("所有的欧拉路为:\n");
        for (i = 0; i < n; i++)
        {
            s[cur++] = i;
            try1(i);
            cur--;
        }
    }
    else
       printf("不是欧拉图\n");
    return 0;
}

image.gif

对有向图的判断

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
int n, a[100][100], m = 0, visit[100];
int cur = 0, s[100], vis[100][100];
void try1(int k)
{
    int i;
    if (cur == m + 1)
    {
        for (i = 0; i < cur; i++)
        {
            if (i == 0)
                printf("%d", s[i] + 1);
            else
                printf("->%d", s[i] + 1);
        }
        printf("\n");
    }
    else
    {
        for (i = 0; i < n; i++)
        {
            if (a[k][i] && !vis[k][i])
            {
                vis[k][i] = 1;
                s[cur++] = i;
                try1(i);
                cur--;
                vis[k][i] = 0;
            }
        }
    }
}
void dfs(int k)
{
    int i;
    visit[k] = 1;
    for (i = 0; i < n; i++)
    {
        if (a[k][i] && !visit[i])
        {
            dfs(i);
        }
    }
}
int fun()//判断连通性
{
    int i, j;
    for (i = 0; i < n; i++)
    {
        memset(visit, 0, sizeof(visit));
        dfs(i);
        for (j = 0; j < n; j++)
        {
            if (!visit[j])
                break;
        }
        if (j == n)
            return 1;
    }
    return 0;
}
int main()
{
    int i, j;
    printf("请输入节点个数n:");
    scanf("%d", &n);
    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++)
            scanf("%d", &a[i][j]);
    if (fun() == 0)
    {
        printf("该图不是连通图!\n");
        return 0;
    }
    printf("该图是连通图!\n");
    int odd = 0, begin = -1, end = -1;
    for (i = 0; i < n; i++)
    {
        int sum1 = 0, sum2 = 0;
        for (j = 0; j < n; j++)
        {
            sum1 += a[i][j];
            sum2 += a[j][i];
        }
        if (sum1 != sum2)
        {
            odd++;
            if (sum1 - sum2 == 1)
                begin = i;
            if (sum2 - sum1 == 1)
                end = i;
        }
    }
    if (odd == 0)
    {
        printf("该图是欧拉图。\n");
        printf("所有的欧拉路为:\n");
        for (i = 0; i < n; i++)
        {
            s[cur++] = i;
            try1(i);
            cur--;
        }
    }
    else
       printf("不是欧拉图\n");
    return 0;
}

image.gif

二叉树的应用

(1)用一维数组f[N]存贮通信符号的使用频率,用求最优二叉树的方法求得每个通信符号的前缀码。

(2)用链表保存最优二叉树,输出前缀码时可用树的遍历方法。

源码

#include <stdio.h>
#include <stdlib.h>
#define N 13
struct tree 
{
    float num;
    struct tree* Lnode;
    struct tree* Rnode;
}*fp[N]; //保存结点
char s[2 * N]; //放前缀码
void inite_node(float f[], int n) 
{ //生成叶子结点
    int i;
    struct tree* pt;
    for (i = 0; i < n; i++) 
    {
        pt = (struct tree*)malloc(sizeof(struct tree));//生成叶子结点
        pt->num = f[i];
        pt->Lnode = NULL;
        pt->Rnode = NULL;
        fp[i] = pt;
    }
}
void sort(struct tree* array[],int n) 
{ //将第N-n个点插入到已排好序的序列中。
    int i;
    struct tree* temp;
    for (i = N - n; i < N - 1; i++) 
    {
        if (array[i]->num > array[i + 1]->num) 
        {
            temp = array[i + 1];
            array[i + 1] = array[i];
            array[i] = temp;
        }
    }
}
struct tree* construct_tree(float f[], int n) 
{ //建立树
    int i;
    struct tree* pt;
    for (i = 1; i < N; i++) 
    {
        pt = (struct tree*)malloc(sizeof(struct tree));//生成非叶子结点
        pt->num = fp[i - 1]->num + fp[i]->num;
        pt->Lnode = fp[i - 1];
        pt->Rnode = fp[i];
        fp[i] = pt;//w1+w2
        sort(fp, N - i);
    }
    return fp[N - 1];
}
void preorder(struct tree* p, int k, char c) 
{
    int j;
    if (p != NULL) 
    {
        if (c == 'l')
            s[k] = '0';
        else
            s[k] = '1';
        if (p->Lnode == NULL) 
        {
            //P指向叶子
            printf("%.2f:  ", p->num);
            for (j = 0; j <= k; j++)
                printf("%c", s[j]);
            putchar('\n');
        }
        preorder(p->Lnode, k + 1, 'l');
        preorder(p->Rnode, k + 1, 'r');
    }
}
int main() 
{
    float f[N] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41 };
    struct tree* head;
    inite_node(f, N); //初始化结点
    head = construct_tree(f, N);//生成最优树
    s[0] = 0;
    preorder(head, 0, 'l');//遍历树
    return 0;
}

image.gif

源码下载

gitee下载链接:

欧拉图/欧拉图/test1.c · 赵博涵/c_language_exercises - 码云 - 开源中国 (gitee.com)

相关文章
|
29天前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
60 4
|
1月前
|
C语言
大学生期末C语言实验(学生成绩和鞍点)
大学生期末C语言实验(学生成绩和鞍点)
148 0
大学生期末C语言实验(学生成绩和鞍点)
ly~
|
1月前
|
网络协议 算法 关系型数据库
C语言的应用
C 语言因其高效性和对硬件的直接访问能力,在多个领域有广泛应用。在系统软件领域,它被用于开发操作系统(如 Unix 和 Linux 的内核)和嵌入式系统(如汽车电子控制系统)。在游戏开发中,C 语言常用于构建游戏引擎的底层部分(如 Unity 和 Unreal Engine 的核心模块)及性能要求高的独立游戏。此外,C 语言也用于数据库管理系统(如 MySQL 和 PostgreSQL 的核心功能)和网络编程(如 TCP/IP 协议栈和网络服务器的核心模块)。
ly~
33 3
|
1月前
|
Java Unix Linux
1.3 C语言的应用范围
C语言自20世纪80年代以来一直是主流编程语言,适用于小型计算机、个人电脑及大型机。因其高效紧凑且易于修改和移植,广泛用于软件开发。尽管后来C++和JAVA流行起来,但C语言仍然是软件行业核心,并在嵌入式系统、科学编程和操作系统开发如Linux中扮演重要角色。即使到现在,掌握C语言仍是一项重要技能。不是必须得是计算机专家才能使用C语言,学习C语言同时也能学到很多C++的知识。
49 8
|
2月前
|
C语言
数据结构基础详解(C语言):图的基本概念_无向图_有向图_子图_生成树_生成森林_完全图
本文介绍了图的基本概念,包括图的定义、无向图与有向图、简单图与多重图等,并解释了顶点度、路径、连通性等相关术语。此外还讨论了子图、生成树、带权图及几种特殊形态的图,如完全图和树等。通过这些概念,读者可以更好地理解图论的基础知识。
100 8
|
2月前
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
|
2月前
|
存储 安全 C语言
C语言 二级指针应用场景
本文介绍了二级指针在 C 语言中的应用,
|
3月前
|
程序员 C语言
位操作在C语言中的解析与应用
位操作在C语言中的解析与应用
90 0
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
34 3
|
7天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
23 6