案例6-1.5 旅游规划 (25 分)邻接表实现

案例6-1.5 旅游规划 (25 分) 用邻接表实现Dijkstra算法

这题一开始做的时候没想到用邻接数组做,所以就用的链表。
总的来说还是Dijkstra算法,只不过是存储方式的问题罢了,我用了四个结构体,三个用来构建邻接表,是一层一层的关系,最后一个是做Dijkstra算法用的,具体注释我在做的时候为了检查也写了不少,应该能看懂吧,用优先队列应该还可以再改进,以后再改吧,现在有点勉强…立flag
Putout-list是我检查邻接表有没有建立,建立的数据会不会出错。
另外我没做主链表的内存回收…懒的搞,反正交了能过
提交图如下:
在这里插入图片描述
代码如下:

#include <stdio.h>
#include <cctype>
#include<cstring>
#include <cstdlib>
#include <iostream>
#include <string>
#include <queue>
using namespace std;

#define INFINITY 99999

typedef struct One_point *Linklist;
struct One_point //记录单个节点出度的相关节点数据
{
    int city;
    int legth;
    int cost;
    Linklist Next;
};
typedef struct City_Head *City;
struct City_Head//每个节点的每个头,每一个都包含这个节点的与其相连节点的各个信息
{
    Linklist body;//相当于每一个链表的头
    int city;
    int link_number;
};
typedef struct Vertex_Head *Map;
struct Vertex_Head // 记录所有节点头的数据,将每一个链表的头整合!
{
    City Head;
    int Whole_edge;
    int start;
    int goal;
    int Whole_number;
};
struct Dijk
{
    int cost;
    int legth;
};


Map Creat_Graph();//创建一个图,并初始化相关数据
void Input(Map p);//输入图的数据,完整的构建一个图
Linklist Creat_Node(int city,int legth,int cost);//返回一个单节点
void Insert_list(City_Head &head,Linklist Node);//将Node插入单节点中
void Putout_list(Map p);//输出全部数据,检查正确性
void Dijkstra(Map p);

int main(int argc, char const *argv[])
{
	//freopen("F:\\测试数据\\数据结构学习与实验指导数据\\案例6-1.5 旅游规划.txt","r",stdin); 
    Map whole_city=Creat_Graph();
    Input(whole_city);
    Dijkstra(whole_city);
//    Putout_list(whole_city);
    system("pause");
    return 0;
}
void Dijkstra(Map p)
{
    bool *Visited=(bool*)malloc(sizeof(bool)*p->Whole_number);//记录是否经过
    memset(Visited,0,sizeof(bool)*p->Whole_number);
    Dijk *record=(Dijk*)malloc(sizeof(Dijk)*p->Whole_number);//记录最小值
    // memset(record,INFINITY,sizeof(Dijk)*p->Whole_number);
    for (int i = 0; i < p->Whole_number; i++)
        record[i].cost=record[i].legth=INFINITY;
    record[p->start].cost=record[p->start].legth=0;//起始位置的最优位置一定是0;
    //下面就是正式的Dijkstra算法了:

    while (true)
    {
        int i,minV=INFINITY,min;
        for ( i = 0; i < p->Whole_number; i++)
            if (!Visited[i])
                break;
        if (i == p->Whole_number)
            break; //每次都检查一遍是不是全部点都已经纳入最优解了
        
        for ( i = 0; i < p->Whole_number; i++)
        {
            if ((minV >= record[i].legth) && !Visited[i]) 
            {
                min=i; 
                minV=record[i].legth;
            }//找到距离的最小值
        }
        Visited[min]=true;
        //接下来找这个距离最小值的邻接点
        int linklegth=record[min].legth;
        int linkcost=record[min].cost;
        for (Linklist temp=p->Head[min].body;temp; temp=temp->Next)
        {
            if (!Visited[temp->city])
            {
                if (record[temp->city].legth == (temp->legth+linklegth)&&
			                record[temp->city].cost > temp->cost+linkcost)
                   record[temp->city].cost=temp->cost+linkcost;
                if (record[temp->city].legth > (temp->legth+linklegth))
				{
				    record[temp->city].legth=temp->legth+linklegth;
                	record[temp->city].cost=temp->cost+linkcost;
				}
            }
        }
    }
    cout << record[p->goal].legth << " " << record[p->goal].cost <<endl;
    free(record);
    free(Visited);
    return;
}
void Insert_list(City_Head &head,Linklist Node)//这里必须传引用,不然修改不了,因为传的是形参,不用引用用Putout输出回发现链表是空的
{
    Linklist Temp=head.body;
    head.body=Node;
    Node->Next=Temp;
}
void Input(Map p)
{
    for (int i = 0; i < p->Whole_edge; i++)
    {
        int a,b,c,d;
        scanf("%d%d%d%d",&a,&b,&c,&d);//cin极有可能超时....
        p->Head[a].link_number++;
        p->Head[b].link_number++;
        Linklist One_Node,Two_Node;
        One_Node=Creat_Node(b,c,d);
        Two_Node=Creat_Node(a,c,d);
        Insert_list(p->Head[a],One_Node);
        Insert_list(p->Head[b],Two_Node);
    }
    
}
Map Creat_Graph()
{
    Map whole_city=new Vertex_Head; //创建所有头节点的整合初始化
    cin >> whole_city->Whole_number >>whole_city->Whole_edge
    >> whole_city->start >> whole_city->goal;
    whole_city->Head=new City_Head[whole_city->Whole_number];
    memset(whole_city->Head,0,sizeof(City_Head)*whole_city->Whole_number);
    for (int i = 0; i < whole_city->Whole_number; i++)
        whole_city->Head[i].city=i;
    return whole_city;
}
Linklist Creat_Node(int city,int legth,int cost)
{
    Linklist p=new One_point;
    p->cost=cost;
    p->legth=legth;
    p->city=city;
    return p;
}
void Putout_list(Map p)
{
    cout << "该图的边数和点数分别为:" <<  p->Whole_number<< " " << p->Whole_edge <<endl;
    for (int i = 0; i < p->Whole_number; i++)
    {
        cout << "该链表的城市,连接城市的个数:" <<p->Head[i].city << " "<<p->Head[i].link_number<< endl;
        Linklist temp=p->Head[i].body;
        while (temp)
        {
            cout <<"与其相连的城市,长度和花销" <<temp->city<< " " << temp->legth << " " << temp->cost<<endl;
            temp=temp->Next;
        }
        cout <<endl;
    }
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值