数据结构实验设计

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
完整代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;

typedef long long LL;
const int N = 50, P = 131;
LL ha[N];   //ha[i]表示下标i的字符串的哈希值
int p[N];   //用于搜索结点是否联通
char place[N][21]; //城市的名称对应其下标存在place中,如place[1]="Xiamen"表示"Xiamen"对应的编号是1

int n,m; //n表示城市的数目,m表示路径的数目

struct Road {//Road结构体存储每条路径的信息
    int a, b, len;
    //a,b分别表示城市编号 len表示城市间距离
    bool operator < (const Road &W) const
    {
        return len < W.len;
    }
}roads[N];


LL hash_num(char s[])//求字符串s的哈希值
{
    LL h[20];   //h[i]表示长度为i的部分的串的hash值
    h[0] = 0;   //初始化
    int l = strlen(s);//l为s的长度
    for(int i = 0; i < l; i ++ )
        h[ i+1 ] = h[i] * P + s[i];//hash具体函数
    return h[l];//返回串s的hash值
}

//find函数用来查找
int find(char s[])
{ 
    int l = strlen(s);//l为串s的长度
    LL hs = hash_num(s);//hs为串s的hash值
    for(int i = 0; i < n; i ++)
        在所有已经存储过的串里查找有无hash值相等的,若有,输出其下标
        if(ha[i] == hs)return i; 
        //由于id是以递增的方式取的,那么到ha[i]为0后,后面的ha值全为0
        else if(ha[i] == 0)return -1; //如果没有,返回-1
    return -1;
}

//search函数用于搜索结点x所在联通树终点
int search(int x)
{
    if(p[x] != x)p[x] = search(p[x]);//x不是新的结点,往下找
    return p[x];
}

int kruskal()
{
    int cnt = 0; //已经存储过的边
    int res = 0; //最小生成树的总权值
    for(int i = 0; cnt != n - 1 && i < m; i ++ ) 
    {
        //边的信息的取出
        int a = roads[i].a;
        int b = roads[i].b;
        int w = roads[i].len;
        if( search(a) != search(b) )//两点不联通
        {
            res += w;//边权存入
            cnt ++; //边数++
            p[search(a)] = p[search(b)];//连接两个结点
            printf("第%d条线路为%s <-> %s, 路径长为%d\n",cnt,place[a],place[b],w);
        }
    }
    return res;//返回总权值
}

int main()
{
    memset(ha, 0, sizeof ha);//初始化
    scanf("%d%d", &n,&m);

    int id = 0; //id初始化
    for(int i = 0; i < n; i ++ )//p数组初始化
        p[i] = i;
        
    //创建所有路径信息
    for(int i = 0; i < m; i ++ )
    {
        printf("请输入两个地区的信息:");
        char origin[21],terminal[21];
        //origin和terminal分别为两个城市名
        int w;//边权
        scanf("%s%s%d", origin, terminal, &w);
        roads[i].len = w;
        //若find值为-1,表示地点信息未创建,则创建即可。
        if( find(origin) == -1)
        {
            roads[i].a = id;    //赋值给其一个id
            ha[id] = hash_num(origin);//求出其hash值
            strcpy(place[id], origin);//origin复制给place[i]
            id ++;
        }
        else roads[i].a = find(origin);//已经有,直接把其find值存入
        //同理
        if( find(terminal) == -1)
        {
            roads[i].b = id;
            ha[id] = hash_num(terminal);
            strcpy(place[id], terminal);
            id ++;
        }
        else roads[i].b = find(terminal);
    }

    sort(roads,roads + m);
    int res = kruskal();
    printf("总路径长为%d\n",res);
    return 0;
}

测试数据

4 5
Xiamen Shanghai 600
Shanghai Hefei 1000
Hefei Beijing 900
Beijing Xiamen 1500
Beijing Shanghai 1300

输出
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AC Maker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值