数据结构 实验10~11 图及其应用

实验目的:熟悉图的基本概念、逻辑特性、存储表示方法、基本操作和基本应用。

实验要求:熟悉图的基本概念、逻辑特性、存储表示方法,实现无向网的存储表示、图的深度优先搜索遍历、广度优先搜索遍历、单源最短路径算法。

实验内容

编写程序,实现以下功能:

(1) 实现交通网、通信网或局域网的邻接矩阵存储表示,设数据元素类型为字符串(如地名、房间号等)。

(2) 实现该网的深度和广度优先搜索遍历,输出遍历结果。

#include <iostream>
using namespace std;

//邻接矩阵
const int MaxSize = 10;      //图中最多顶点个数
int visited[MaxSize] = {0};  //全局数组变量visited初始化
class MGraph
{
public:
    MGraph (string a[], int n, int e); //构造函数
    ~MGraph(){}                    //析构函数为空
    void DFTraverse(int v);        //深度优先遍历图
    void BFTraverse(int v);        //广度优先遍历图
private:
    string vertex[MaxSize];          //存放图中顶点的数组
    int edge[MaxSize][MaxSize];    //存放图中边的数组
    int vertexNum, edgeNum;         //图的顶点数和边数
};

//构造函数——图的建立
MGraph::MGraph(string a[], int n, int e)
{
    int i, j, k;
    vertexNum = n;
    edgeNum = e;
    for(i = 0; i < vertexNum; i++){   //存储顶点
        vertex[i] = a[i];
    }
    for(i = 0; i < vertexNum; i++){   //初始化邻接矩阵
        for(j = 0; j < vertexNum; j++){
            edge[i][j] = 0;
        }
    }
    for(k = 0; k < edgeNum; k++){    //依次输入每一条边
        cin >> i >> j;
        edge[i][j] = edge[j][i] = 1;  //置有边标志
    }
}

//深度优先遍历
void MGraph::DFTraverse(int v)
{
    cout << vertex[v] << " ";
    visited[v] = 1;
    for(int j = 0; j < vertexNum; j++){
    if(edge[v][j] == 1 && visited[j] == 0)
        DFTraverse(j);
    }
}

//广度优先遍历
void MGraph::BFTraverse(int v)
{
    int w, j, Q[MaxSize];       //采用顺序队列
    int front = -1, rear = -1;  //初始化队列
    cout << vertex[v] << " ";
    visited[v] = 1;
    Q[++rear] = v;              //被访问顶点入队
    while(front != rear)        //当队列非空时
    {
        w = Q[++front];         //将队头元素出队并送到v中
        for(j = 0; j < vertexNum; j++){
           if(edge[w][j] == 1 && visited[j] == 0){
            cout << vertex[j] << " ";
            visited[j] = 1;
            Q[++rear] = j;
           }
        }
    }
}

int main()
{
    int i;
    string str[] = {"v0","v1","v2","v3"};
    MGraph MG(str, 4, 4);  //建立一个具有4个顶点4条边的无向图
    for(i = 0; i < MaxSize; i++){
        visited[i] = 0;
    }
    cout << "深度遍历序列是:";
    MG.DFTraverse(0);          //从顶点0出发进行深度优先遍历
    cout << endl;
    for(i = 0; i < MaxSize; i++){
        visited[i] = 0;
    }
    cout << "广度遍历序列是:";
    MG.BFTraverse(0);          //从顶点0出发进行广度优先遍历
    cout  << endl;
    return 0;
}

(3) *实现上述网络的邻接表存储表示,实现其广度优先搜索遍历,输出遍历结果。

#include <iostream>
using namespace std;

const int MaxSize = 10;      //图中最多顶点个数
int visited[MaxSize] = {0};  //全局数组变量visited初始化

//邻接表的存储结构
struct EdgeNode    //定义边表结点
{
    int adjvex;    //邻接点域
    EdgeNode * next;
};
struct VertexNode   //定义顶点表结点
{
    string vertex;
    EdgeNode * firstEdge;
};

//邻接表的实现
class ALGraph
{
public:
    ALGraph (string a[], int n, int e); //构造函数
    ~ALGraph();                       //析构函数
    void DFTraverse(int v);           //深度优先遍历图
    void BFTraverse(int v);           //广度优先遍历图
private:
    VertexNode adjlist[MaxSize];    //存放顶点表的数组
    int vertexNum, edgeNum;         //图的顶点数和边数
};

//构造函数——图的建立
ALGraph::ALGraph(string a[], int n, int e)
{
    int i, j, k;
    EdgeNode * s = NULL;
    vertexNum = n;
    edgeNum = e;
    for(i = 0; i < vertexNum; i++){   //输入顶点信息,初始化顶点表
        adjlist[i].vertex = a[i];
        adjlist[i].firstEdge = NULL;
    }
    for(k = 0; k < edgeNum; k++){    //依次输入每一条边
        cin >> i >> j;                //输入边所依附的两个顶点的编号
        s = new EdgeNode; s->adjvex = j;//生成一个边表结点s
        s->next = adjlist[i].firstEdge; //将结点s插入表头
        adjlist[i].firstEdge = s;
    }
}

//析构函数——图的销毁
ALGraph:: ~ALGraph()
{
    EdgeNode * p = NULL, * q = NULL;
    for(int i = 0; i < vertexNum; i++){
        p = q = adjlist[i].firstEdge;
        while(p != NULL){
            p = p->next;
            delete q;
            q = p;
        }
    }
}

//深度优先遍历
void ALGraph::DFTraverse(int v)
{
    int j;
    EdgeNode * p = NULL;
    cout << adjlist[v].vertex << " ";
    visited[v] = 1;
    p = adjlist[v].firstEdge;   //工作指针p指向顶点v的边表
    while(p != NULL)            //依次搜索顶点v的邻接点j
    {
        j = p->adjvex;
        if(visited[j] == 0) DFTraverse(j);
        p = p->next;
    }
}

//广度优先遍历
void ALGraph::BFTraverse(int v)
{
    int w, j, Q[MaxSize];       //采用顺序队列
    int front = -1, rear = -1;  //初始化队列
    EdgeNode * p = NULL;
    cout <<adjlist[v].vertex <<" ";
    visited[v] = 1;
    Q[++rear] = v;              //被访问顶点入队
    while(front != rear)        //当队列非空时
    {
        w = Q[++front];          //将队头元素出队并送到v中
        p = adjlist[w].firstEdge;//工作指针p指向顶点v的边表
        while(p != NULL)
        {
            j = p->adjvex;
       		if (visited[j] == 0) {
         		cout << adjlist[j].vertex << " ";
         		visited[j] = 1;
         		Q[++rear] = j;
       		}
       		p = p->next;
    	}
   	}
}

int main( )
{
	//测试数据是图6-20(a),边是(0 1)(0 3)(0 4)(1 2)(2 4)(3 2)(3 4)
	string str[] = {"v0", "v1", "v2", "v3", "v4"};
	int i;
	ALGraph ALG(str, 5, 7);               //建立具有5个顶点7条边的有向图
	for (i = 0; i < MaxSize; i++)
		visited[i] = 0;
	cout << "深度优先遍历序列是:";
	ALG.DFTraverse(0);                       //从顶点0出发进行深度优先遍历
	cout << endl;
	for (i = 0; i < MaxSize; i++)
		visited[i] = 0;
	cout << "广度优先遍历序列是:";
	ALG.BFTraverse(0);                      //从顶点0出发进行广度优先遍历
	cout << endl;
	return 0;
}

(4) *求从一个地点到其它各个地点的最短路径。

#include <iostream>
#define Max 503
#define INF 0xcffffff
using namespace std;

typedef struct AMGraph  							//定义图
{
    int vex, arc;
    int arcs[Max][Max];								//邻接矩阵
};

int dis[Max], path[Max];							//dis保存最短路径总权值、path通过保存路径的前驱结点来保存路径
bool book[Max];										//已找到最短路集合

void Dijkstra(AMGraph &G)							//迪杰斯特拉算法
{
    for (int i = 1; i <= G.vex; i++)
    {
        dis[i] = G.arcs[1][i];						//初始化dis数组
        path[i] = dis[i] < INF ? 1 : -1;			//初始化路径数组
    }
    book[1] = true;
    dis[1] = 0;										//起点初始化
    for (int i = 2; i <= G.vex; i++)				//遍历G.vex-1次
    {
        int mins = INF, u = 1;
        for (int j = 1; j <= G.vex; j++)			//找到当前没加入集合的最短路的后驱点
        {
            if (!book[j] && mins > dis[j])
            {
                mins = dis[j];
                u = j;
            }
        }
        book[u] = true;								//将该点加入集合
        for (int j = 1; j <= G.vex; j++)			//遍历所有其他点对其最短路进行更新(松弛操作)
        {
            if (!book[j] && dis[j] > dis[u] + G.arcs[u][j])
            {
                dis[j] = dis[u] + G.arcs[u][j];		//更新最短路径值
                path[j] = u;						//修改j的前驱为u
            }
        }
    }
}

void find(int x)									//递归输出最短路径
{
    if (path[x] == 1)
    {
        cout << 1;
    }
    else
    {
        find(path[x]);
    }
    cout << " -> " << x;
    return;
}

void putin(AMGraph &G)								//输入图
{
    cin >> G.vex >> G.arc;
    for (int i = 1; i <= G.vex; i++)				//初始化邻接矩阵
        for (int j = 1; j <= G.vex; j++)
            G.arcs[i][j] = INF;

    for (int i = 1; i <= G.arc; i++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        G.arcs[u][v] = w;
    }
}

void putout(AMGraph &G)								//输出
{
    /* cout << "起点 v1 到各点的最短路程为: \n";
    for (int i = 1; i < G.vex; i++)
    {
        cout << dis[i] << " ";
    }
    cout << dis[G.vex] << endl; */
    for (int i = 2; i <= G.vex; i++)
    {
        cout << "起点 v1 到 v" << i << " 的路径为: ";
        find(i);
        cout << " 最短路径长度为:" << dis[i] << " ";
        cout << endl;
    }
}

int main()
{
    AMGraph G;
    putin(G);
    Dijkstra(G);
    putout(G);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

再见以前说再见

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

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

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

打赏作者

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

抵扣说明:

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

余额充值