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)

相关文章
|
26天前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
38 1
|
27天前
|
C语言 开发者
C语言中的模块化编程思想,介绍了模块化编程的概念、实现方式及其优势,强调了合理划分模块、明确接口、保持独立性和内聚性的实践技巧
本文深入探讨了C语言中的模块化编程思想,介绍了模块化编程的概念、实现方式及其优势,强调了合理划分模块、明确接口、保持独立性和内聚性的实践技巧,并通过案例分析展示了其应用,展望了未来的发展趋势,旨在帮助读者提升程序质量和开发效率。
51 5
|
27天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
53 5
|
26天前
|
程序员 编译器 C语言
C语言中的预处理器指令,涵盖其基本概念、常见指令(如`#define`、`#include`、条件编译指令等)、使用技巧及注意事项
本文深入解析C语言中的预处理器指令,涵盖其基本概念、常见指令(如`#define`、`#include`、条件编译指令等)、使用技巧及注意事项,并通过实际案例分析,展示预处理器指令在代码编写与处理中的重要性和灵活性。
59 2
|
27天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
26天前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
43 1
|
26天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
57 1
|
27天前
|
网络协议 物联网 数据处理
C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势
本文探讨了C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势。文章详细讲解了使用C语言实现网络通信程序的基本步骤,包括TCP和UDP通信程序的实现,并讨论了关键技术、优化方法及未来发展趋势,旨在帮助读者掌握C语言在网络通信中的应用技巧。
38 2
|
1月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
24天前
|
存储 C语言 开发者
【C语言】字符串操作函数详解
这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
48 10