数据结构实验--实验二非线性数据结构的实现与应用

该文详细介绍了如何使用C++实现基于邻接矩阵的有向网络,包括顶点和弧的操作,如插入、删除、查找、修改等,以及深度优先遍历和广度优先遍历。此外,还实现了Dijkstra的单源最短路径算法,并提供了平分酒问题的应用示例。
摘要由CSDN通过智能技术生成

数据结构实验--实验二非线性数据结构的实现与应用


实验目的

  1. 掌握基于邻接矩阵存储结构的有向网络的实现。
  2. 掌握有向网络的两类遍历算法。
  3. 掌握有向网络的单源最短路径算法(Dijkstra)。
  4. 掌握最短路径算法的应用:平分酒。

实验要求、内容

  1. 基于邻接矩阵存储结构实现有向网络的典型操作(构造、析构、增加顶点、删除顶点、增加弧、删除弧、查找 一个顶点、修改一个顶点、查找一个弧、修改一个弧、判空、判满、图中顶点个数、图中的弧个数、深度优先遍历、 广度优先遍历),测试和调试程序。 提示:用栈实现有向网络的深度优先遍历算法,用队列实现有向网络的广度优先遍历算法。
  2. 实现有向网络的单源最短路径算法,测试和调试程序。
  3. 使用有向网络的单源最短路径算法,解决“平分酒”问题,测试和调试程序。

实验设备

计算机、Windows 操作系统、C++语言集成开发环境。

实验指导

  1. 基于邻接矩阵存储结构实现有向网络的典型操作(构造、析构、增加顶点、删除顶点、增加弧、删除弧、查找 一个顶点、修改一个顶点、查找一个弧、修改一个弧、判空、判满、图中顶点个数、图中的弧个数、深度优先遍历、 广度优先遍历),测试和调试程序。注意:不要直接定义和使用一维数组和二维数组,请通过 new 操作和 delete 操作来申请或者释放一维数组与二维 数组的空间。实现完后,执行测试程序,逐一检验自己的 Network 类所有方法是否运行正常,给出运行截图并进行文字说明, 解释各截图中输出结果的含义。
  2. 掌握有向网络的单源最短路径算法(Dijkstra),测试和调试程序。
  3. 掌握最短路径算法的应用:平分酒。

Network.h

#ifndef NETWORK_H
#define NETWORK_H

#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;

enum Error_code { success, fail, range_error1, underflow, overflow, fatal, not_present, duplicate_error, entry_found, internal_error }; 


//三个模板参数:VertexType 为顶点数据类型,ArcType 为弧数据类型,graph_size 为预先设定的顶点个数 
template <class VertexType, class ArcType, int graph_size> 
class Network //有向网络
{ 
    public: 
    Network(ArcType infinityArc);//infinityArc 为网络中初始的无穷大弧,邻接矩阵各元素的初始值 
    ~Network(); 
    void write();//以矩阵形式输出有向网络,调试时可以检查有向网络二维数组的值 
                 //由于是通用类型的顶点和弧,所以在使用该类解决问题时可能需要完成输出运算符<<的重载 
    Error_code insertVertex(VertexType dataIn);//插入顶点,数据域为 dataIn 
    Error_code deleteVertex(VertexType dltKey, ArcType infinityArc); 
    //删除顶点,其数据域中为 dltKey,将该弧变为无穷大的断弧 infinityArc
    Error_code insertArc(VertexType fromKey, VertexType toKey, ArcType newInfo, ArcType infinityArc); 
    //插入弧,该弧从 fromKey 指向 toKey,数据为 newInfo 
    Error_code deleteArc(VertexType fromKey, VertexType toKey, ArcType infinityArc); 
    //删除弧,该弧从 fromKey 指向 toKey,相当于将该弧置为无穷大的断弧 infinityArc 
    Error_code retrieveVertex(VertexType dataOut, int & i); 
    //查 DataOut 的顶点,返回该该顶点所在一维数组的位置 i 
    Error_code replaceVertex(VertexType dataOld, VertexType dataNew); 
    //查到 dataOld 的顶点,将其数据改为 dataNew 
    Error_code retrieveArc(VertexType fromKey, VertexType toKey, ArcType &dataOut); 
    //查找弧,该弧从 fromKey 指向 toKey,读出弧数据到 dataOut 
    Error_code replaceArc(VertexType fromKey, VertexType toKey, ArcType dataIn,ArcType infinityArc); 
    //修改弧,该弧从 fromKey 指向 toKey,新弧数据为 dataIn 
    VertexType getVertex(int i);//返回第 i 个顶点的数据域
    ArcType getArc(int i, int j);//返回第 i 个顶点的第 j 个弧的数据域
    bool empty();//叛图是否为空
    bool full();//叛图是否为满
    int sizeVertex(); //返回图顶点个数
    int sizeArc(); //返回图弧的个数
    int indegree(VertexType key, ArcType infinityAr); //返回顶点 key 的出度
    int outdegree(VertexType key, ArcType infinityAr); //返回顶点 key 的入度
    void depthFirst(void (*process)(VertexType dataProc), ArcType infinityArc); 
    //深度优先遍历(需要借助于栈),初始化时可能需要无穷大的断弧 infinityArc 
    void breadthFirst(void (*process)(VertexType dataProc), ArcType infinityArc); 
    //广度优先遍历(需要借助于队列),初始化时可能需要无穷大的断弧 infinityArc 
    Error_code shortestPathDistances(VertexType source, ArcType distance[], int prior[], ArcType zeroArc, ArcType infinityArc); 
    //求单源最短路径,source 为源顶点,distance 数组存储源顶点到所有顶点最短路径距离, 
    //prior 数组存储最短路径中各顶点的前驱顶点在一维数组的下标。
    //zeroArc 为距离 0,infinityArc 为距离无穷大
    protected: 
    int countVertex;//该有向网络的顶点个数 
    int countArc;//该有向网络的弧个数 
    //VertexType nodes[graph_size];//info for vertices 
    VertexType *nodes;//nodes 为一维数组,每个元素存储的是每个顶点的信息 
    //ArcType adjacency[graph_size][graph_size];//info for arcs 
    ArcType **adjacency;//adjacency 是二维数组,每个元素存储的是有向网络的弧的信息(如:权值)
    //注意,在实现这个模板类时,为了考虑通用性,0 权值不要写成 0,无穷大权值不要直接写成一个具体的大整数, 
    //可以先分别写成 ArcType 类型的 zeroArc 和 infinityAr
    typedef pair<int, int> PII;
};

#endif // NETWORK_H

Network.cpp

#include"Network.h"
template <class VertexType, class ArcType, int graph_size>
Network<VertexType, ArcType, graph_size>::Network(ArcType infinityArc)//构造函数
{
    nodes = new VertexType[graph_size];//创建顶点数组
    adjacency=new ArcType*[graph_size];//创建邻接矩阵
    for(int i=0;i<graph_size;i++)
    {
        adjacency[i]=new ArcType[graph_size];//创建邻接矩阵
        for (int j=0;j<graph_size;j++)
        {
            adjacency[i][j]=infinityArc;//其他节点的距离为无穷大
        }
    }
    countVertex=0;
    countArc=0;
}
template <class VertexType, class ArcType, int graph_size>
Network<VertexType, ArcType, graph_size>::~Network()//析构函数
{
    delete[] nodes;
    for(int i=0;i<graph_size;i++)
    {
        delete[] adjacency[i];
    }
    delete[] adjacency;
    countVertex=0;
    countArc=0;
}
template <class VertexType, class ArcType, int graph_size>
void Network<VertexType, ArcType, graph_size>::write()
//以矩阵形式输出有向网络,调试时可以检查有向网络二维数组的值
//由于是通用类型的顶点和弧,所以在使用该类解决问题时可能需要完成输出运算符<<的重载 
{
    cout<<"Network:"<<endl;
    cout<<"顶点的个数为:"<<countVertex<<endl;
    cout<<"顶点:\t";
    for(int i=0;i<countVertex;i++)
    {
        cout<<nodes[i]<<'\t';//输出顶点
    }
    cout<<endl;
    cout<<"弧的个数为:"<<countArc<<endl;
    cout<<"弧:\t"<<endl;
    for(int i=0;i<countVertex;i++)
    {
        for(int j=0;j<countVertex;j++)
        {
            cout<<adjacency[i][j]<<'\t';//输出弧
        }
        cout<<endl;
    }
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::insertVertex(VertexType dataIn)
//插入顶点,数据域为 dataIn
{
    if(countVertex==graph_size)
    {//如果顶点数量达到上限,则返回错误代码
        return overflow;
    }
    nodes[countVertex]=dataIn;//插入顶点
    countVertex++;//顶点数量加1
    return success;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::deleteVertex(VertexType dltKey, ArcType infinityArc)
//删除顶点,其数据域中为 dltKey,将该弧变为无穷大的断弧 infinityArc
{
    if(countVertex==0)//如果顶点数量为0,则返回错误代码
    {
        return underflow;
    }
    int i=0;
    if(retrieveVertex(dltKey,i)==fail)//如果没有找到顶点,则返回错误代码
    {
        return not_present;
    }
    countArc-=(indegree(dltKey,infinityArc)+outdegree(dltKey,infinityArc));
    //删除顶点后,弧数量减去该顶点的入度和出度
    for(int j=i;j<countVertex-1;j++)//删除第i行的狐
    {
        for(int k=0;k<countVertex;k++)
        {
            adjacency[j][k]=adjacency[j+1][k];
        }
    }
    for(int j=i;j<countVertex-1;j++)//删除第i列的狐
    {
        for(int k=0;k<countVertex;k++)
        {
            adjacency[k][j]=adjacency[k][j+1];
        }
    }
    while(i<countVertex-1)//删除顶点
    {
        nodes[i]=nodes[i+1];
        i++;
    }
    countVertex--;//顶点数量减1
    return success;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::insertArc(VertexType fromKey, VertexType toKey,ArcType newInfo, ArcType infinityArc)
//插入弧,起点为 start,终点为 end,权重为 weight
{
    if(countArc==graph_size*graph_size)//如果弧数量达到上限,则返回错误代码
    {
        return overflow;
    }
    int i,j;
    retrieveVertex(fromKey,i);//查找起点
    retrieveVertex(toKey,j);//查找终点
    if(i==-1||j==-1)//如果没有找到起点或终点,则返回错误代码
    {
        return not_present;
    }
    if(adjacency[i][j]!=infinityArc)//如果该弧已存在,则返回错误代码
    {
        return duplicate_error;
    }
    adjacency[i][j]=newInfo;//插入弧
    countArc++;//弧数量加1
    return success;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::deleteArc(VertexType fromKey, VertexType toKey, ArcType infinityArc)
//删除弧,起点为 start,终点为 end
{
    if(countArc==0)
    {//如果弧数量为0,则返回错误代码
        return underflow;
    }
    int i,j;
    retrieveVertex(fromKey,i);
    retrieveVertex(toKey,j);
    if(i==-1||j==-1)
    {//如果没有找到起点或终点,则返回错误代码
        return not_present;
    }
    if(adjacency[i][j]!=infinityArc)//如果该弧不存在,则返回错误代码
    {
        adjacency[i][j]=infinityArc;//删除弧
        countArc--;//弧数量减1
    }
    return success;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::retrieveVertex(VertexType dataOut, int & i)
//查 DataOut 的顶点,返回该该顶点所在一维数组的位置 i
{
    for(int j=0;j<countVertex;j++)
    {
        if(nodes[j]==dataOut)
        {//如果找到顶点,则返回该顶点所在一维数组的位置 i
            i=j;
            return success;
        }
    }
    i=-1;//如果没有找到顶点,则返回错误代码
    return fail;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>:: replaceVertex(VertexType dataOld, VertexType dataNew)
//查到 dataOld 的顶点,将其数据改为 dataNew
{
    int i;
    if(retrieveVertex(dataOld,i)==fail)
    {
        return not_present;
    }
    nodes[i]=dataNew;
    return success;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::retrieveArc(VertexType fromKey, VertexType toKey, ArcType & dataOut)
//查到 fromKey 到 toKey 的弧,将其权重赋给 dataOut
{
    int i,j;
    if(retrieveVertex(fromKey,i)==fail||retrieveVertex(toKey,j)==fail)
    {
        return not_present;
    }
    dataOut=adjacency[i][j];
    return success;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::replaceArc(VertexType fromKey, VertexType toKey, ArcType dataIn,ArcType infinityArc)
//修改弧,该弧从 fromKey 指向 toKey,新弧数据为 dataIn 
{
    int i,j;
    if(retrieveVertex(fromKey,i)==fail||retrieveVertex(toKey,j)==fail)
    {
        return not_present;
    }
    if(adjacency[i][j]==infinityArc)
    {
        countArc++;
    }
    adjacency[i][j]=dataIn;
    return success;
}
template <class VertexType, class ArcType, int graph_size>
VertexType Network<VertexType, ArcType, graph_size>::getVertex(int i)//返回第 i 个顶点的数据域
{
    return nodes[i];
}
template <class VertexType, class ArcType, int graph_size>
ArcType Network<VertexType, ArcType, graph_size>::getArc(int i, int j)//返回第 i 个顶点到第 j 个顶点的弧数据域
{
    return adjacency[i][j];
}
template <class VertexType, class ArcType, int graph_size>
bool Network<VertexType, ArcType, graph_size>:: empty()//叛图是否为空
{
    return countVertex==0;
}
template <class VertexType, class ArcType, int graph_size>
bool Network<VertexType, ArcType, graph_size>:: full()//叛图是否为满
{
    return countVertex==graph_size&&countArc==graph_size*graph_size;
}
template <class VertexType, class ArcType, int graph_size>
int Network<VertexType, ArcType, graph_size>:: sizeVertex()//返回顶点数
{
    return countVertex;
}
template <class VertexType, class ArcType, int graph_size>
int Network<VertexType, ArcType, graph_size>:: sizeArc()//返回弧数
{
    return countArc;
}
template <class VertexType, class ArcType, int graph_size>
int Network<VertexType, ArcType, graph_size>::indegree(VertexType key, ArcType infinityAr) //返回顶点 key 的出度
{
    int i;
    if(retrieveVertex(key,i)==fail)
    {
        return 0;
    }
    int count=0;
    for(int j=0;j<countVertex;j++)
    {//遍历所有顶点
        if(adjacency[i][j]!=infinityAr)
        {//如果该顶点有弧指向它,则出度加1
            count++;
        }
    }
    return count;
}
template <class VertexType, class ArcType, int graph_size>
int Network<VertexType, ArcType, graph_size>::outdegree(VertexType key, ArcType infinityAr)//返回顶点 key 的入度
{
    int i;
    if(retrieveVertex(key,i)==fail)
    {
        return 0;
    }
    int count=0;
    for(int j=0;j<countVertex;j++)
    {
        if(adjacency[j][i]!=infinityAr)
        {//如果该顶点有弧指向它,则入度加1
            count++;
        }
    }
    return count;
}
template <class VertexType, class ArcType, int graph_size>
void Network<VertexType, ArcType, graph_size>:: depthFirst(void (*process)(VertexType dataProc), ArcType infinityArc)
//深度优先遍历(需要借助于栈),初始化时可l能需要无穷大的断弧 infinityArc 
{
    if(countVertex==0)
    {//如果叛图为空,则返回
        return;
    }
    stack<int> s;
    bool *visited=new bool[countVertex];//记录是否被访问过
    for(int i=0;i<countVertex;i++)
    {//初始化 visited 数组
        visited[i]=false;
    }
    s.push(0);//入栈第一个顶点
    visited[0]=true;//设置第一个顶点为已访问
    while(!s.empty())
    {
        int data=s.top();
        s.pop();
        process(nodes[data]);//处理顶点数据域
        for(int i=countVertex-1;i>=0;i--)
        {
            if(!visited[i]&&adjacency[data][i]!=infinityArc)
            {//如果该顶点未被访问过且有弧指向它,则入栈
                s.push(i);
                visited[i]=true;
            }
        }
    }
    delete [] visited;
}
template <class VertexType, class ArcType, int graph_size>
void Network<VertexType, ArcType, graph_size>:: breadthFirst(void (*process)(VertexType dataProc), ArcType infinityArc)
//广度优先遍历(需要借助于队列),初始化时可能需要无穷大的断弧 infinityArc
{
    if (countVertex==0)
    {//如果叛图为空,则返回
        return;
    }
    queue<int> q;
    bool *visited=new bool[countVertex];//记录是否被访问过
    for(int i=0;i<countVertex;i++)
    {//初始化 visited 数组
        visited[i]=false;
    }
    q.push(0);//入队第一个顶点
    visited[0]=true;//设置第一个顶点为已访问
    while(!q.empty())
    {
        int data=q.front();
        q.pop();
        process(nodes[data]);//处理顶点数据域
        for(int i=0;i<countVertex;i++)
        {
            if(!visited[i]&&adjacency[data][i]!=infinityArc)
            {//如果该顶点未被访问过且有弧指向它,则入队
                q.push(i);
                visited[i]=true;
            }
        }
    }
    delete [] visited;
}
template <class VertexType, class ArcType, int graph_size>
Error_code Network<VertexType, ArcType, graph_size>::shortestPathDistances(VertexType source, ArcType distance[], int prior[], ArcType zeroArc, ArcType infinityArc)
//求单源最短路径,source 为源顶点,distance 数组存储源顶点到所有顶点最短路径距离, 
//prior 数组存储最短路径中各顶点的前驱顶点在一维数组的下标。
//zeroArc 为距离 0,infinityArc 为距离无穷大
{
    if(countVertex==0)
    {//如果叛图为空,则返回
        return fail;
    }
    bool *visited=new bool[countVertex];//记录是否被访问过
    for(int i=0;i<countVertex;i++)
    {
        visited[i]=false;
    }
    int cnt=0;//source的位置
    retrieveVertex(source,cnt);
    distance[cnt]=zeroArc;//设置源顶点到自身的距离为0
    for(int i=0;i<countVertex;i++)
    {
        int minIndex=-1;//最短距离的顶点在一维数组的下标
        for(int j=0;j<countVertex;j++)
        {//找出最短距离的顶点
            if(!visited[j]&&(minIndex==-1||distance[j]<distance[minIndex]))
            {//如果该顶点未被访问过且距离小于当前最短距离,则设置为最短距离的顶点
                minIndex=j;
            }
        }
        if(minIndex==-1)
        {//如果没有找到最短距离的顶点,则说明图中没有路径到源顶点
            delete [] visited;
            return fail;
        }
        visited[minIndex]=true;//设置最短距离的顶点为已访问
        for(int j=0;j<countVertex;j++)
        {//更新最短距离
            if(!visited[j]&&adjacency[minIndex][j]!=infinityArc)
            {
                if(distance[minIndex]+adjacency[minIndex][j]<distance[j])
                {
                    distance[j]=distance[minIndex]+adjacency[minIndex][j];//更新距离
                    prior[j]=minIndex;//设置前驱顶点
                }
            }
        }
    }
    delete [] visited;
    return success;
}
//Dijkstra 优先队列优化版本
// template <class VertexType, class ArcType, int graph_size>
// Error_code Network<VertexType, ArcType, graph_size>::shortestPathDistances(VertexType source, ArcType distance[], int prior[], ArcType zeroArc, ArcType infinityArc)
// //求单源最短路径,source 为源顶点,distance 数组存储源顶点到所有顶点最短路径距离, 
// //prior 数组存储最短路径中各顶点的前驱顶点在一维数组的下标。
// //zeroArc 为距离 0,infinityArc 为距离无穷大
// {
//     if(countVertex==0)
//     {//如果叛图为空,则返回
//         return fail;
//     }
//     bool *visited=new bool[countVertex];//记录是否被访问过
//     for(int i=0;i<countVertex;i++)
//     {
//         visited[i]=false;
//     }
//     int cnt=0;//source的位置
//     retrieveVertex(source,cnt);
//     distance[cnt]=zeroArc;//设置源顶点到自身的距离为0
//     priority_queue<PII,vector<PII>,greater<PII>> res;//优先队列,存储最短距离的顶点,小顶堆
//     res.push({0,cnt});
//     while(!res.empty())
//     {
//         PII top=res.top();
//         res.pop();
//         int minIndex=top.second;
//         if(visited[minIndex])
//         {
//             continue;
//         }
//         visited[minIndex]=true;//设置最短距离的顶点为已访问
//         for(int j=0;j<countVertex;j++)
//         {//更新最短距离
//             if(!visited[j]&&adjacency[minIndex][j]!=infinityArc)
//             {
//                 if(distance[minIndex]+adjacency[minIndex][j]<distance[j])
//                 {
//                     distance[j]=distance[minIndex]+adjacency[minIndex][j];//更新距离
//                     prior[j]=minIndex;//设置前驱顶点
//                     res.push({distance[j],j});//更新优先队列
//                 }
//             }
//         }
//     }
//     delete [] visited;
//     return success;
// }

main.cpp

#include"Network.h"
#include"Network.cpp"
const int graph_size=20,zero=0,infinity=999;
void traverse(char a)
{
    cout<<a<<'\t';
}
void text1()//测试网络类
{
    Network<char,int,graph_size> net(infinity);
    net.insertVertex('A');
    net.insertVertex('B');
    net.insertVertex('C');
    net.insertVertex('D');
    net.insertVertex('E');
    net.insertArc('A','B',1,infinity);
    net.insertArc('A','C',1,infinity);
    net.insertArc('B','C',1,infinity);
    net.insertArc('B','D',1,infinity);
    net.insertArc('C','A',1,infinity);
    net.insertArc('C','D',1,infinity);
    net.insertArc('D','B',1,infinity);
    net.insertArc('D','E',1,infinity);
    net.insertArc('E','D',1,infinity);
    net.insertArc('E','C',1,infinity);
    net.insertArc('E','B',1,infinity);
    net.write();
    cout<<endl;
    net.deleteVertex('E',infinity);
    cout<<"删除顶点E后:"<<endl;
    net.write();
    cout<<endl;
    net.deleteArc('B','C',infinity);
    cout<<"删除弧(B,C)后:"<<endl;
    net.write();
    cout<<endl;
    int res;
    net.retrieveVertex('B',res);
    cout<<"查找顶点B的位置为:"<<res+1<<endl;
    net.retrieveArc('B','C',res);
    cout<<"查找弧(B,C)的权值为:"<<res<<endl;
    net.replaceArc('B','C', 2 ,infinity);
    cout<<"更改弧(B,C)的权值为:2"<<endl;
    net.replaceVertex('D','E');
    cout<<"替换顶点D为E后:"<<endl;
    net.write();
    if(net.empty())
    {
        cout<<"网络为空"<<endl;
    }
    else
    {
        cout<<"网络不为空"<<endl;
    }
    if(net.full())
    {
        cout<<"网络已满"<<endl;
    }
    else
    {
        cout<<"网络未满"<<endl;
    }
    cout<<"网络中顶点的个数为:"<<net.sizeVertex()<<endl;
    cout<<"网络中弧的个数为:"<<net.sizeArc()<<endl;
    cout<<"深度优先遍历:"<<endl;
    net.depthFirst(traverse,infinity);
    cout<<endl;
    cout<<"广度优先遍历:"<<endl;
    net.breadthFirst(traverse,infinity);
    cout<<endl;
}
void text2()//测试求单源最短路径
{
    Network<char,int,graph_size> net(infinity);
    net.insertVertex('A');
    net.insertVertex('B');
    net.insertVertex('C');
    net.insertVertex('D');
    net.insertVertex('E');
    net.insertArc('A','B',1,infinity);
    net.insertArc('A','C',1,infinity);
    net.insertArc('B','C',1,infinity);
    net.insertArc('B','D',1,infinity);
    net.insertArc('C','A',1,infinity);
    net.insertArc('C','D',1,infinity);
    net.insertArc('D','B',1,infinity);
    net.insertArc('D','E',1,infinity);
    net.insertArc('E','D',1,infinity);
    net.insertArc('E','C',1,infinity);
    net.insertArc('E','B',1,infinity);
    net.write();
    int *distance=new int[graph_size],*prior=new int[graph_size];
    for(int i=0;i<graph_size;i++)
    {
        distance[i]=infinity;
        prior[i]=i;
    }
    net.shortestPathDistances('A',distance,prior,zero,infinity);
    cout<<"A到其他顶点的最短路径为:"<<endl;
    for(int i=0;i<net.sizeVertex();i++)
    {
        cout<<"A到"<<char(i+'A')<<"的最短路径为:"<<distance[i]<<endl;
    }
    cout<<"A到其他顶点的最短路径的前驱顶点为:"<<endl;
    for(int i=0;i<net.sizeVertex();i++)
    {
        cout<<"A到"<<char(i+'A')<<"的最短路径的前驱顶点为:"<<char(prior[i]+'A')<<endl;
    }
    delete[] distance;
    delete[] prior;
}
struct State//酒瓶的状态
{
    int a,b,c;
    State(int a=0,int b=0,int c=0)
    {
        this->a=a;
        this->b=b;
        this->c=c;
    }
    bool operator==(const State &s)const
    {//重载==运算符
        return a==s.a&&b==s.b&&c==s.c;
    }
    friend ostream& operator<<(ostream &output,const State &s)
    {//重载<<运算符
        output<<"("<<s.a<<","<<s.b<<","<<s.c<<")";
        return output;
    }
};

void text3()//平分酒
{
    Network<State,int,graph_size> net(infinity);
    State start(3,5,0),end(0,4,4);//初始状态和终止状态
    int s[]={3,5,8};//酒瓶的最大容量
    int sum=8;//酒的总量
    for(int i=0;i<=s[0];i++)
        for(int j=0;j<=s[1];j++)
            if(i+j<=sum)
            {
                State temp(i,j,sum-i-j);
                if((temp.a==0||temp.a==s[0])||(temp.b==0||temp.b==s[1])||(temp.c==0||temp.c==s[2]))
                {//至少有一个达到最大值或0
                    net.insertVertex(temp);//插入状态
                }
            }
    for(int i=0;i<net.sizeVertex();i++)
        for(int j=0;j<net.sizeVertex();j++)
        {
            State x1=net.getVertex(i),x2=net.getVertex(j);
            if(i!=j)
            {
                if(x1.a!=x2.a&&x1.b!=x2.b&&x1.c==x2.c)
                {//条件1:只能有2个变量改变
                    if(x2.a==0||x2.b==0||x2.a==s[0]||x2.b==s[1])
                    {//条件2:改变的2个变量中至少有一个达到最大值或0
                        net.insertArc(x1,x2,1,infinity);//满足直接可达,添加有向边1
                    }
                }
                else if(x1.a!=x2.a&&x1.c!=x2.c&&x1.b==x2.b)
                {
                    if(x2.a==0||x2.c==0||x2.a==s[0]||x2.c==s[2])
                    {
                        net.insertArc(x1,x2,1,infinity);
                    }
                }
                else if(x1.b!=x2.b&&x1.c!=x2.c&&x1.a==x2.a)
                {
                    if(x2.b==0||x2.c==0||x2.b==s[1]||x2.c==s[2])
                    {
                        net.insertArc(x1,x2,1,infinity);
                    }
                }
            }
        }
    net.write();
    int *distance=new int[graph_size],*prior=new int[graph_size];
    for(int i=0;i<graph_size;i++)
    {
        distance[i]=infinity;
        prior[i]=i;
    }
    net.shortestPathDistances(start,distance,prior,zero,infinity);
    int cnt1,cnt2;//开始和结束在net的位置
    net.retrieveVertex(start,cnt1);
    net.retrieveVertex(end,cnt2);
    cout<<"最短路径的长度为:"<<distance[cnt2]<<endl;
    cout<<"从"<<start<<"到"<<end<<"的最短路径为:"<<endl;
    stack<State> path;//路径栈
    path.push(end);
    while(prior[cnt2]!=cnt1)
    {//查找路径
        path.push(net.getVertex(prior[cnt2]));
        cnt2=prior[cnt2];
    }
    path.push(start);
    while(!path.empty())
    {//输出路径
        if(path.size()!=1)cout<<path.top()<<"->";
        else cout<<path.top()<<endl;
        path.pop();
    }
    delete[] distance;
    delete[] prior;
}
int main()
{   
    text1();//测试网络类
    //text2();//测试最短路径算法
    //text3();//测试平分酒
    system("pause");
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

NeutronShip

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

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

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

打赏作者

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

抵扣说明:

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

余额充值