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)

相关文章
|
19天前
|
存储 算法 程序员
C语言:基础与应用的双重魅力
C语言:基础与应用的双重魅力
|
8天前
|
机器学习/深度学习 算法 数据挖掘
【C 言专栏】C 语言与机器学习的应用
【5月更文挑战第6天】C语言在机器学习中扮演关键角色,以其高效性、灵活性和可移植性实现底层算法、嵌入式系统和高性能计算。在神经网络、决策树和聚类算法等领域的实现中不可或缺。C语言被用于TensorFlow和OpenCV等知名库的底层,常与C++、Python结合使用。尽管面临开发难度和适应新算法的挑战,但C语言在机器学习领域的价值和潜力将持续展现,为科技进步贡献力量。
【C 言专栏】C 语言与机器学习的应用
|
10天前
|
存储 缓存 算法
【C 言专栏】C 语言中的数据结构应用
【5月更文挑战第4天】本文探讨了C语言中的核心数据结构,包括数组、链表(单链表和双链表)、栈、队列、二叉树(如二叉搜索树和二叉堆)以及图结构。这些数据结构在程序设计中扮演着关键角色,如数组的快速访问、链表的动态管理、栈和队列的处理流程控制、树和图的复杂关系表示。理解并选择适当的数据结构可优化程序性能,而内存管理和算法优化则进一步提升效率。通过案例分析和展望未来发展趋势,本文旨在帮助读者深化对C语言数据结构的理解和应用。
【C 言专栏】C 语言中的数据结构应用
|
13天前
|
机器学习/深度学习 算法 C语言
【C言专栏】递归算法在 C 语言中的应用
【4月更文挑战第30天】本文介绍了递归算法在C语言中的应用,包括基本概念(通过调用自身解决子问题)、特点(调用自身、终止条件、栈空间)和实现步骤(定义递归函数、分解问题、设置终止条件、组合解)。文中通过阶乘计算和斐波那契数列两个案例展示了递归的使用,强调了递归可能导致的栈溢出问题及优化需求。学习递归有助于理解和应用“分而治之”策略。
|
14天前
|
存储 算法 程序员
【C言专栏】C 语言结构体的应用与实践
【4月更文挑战第30天】C语言中的结构体是自定义数据类型的关键,它组合不同类型的數據以创建新类型,尤其适合处理复杂对象如学生信息。通过定义结构体如`struct Student`,包含名字、学号和成绩,可以方便地实例化和访问成员。结构体在链表实现、函数参数传递和数组中都有广泛应用,如表示链表节点和处理批量数据。理解并熟练运用结构体对于C语言编程至关重要,能提升代码效率和可读性。
|
19天前
|
存储 算法 程序员
C语言:深入探索与实战应用
C语言:深入探索与实战应用
13 0
|
19天前
|
C语言
if语句的应用(C语言零基础教程)
if语句的应用(C语言零基础教程)
|
19天前
|
C语言
C语言:内存函数(memcpy memmove memset memcmp使用)
C语言:内存函数(memcpy memmove memset memcmp使用)
|
5天前
|
存储 编译器 C语言
C语言:字符函数 & 字符串函数 & 内存函数
C语言:字符函数 & 字符串函数 & 内存函数
13 2
|
13天前
|
缓存 安全 编译器
【C 言专栏】C 语言函数的高效编程技巧
【5月更文挑战第1天】本文探讨了C语言中函数的高效编程技巧,包括函数的定义与作用(如代码复用和提高可读性)、设计原则(单一职责和接口简洁)、参数传递方式(值传递、指针传递和引用传递)、返回值管理、调用约定、嵌套与递归调用,以及函数优化技巧和常见错误避免。掌握这些技巧能提升C语言代码的质量和效率。
【C 言专栏】C 语言函数的高效编程技巧