报告汇总之c语言数据结构报告篇(四)通信网的建立

报告汇总之c语言数据结构报告篇(四)

通信网的建立

代码区

//
//  main.c
//  通信网构建
//
//  Created by tianyu on 2019/10/20.
//  Copyright © 2019 tianyu. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
#define wuqiong 100000

//顶点信息
typedef struct Vex
{
    char name[MAX][64];
    char code[MAX][64];
    int length;
}v;

//存放边的信息
typedef struct Edge
{
    char vex1[64];
    char vex2[64];
    int weight;
    int A[MAX][MAX];//用来存放邻接矩阵
    int vexnumber;//用来存放顶点的数目
    int edgenumer;//用来存放边的数目
}e;

//初始化顶点线性表
void initVex (v*L)
{
    L->length=-1;
}

//获取顶点
void GetVex (v*L,e*B)
{
    initVex(L);
    printf("请输入初始的顶点个数:");
    scanf("%d",&B->vexnumber);
    for (int i=0;i<B->vexnumber;i++)
    {
        L->length++;
        printf("请输入城市名称:");
        scanf("%s",L->name[i]);
        printf("请输入城市的编号:");
        scanf("%s",L->code[i]);
    }
}

//获取边的信息并构建邻接矩阵
void GetEdge (e*B,v*L)
{
    printf("请输入边的数量:");
    scanf("%d",&B->edgenumer);
    //初始化邻接矩阵
    for (int i=0;i<=B->vexnumber-1;i++)
        for (int j=0;j<=B->vexnumber-1;j++)
        {
            if (i==j)
                B->A[i][j]=0;
            else
                B->A[i][j]=wuqiong;
        }
    int i,j;
    //录入邻接矩阵中边的信息
    int m=B->edgenumer;
    while (m>0)
    {
        //录入每条边的基本信息
        printf("请输入边的第一个顶点:");
        scanf("%s",B->vex1);
        getchar();
        printf("请输入边的第二个顶点:");
        scanf("%s",B->vex2);
        printf("请输入两个地点之间的距离:");
        scanf("%d",&B->weight);
        //找出边的顶点的位置
        for (i=0;i<=L->length;i++)
        {
            if (strcmp(L->name[i], B->vex1)==0)
            {
                break;
            }
        }
        for (j=0;j<=L->length;j++)
        {
            if (strcmp(L->name[j], B->vex2)==0)
            {
                break;
            }
        }
        //将边的值录入邻接矩阵中
        B->A[i][j]=B->weight;
        B->A[j][i]=B->A[i][j];
        m--;
    }
    for (int i=0;i<=B->vexnumber-1;i++)
    {
        for (int j=0;j<=B->vexnumber-1;j++)
        {
            printf("%7d ",B->A[i][j]);
        }
        printf("\n");
    }
}

//删除边的信息
void DeletEdge (e*B,v*L)
{
    printf("请输入需要删除边的一个顶点:\n");
    scanf("%s",B->vex1);
    printf("请输入需要删除边的另一个顶点:\n");
    scanf("%s",B->vex2);
    
    int i,j;
    for (i=0;i<=L->length;i++)
    {
        if (strcmp(L->name[i], B->vex1)==0)
        {
            break;
        }
    }
    for (j=0;j<=L->length;j++)
    {
        if (strcmp(L->name[j], B->vex2)==0)
        {
            break;
        }
    }
    B->A[i][j]=B->A[j][i]=wuqiong;
}
//增加边的距离
void addedge (e*B,v*L)
{
    printf("请输入需要增加边的一个顶点:\n");
    scanf("%s",B->vex1);
    printf("请输入需要增加边的另一个顶点:\n");
    scanf("%s",B->vex2);
    int i,j;
    for (i=0;i<=L->length;i++)
    {
        if (strcmp(L->name[i], B->vex1)==0)
        {
            break;
        }
    }
    for (j=0;j<=L->length;j++)
    {
        if (strcmp(L->name[j], B->vex2)==0)
        {
            break;
        }
    }
    printf("请输入需要增加的距离:");
    int h;
    scanf("%d",&h);
    B->A[j][i]+=h;
    B->A[i][j]=B->A[j][i];
}
//城市相关信息的修改
void alter (v*L)
{
    printf("1---修改城市名称\n");
    printf("2---修改城市编号\n");
    printf("请输入需要对城市信息进行的操作:");
    int m;
    scanf("%d",&m);
    printf("请输入需要修改的城市的名字:");
    char t[64];
    scanf("%s",t);
    int i;
    for (i=0;i<=L->length;i++)
    {
        if (strcmp(L->name[i], t)==0)
        {
            break;
        }
    }
    if (m==1)
    {
        printf("请输入修改后的城市的名字:");
        scanf("%s",t);
        strcpy(L->name[i], t);
    }
    else
    {
        printf("请输入修改后的城市的编号:");
        scanf("%s",t);
        strcpy(L->name[i], t);
    }
}
void printfedge (e*B)
{
    for (int i=0;i<=B->vexnumber-1;i++)
    {
        for (int j=0;j<=B->vexnumber-1;j++)
        {
            printf("%7d ",B->A[i][j]);
        }
        printf("\n");
    }

}
//更改图的相关信息
void change (e*B,v*L)
{
    printf("1---城市间的距离的增加\n");
    printf("2---城市间距离的删除\n");
    printf("3---城市的相关信息的修改\n");
    printf("4---城市边的关系的显示\n");
    printf("请输入需要对城市信息进行的操作:\n");
    int m;
    scanf("%d",&m);
    switch (m)
    {
        case 2:
            DeletEdge(B, L);
            break;
        case 1:
            addedge(B, L);
            break;
        case 3:
            alter(L);
            break;
        case 4:
            printfedge(B);
            break;
        default:
            printf("您输入的指令有误请重新输入!\n");
            break;
    }
    
}

//prim算法
void prim (e*B,v*L)
{
    int k[100],m=0,i=0,p=0,mix=wuqiong,u=0,n=0,g=0,r[100],w[100];
    k[0]=0;
    int min=wuqiong;
    while (1)
    {
        for (int j=0;j<L->length+1;j++)
        {
            if (min>=B->A[i][j]&&B->A[i][j]!=0)
            {
                p=0;
                min=B->A[i][j];
                m++;
                k[m]=j;
            }
            else if (j==L->length-1)
                p=1;
        }
        B->A[i][k[m]]=0;
        B->A[k[m]][i]=B->A[i][k[m]];
        for (int i=0;i<=B->vexnumber-1;i++)
        {
            for (int j=0;j<=B->vexnumber-1;j++)
            {
                printf("%7d ",B->A[i][j]);
            }
            printf("\n");
        }
        //将未录入边保存
        for (int j=0;j<L->length+1;j++)
        {
            if (B->A[i][j]!=wuqiong&&B->A[i][j]!=0&&j!=k[m])
            {
                r[n]=B->A[i][j];
                w[n]=j;
                n++;
            }
        }
        
        for (int j=0;j<n;j++)
        {
            if (mix>r[j])
            {
                p=0;
                mix=r[j];
                u=j;
            }
        }
        r[u]=wuqiong;
        u=w[u];
        min=mix;
        g=0;
        if (p==0)
        {
            printf("%s->",L->name[i]);
        }
        if (m!=0)
        {
            i=k[m];
            m--;
            p=0;
        }
        if (u!=0&&p==1&&m==0)
        {
            p=0;
            i=u;
            u=0;
        }

        if (p!=0)
        {
            printf("%s\n",L->name[i]);
            break;
        }
    }
}

void prim2 (e*B,v*L)
{
    int a[100][100];
    for (int i=0;i<=B->vexnumber-1;i++)
    {
        for (int j=0;j<=B->vexnumber-1;j++)
        {
            a[i][j]=B->A[i][j];
        }
    }
    int i=0,j,min=wuqiong,k[100],p=B->vexnumber,t=0,m=0,n,g[100];
    k[t]=0;
    n=0;
    for (int i=0;i<=L->length+1;i++)
    {
        g[i]=i;
    }
    printf("%s->",L->name[m]);//打印第一个顶点
    p--;
    while (p>=1)
    {
        int q=t;
        t++;
        for (i=k[q];q>=0;q--)
        {
            i=k[q];
            n=i;
        for (j=0;j<=L->length;j++)
        {
            if (min>B->A[i][j]&&B->A[i][j]!=0)
            {
                min=B->A[i][j];
                k[t]=j;
                m=j;
            }
        }
        }
        //将遍历过的元素置零
        B->A[n][m]=0;
        B->A[m][n]=B->A[n][m];
        //打印遍历的元素
        if (g[m]!=0)
        {
            if (p>1)
                printf("%s->",L->name[m]);
            else
                printf("%s\n",L->name[m]);
            g[m]=0;
            p--;
            min=wuqiong;
        }
    }
    for (int i=0;i<=B->vexnumber-1;i++)
    {
        for (int j=0;j<=B->vexnumber-1;j++)
        {
            B->A[i][j]=a[i][j];
        }
    }
}
void kruskal (e*B,v*L)
{
    int a[100][100];
    for (int i=0;i<=B->vexnumber-1;i++)
    {
        for (int j=0;j<=B->vexnumber-1;j++)
        {
            a[i][j]=B->A[i][j];
        }
    }
    //g[]判断顶点是否输出,k[]用来判断是否构成回路
    int m=0,n=0,min=wuqiong,k[MAX],g[MAX];
    int p=L->length;
    //g和k赋处值
    for (int i=0;i<=L->length;i++)
    {
        k[i]=i;
        g[i]=i;
    }
    //打印第一个顶点
    printf("%s->",L->name[m]);
    p--;
    while (p>=0)
    {
        //找到最短的边
        for (int i=0;i<=L->length;i++)
            for (int j=0;j<=L->length;j++)
            {
                if (min>B->A[i][j]&&B->A[i][j]!=0)
                {
                    min=B->A[i][j];
                    m=i;
                    n=j;
                }
            }
        //将找到的边变为0
        B->A[m][n]=0;
        B->A[n][m]=B->A[m][n];
        //判断并输出顶点
        if (k[m]!=k[n])
        {
            if (p>=1)
            {
                if (g[n]!=0)
                {
                    printf("%s->",L->name[n]);
                    g[n]=0;
                }
                else
                {
                    printf("%s->",L->name[m]);
                    g[m]=0;
                }
            }
            else
            {
                if (g[n]!=0)
                {
                    printf("%s\n",L->name[n]);
                    g[n]=0;
                }
                else
                {
                    printf("%s\n",L->name[m]);
                    g[m]=0;
                }
            }
            for (int i=0;i<=L->length;i++)
            {
                if (k[i]==n)
                    k[i]=m;
            }
            p--;
        }
        min=wuqiong;
    }
    for (int i=0;i<=B->vexnumber-1;i++)
    {
        for (int j=0;j<=B->vexnumber-1;j++)
        {
            B->A[i][j]=a[i][j];
        }
    }
}

//菜单系统
void menu (e*B,v*L)
{
    int n;
    printf("1---创建城市的信息\n");
    printf("2---使用prim算法进行通讯网的构建\n");
    printf("3---使用kruskal算法进行通讯网的构建\n");
    printf("4---对城市的信息进行修改\n");
    printf("请输入您需要进行的操作:\n");
    scanf("%d",&n);
    switch (n)
    {
        case 1:
            GetVex(L, B);
            GetEdge(B, L);
            break;
            
        case 2:
            prim2(B, L);
            break;
        case 3:
            kruskal(B, L);
            break;
        case 4:
            change(B, L);
            break;
        default:
            printf("您输入的指令有误请重新输入!\n");
            break;
    }
    
}
int main()
{
    v*L;
    L=(v*)malloc(sizeof(v));
    e*B;
    B=(e*)malloc(sizeof(e));
    while (1)
    {
        menu(B, L);
    }
    return 0;
}

报告区

第一部分:实验分析与设计(可加页)
一、 实验内容描述(问题域描述)

在 n 个城市之间建立通信联络网,则连通 n 个城市只需要 n-1 条线路。要求在 最节省经费的前提下建立这个通信网。

  1. (1) 完成城市信息的输入。
  2. (2) 完成城市信息的编辑,包括城市以及城市间距离的增加,删除,信息修改等。
  3. (3) 允许用户指定下列两种策略进行通信网的构建
    1)采用 Prim 算法进行通信网的构建; 2)采用 Kruskal 算法进行通信网的构建;
    二、 实验基本原理与设计(数据结构设计与算法设计)
    数据结构设计
    (1) 利用线性表存储图的顶点信息
    (2) 利用领接矩阵存储图的边的信息
    算法设计
    prim算法
    (1) 拟定第一个顶点为初始点查找最短边
    (2) 将查找到的最短边的顶点序号存放在k中,并将该边删除
    (3) 遍历k中存放的点的所有顶点的边找到最短的边
    (4) 重复(2)(3)步直到所有顶点输出
    Kuskal 算法
    (1) 查找所有边找到最短的边
    (2) 将边的两个顶点的记号数组变为其中一个顶点的序号
    (3) 删除最短的边
    (4) 重复(2)(3)边直到所有顶点输出

三、主要仪器设备及耗材
1.PC机
2.开发环境(比如:VC,Eclipse)

X-code

第二部分:实验调试与结果分析(可加页)
一、 调试过程(包括调试方法描述、实验数据记录,实验现象记录,实验过程发现的问题等)
1.调试方法描述
① 输入c程序,并保存;
② 编译c程序,找出程序的语法错误并改正;
③ 输入测试数据,运行c程序,若有错,查找并修改程序的逻辑错误;
④ 重复②-③步,直到得到正确的运行结果。
2.实验输入/输出数据记录
在这里插入图片描述
在这里插入图片描述
3.实验过程发现的问题
(1)如何在使用Kruskal方式的时候避免构成回路;设计另一个数组存放集合辅助判断是否构成回路
(2)如何创建一个图表
(3)初始化点集的问题
(4)在利用矩阵后矩阵的值会发生变化;设计一个新的矩阵存储该领接矩阵
二、 实验结果及分析(包括结果描述、实验现象分析、影响因素讨论、综合分析和结论等)
1.结果描述
可以实现题目所需要的所有要求
2.实验现象分析
结果正确
3.影响因素讨论
边的多少直接影响该选择哪一个算法更快
4.算法分析(包括时间和空间)
T(n)=O(n2)
S(n)=O(n2)

5.结论
实验结果均正确,满足题目要求。
三、 实验小结、建议及体会
这次的实验我主要把时间花费在如何创建一个图上,因为对图的理解不是特别透彻所以在第一步总是碰壁。我做prim算法的时间比kruskal的时间要长,应该是做prim的时候无法理解点集和边集,做出来之后,kruskal就顺利了很多。这还是体现了那点,应该要在着手一个程序之前,充分的了解其原理。
从这个实验中更能体现先理解原理在写代码;这是目前写的很长的一个代码了;500多行敲下来不出错只有好好理解原理才能办到。在今后的学习中要对原理进行更加细致的分析。

发布了10 篇原创文章 · 获赞 9 · 访问量 255

猜你喜欢

转载自blog.csdn.net/qq_45621040/article/details/104112901