(数据结构)图的应用,一个简单的学校地图.包含的内容:图的最短路径算法 和 图的深度优先遍历算法

时间:2022-06-25 09:53:15

数据结构,图的应用实例,一个简单的学校地图.

其中包含的内容:图的最短路径算法(迪杰斯特拉算法) 和 图的深度优先遍历算法

其中程序功能: 1.存储简单的学校地图并显示; 2.给出一个点,能够输出从此点到其他顶点的最短路径及最短距离; 3.给出两个顶点,能够输出次两点之间所有路径及距离 和 最短路径及距离

学校地图:(建立图的基础,看着这个图会容易理解一点)

(数据结构)图的应用,一个简单的学校地图.包含的内容:图的最短路径算法 和 图的深度优先遍历算法

程序运行结果截图:

(数据结构)图的应用,一个简单的学校地图.包含的内容:图的最短路径算法 和 图的深度优先遍历算法

(数据结构)图的应用,一个简单的学校地图.包含的内容:图的最短路径算法 和 图的深度优先遍历算法

(数据结构)图的应用,一个简单的学校地图.包含的内容:图的最短路径算法 和 图的深度优先遍历算法

(数据结构)图的应用,一个简单的学校地图.包含的内容:图的最短路径算法 和 图的深度优先遍历算法

(数据结构)图的应用,一个简单的学校地图.包含的内容:图的最短路径算法 和 图的深度优先遍历算法

废话不说,直接上程序源码. 自己需要的地方可以看一下源码,找一下自己需要的地方

我写的代码是用C++干着面向过程的勾当...真心觉得自己能力不咋滴...贴出代码, 大家有需要的函数可以参考一下原理.


程序源码:

main.cpp

#include "GraphList.h"

int main()
{
    GraphList graphList;//图
    int choice;//存放用户的选择
    char element_1, element_2;
    int locate_1, locate_2;
    int Path[MAX_VERTEX_NUM], Dest[MAX_VERTEX_NUM];
    bool DIJFlag = false;//标记是否进行过了DIJ算法

    createGraph(graphList);

    cout << "A.学校正门, B.研究院, C.校训石, D.体育场, E.M楼, F.G楼, G.主楼, H.C楼, I.教师公寓, J.食堂, K.N楼\n"
         << "\n--The output formate: (Source,Destination,Value)"
         << "\n------------------------------------------------------------------------"
         << "\n--The Graph have been created:";
    printGraph(graphList);

    cout << "\n------------------------------------------------------------------------"
         << "\n--Program Menu:"
         << "\n--1.shortest path between source to other vertex(Dijkstra Algorithm)."
         << "\n--2.all path and shortest path between two vertexs(Floyd Algorithm)."
         << "\n--0.exit."
         << "\n\n-------------------------------------------"
         << "\n--Please enter your choice(0/1/2): ";
    cin >> choice;
    while(choice != 0)
    {
        switch(choice)
        {
        case 1:
            cout << "\n--Please enter one vertex: ";
            cin >> element_1;
            if((locate_1=findNode(graphList, element_1)) == -1) return 0;

            if(!DIJFlag)//如果没有进行了DIJ算法查找最短路径
            {
                shortestPath_DIJ(graphList, locate_1, Path, Dest);
                DIJFlag = true;
            }
            printShortestPath_DIJ(graphList, locate_1, Path, Dest);
            break;
        case 2:
            cout << "\n--Please enter two vertexs(e.g.: A B): ";
            cin >> element_1 >> element_2;
            locate_1 = findNode(graphList, element_1);
            locate_2 = findNode(graphList, element_2);
            if((locate_1==-1) || (locate_2==-1)) return 0;

            if(!DIJFlag)//如果没有进行了DIJ算法查找最短路径
            {
                shortestPath_DIJ(graphList, locate_1, Path, Dest);
                DIJFlag = true;
            }
            cout << "All Path  Between " << element_1 << " and " << element_2 << ":";
            allPath_2Vexs(graphList, locate_1, locate_2);//输出所有路径
            cout << "\n--------------------------------------";
            printShortestPath_2Vexs(graphList, locate_1, locate_2, Path, Dest);
            break;
        default:
            cout << "--Your input unavailable!\n";
            return 0;
        }
        cout << "\n\n-------------------------------------------"
             << "\n--Please enter your choice(0/1/2): ";
        cin >> choice;
    }

    deleteGraph(graphList);//删除图,防止内存泄露
    return 0;
}


GraphList.h

#ifndef GRAPHLIST_H_INCLUDED
#define GRAPHLIST_H_INCLUDED

#include <iostream>
#include <string>
#include <cstdlib>
#include <stack>
#include <vector>
using namespace std;

#define MAX_VERTEX_NUM 11//最大支持的节点数
#define INFINITY 1000//表示无穷大
typedef int EdgeValueType;//定义边权重类型
typedef char VertexType;//定义顶点表顶点的内容类型

typedef struct EdgeNode//边表节点
{
    int adjvexLocate;//该弧所指向的顶点在定点表中的位置
    EdgeValueType value;//权重
    EdgeNode *next;//指向下一个节点
} EdgeNode;

typedef struct VertexNode//顶点表
{
    VertexType data;//顶点名称
    EdgeNode *firstarc;//指向第一条依附顶点的指针
} VertexNode, VertexList[MAX_VERTEX_NUM]; //顶点节点,顶点表

typedef struct GraphList
{
    VertexList vertexList;//建立顶点表
    int vertexNum, edgeNum;//整个图中存放顶点、边的个数
} GraphList;

//函数声明
int findNode(GraphList &graphList, char element);
bool createGraph(GraphList &graphList);
bool printGraph(GraphList &graphList);
void shortestPath_DIJ(GraphList &graphList, int vex, int P[], int D[]);//单源最短路径算法
void printShortestPath_DIJ(GraphList &graphList, int vex, int Path[], int Dest[]);//打印出生成的单源最短路径
void printShortestPath_2Vexs(GraphList &graphList, int vex1, int vex2, int Path[], int Dest[]);//打印两点之间最短路径及距离
void allPath_2Vexs(GraphList &graphList, int startVex, int endVex);//任意两点之间的所有路径
void visit(GraphList &graphList, int vex, int endVex, bool status[], vector<int> &pathStack, int length);
bool deleteGraph(GraphList &graphList);//销毁图,防止内存泄露

#endif // GRAPHLIST_H_INCLUDED


GraphList.cpp

#include "GraphList.h"

int findNode(GraphList &graphList, char element)//查找顶点,工具方法
{
    int i;
    for(i=0; i<graphList.vertexNum; i++)
    {
        if(element == graphList.vertexList[i].data)
        {
            break;
        }
    }
    if(i >= graphList.vertexNum)
    {
        cout << "The element not find\n";
        return -1;
    }
    return i;
}

bool createGraph(GraphList &graphList)//创建图,并执行初始化
{
    //为了方便,所有顶点以及边都已经在程序内部定义好了
    //初始化定点表
    graphList.vertexNum = 0;//顶点数
    graphList.edgeNum = 0;//边数
    int value = 0;//暂时存放从邻接矩阵中读取的数值

    char vexArray[MAX_VERTEX_NUM] = {'A','B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'};
    for(int v=0; v<MAX_VERTEX_NUM; v++)//建立顶点表
    {
        if(vexArray[v] != '\0') graphList.vertexNum++;
        graphList.vertexList[v].data = vexArray[v];
        graphList.vertexList[v].firstarc = NULL;
    }
    //初始化边表
    int edgeArray[MAX_VERTEX_NUM][MAX_VERTEX_NUM] = {//初始化邻接矩阵
    //   0,1,2,3,4,5,6,7,8,9,10
        {0,70,40,100,0,0,0,0,0,0,0},//0
        {70,0,50,0,0,0,0,60,0,0,0},//1
        {40,0,0,0,0,100,50,0,0,0,0},//2
        {100,0,0,0,70,65,0,0,0,0,0},//3
        {0,0,0,70,0,40,0,0,0,0,130},//4
        {0,0,100,65,40,0,40,0,0,150,140},//5
        {0,0,50,0,0,40,0,115,0,0,0},//6
        {0,60,0,0,0,0,115,0,105,0,0},//7
        {0,0,0,0,0,0,0,105,0,110,0},//8
        {0,0,0,0,0,150,0,0,110,0,55},//9
        {0,0,0,0,130,140,0,0,0,55,0}//10
    };

    for(int i=0; i<graphList.vertexNum; i++)
    {
        EdgeNode *temp = NULL;
        EdgeNode *Node = NULL;//存放新生成的节点
        for(int j=0; j<graphList.vertexNum; j++)
        {

            if((value = edgeArray[i][j]) != 0)//有边
            {
                if(!(Node = new EdgeNode))
                {
                    cerr << "No Enough Memory!";
                    exit(1);
                }
                Node->adjvexLocate = j;
                Node->value = value;
                Node->next = NULL;//生成节点
                graphList.edgeNum++;
                if(graphList.vertexList[i].firstarc == NULL)//第一个节点
                {
                    graphList.vertexList[i].firstarc = Node;
                    temp = Node;
                }
                else
                {
                    temp->next = Node;
                    temp = Node;
                }
            }
        }
    }
    return true;
}

bool printGraph(GraphList &graphList)//输出图
{
    EdgeNode *temp = NULL;
    //if(!&graphList) return false;
    for(int i=0; i<graphList.vertexNum; i++)
    {
        cout << "\n" << graphList.vertexList[i].data << ": ";
        temp = graphList.vertexList[i].firstarc;
        while(temp)
        {
            cout << " (" << graphList.vertexList[i].data << "," << graphList.vertexList[temp->adjvexLocate].data << ","
                 << temp->value << ") ";
            temp = temp->next;
        }
    }
    return true;
}

void shortestPath_DIJ(GraphList &graphList, int vex, int Path[], int Dest[])///单源最短路径算法
{
    bool finalShortest[MAX_VERTEX_NUM];
    EdgeNode *temp = NULL;
    int minValue = INFINITY;//用作寻找最小的路径权值
    int v = 0;//记录每一次寻找的最小路径终点的位置

    for(int i=0; i<graphList.vertexNum; i++)//第一步初始化
    {
        finalShortest[i] = false;
        Path[i] = -1;//没有前驱,即没有路径
        Dest[i] = INFINITY;//存放vi与给出的源点之间的最短路径
    }

    finalShortest[vex] = true;
    Dest[vex] = 0;//修改源点的值
    Path[vex] = -1;

    temp = graphList.vertexList[vex].firstarc;
    while(temp)
    {
        Dest[temp->adjvexLocate] = temp->value;
        Path[temp->adjvexLocate] = vex;//前驱
        temp = temp->next;
    }//初始化完成

    for(int i=1; i<graphList.vertexNum; i++)//执行n-1次循环,对剩余的n-1个顶点操作
    {
        minValue = INFINITY;
        for(int j=0; j<graphList.vertexNum; j++)
        {
            if(!finalShortest[j])//还没有求出最短路径
            {
                if(Dest[j] < minValue)
                {
                    v = j;
                    minValue = Dest[j];
                }//if(Dest[j] < minValue)
            }//if(!finalShortest[j])
        }//for
        finalShortest[v] = true;//将此终点加入已求出最短路径的集合
        //更新参数
        //temp = graphList.vertexList[v].firstarc;
        for(int j=0; j<graphList.vertexNum; j++)
        {
            int vValue = INFINITY;//存放v 与 j之间的权重
            temp = graphList.vertexList[v].firstarc;//一句话如果放错位置就会出现无法预料的错误!
            while(temp)
            {
                if(temp->adjvexLocate == j)
                {
                    vValue = temp->value;
                    break;
                }
                temp = temp->next;
            }
            if(!finalShortest[j] && (minValue+vValue<Dest[j]))
            {
                Dest[j] = minValue + vValue;//更新为更小的权重
                Path[j] = v;//更新前驱节点
            }//if(!finalShortest[j] && minValue+vValue<Dest[j])
        }//for(int j=0; j<graphList.vertexNum; j++)
    }//for(int i=1; i<graphList.vertexNum; i++)
}

void printShortestPath_DIJ(GraphList &graphList, int vex, int Path[], int Dest[])
{
    int pre = 0;
    cout << "The Shortest Path From "<< graphList.vertexList[vex].data << " to Other Vertexs:";
    for(int i=0; i<graphList.vertexNum; i++)
    {
        if(Dest[i] >= INFINITY || i == vex) continue;

        cout << "\n\t(" << graphList.vertexList[vex].data << "->" << graphList.vertexList[i].data
             << "):  Length = " << Dest[i] << ";  Path: " << graphList.vertexList[i].data;
        pre = Path[i];
        while(pre != -1)
        {
            cout << " " << graphList.vertexList[pre].data;
            pre = Path[pre];
        }
    }
}

//打印两点之间最短路径及距离
void printShortestPath_2Vexs(GraphList &graphList, int vex1, int vex2, int Path[], int Dest[])
{
    int pre = 0;
    cout << "\nThe Shortest Path Between " << graphList.vertexList[vex1].data << " to "
         << graphList.vertexList[vex2].data << " :";

    for(int i=0; i<graphList.vertexNum; i++)
    {
        if(i == vex2)
        {
            cout << "\n\t(" << graphList.vertexList[vex1].data << "->" << graphList.vertexList[vex2].data
                 << "):  Length = " << Dest[i] << "\tPath: " << graphList.vertexList[i].data;
            pre = Path[i];
            while(pre != -1)
            {
                cout << " " << graphList.vertexList[pre].data;
                pre = Path[pre];
            }
            return;
        }
    }
}

bool deleteGraph(GraphList &graphList)//销毁图
{
    if(graphList.vertexNum == 0) return false;
    EdgeNode *temp = NULL;

    for(int i=0; i<graphList.vertexNum; i++)//定点表中每个顶点
    {
        if((temp = graphList.vertexList[i].firstarc) == NULL) continue;

        while(temp)
        {
            graphList.vertexList[i].firstarc = temp->next;
            delete temp;
            temp = graphList.vertexList[i].firstarc;
        }
    }
    return true;
}

void allPath_2Vexs(GraphList &graphList, int startVex, int endVex)
{
    if(startVex == endVex)
    {
        return;
    }


    bool status[MAX_VERTEX_NUM] = {false};//标记点被访问的状态
    vector<int> pathStack;//记录访问到节点的位置
    int length = 0;

    visit(graphList, startVex, endVex, status, pathStack, length);
}

//递归访问每个元素
void visit(GraphList &graphList, int vex, int endVex, bool status[], vector<int> &pathStack, int length)//对vex点进行访问
{
    if(vex == endVex)//找到了终点
    {
        //cout << "\n\tLength=" << pathStack.size()+1 << "\tPath: ";
        cout << "\n\tLength=" << length << "\tPath: ";
        for(unsigned int i=0; i<pathStack.size(); i++)
        {
            cout << " " << graphList.vertexList[pathStack[i]].data;
            //length += graphList.vertexL
        }
        cout << " " << graphList.vertexList[endVex].data;
        return;
    }

    status[vex] = true;
    pathStack.push_back(vex);
    EdgeNode *current = NULL;

    for(current=graphList.vertexList[vex].firstarc; current!=NULL; current = current->next)
    {
        if(!status[current->adjvexLocate])
        {
            length += current->value;
            visit(graphList, current->adjvexLocate, endVex, status, pathStack, length);
        }
    }

    status[vex] = false;//修改标志
    pathStack.pop_back();//回溯
}