图与景区管理系统

图与景区管理系统

功能简介

序号功能实现原理
1创建景区景点图文件读写、结构体
2查询景点信息边的关系
3旅游景点导航链表、深度优先搜索
4搜索最短路径Dijkstra算法、最短路径
5铺设电路规划Prim算法、最小生成树
0退出exit(0)

源代码(Visual Studio 2017下)

数据结构头文件

Graph.h

#ifndef GRAPH_H
#define GRAPH_H

struct Vex
{
    int num;//景点编号
    char name[20];//景点名字
    char desc[1024];//景点介绍
};
struct Edge
{
    int vex1;//边的第一个顶点
    int vex2;//边的第二个顶点
    int weight;//权值
};
struct Graph
{
    int m_aAdjMatrix[20][20];//邻接矩阵
    Vex m_aVexs[20];//顶点信息组数
    int m_nVexNum;//当前图的顶点个数
};
typedef struct Path
{
    int vexs[20];//保存一条路径
    Path *next;//下一条路径
}*PathList;//链表PathList用来保存所有路径

void Init(void);
bool InsertVex(Vex sVex);
bool InsertEdge(Edge sEdge);
Vex GetVex(int nVex);
int FindEdge(int nVex, Edge aEdge[]);
int GetVexnum(void);
void DFS(int nVex, bool isVisited[], int &nIndex, PathList &pList);
void DFSTraverse(int nVex,PathList &pList);
bool TraverseOrNot(int now[], int i);
int FindShortPath(int nVexStart, int nVexEnd, Edge aPath[]);
int FindMinTree(Edge aPath[]);
#endif GRAPH_H
数据结构源文件Graph.cpp

#include"Graph.h"
#include<iostream>
using namespace std;
Graph graph;
int EdgeNum;
Edge aEdge[100];
int allPath[20][20] = {0};
int PathNum=0;
//bool isVisited[20];
bool TraverseOrNot(int now[], int i)
{
    for (int p = 0; p < PathNum; p++)
    {
        for (int q = 0; q < i; q++)
        {
            if (allPath[p][q] != now[q])
            {
                break;
            }
            if ((allPath[p][q] == now[q] && q == i))
                return true;//曾被访问
        }
    }
    return false;
}


void Init(void)
{
    for (int i = 0; i < 20; i++)
    {
        for (int j = 0; j < 20; j++)
        {
            if (i == j)
                graph.m_aAdjMatrix[i][j] = 0;
            else
                graph.m_aAdjMatrix[i][j] = 0xffff;
        }
    }
    graph.m_nVexNum = 0;
}

bool InsertVex(Vex sVex)
{
    if (graph.m_nVexNum >= 20)
    {//顶点已满
        return false;
    }
    graph.m_aVexs[graph.m_nVexNum++] = sVex;
    return true;
}

bool InsertEdge(Edge sEdge)
{
    if (sEdge.vex1 == sEdge.vex2)
        return false;
    graph.m_aAdjMatrix[sEdge.vex1][sEdge.vex2] = sEdge.weight;
    graph.m_aAdjMatrix[sEdge.vex2][sEdge.vex1] = sEdge.weight;
    return true;
}

Vex GetVex(int nVex)
{
    return graph.m_aVexs[nVex];
}
/*
int FindEdge(int nVex, Edge aEdge[])
{
    for (int i = 0; i < EdgeNum; i++)
    {
        if (aEdge[i].vex1 == nVex)
        {
            cout << graph.m_aVexs[aEdge[i].vex1].name << "->" << graph.m_aVexs[aEdge[i].vex2].name << " " << aEdge[i].weight << endl;
        }
        if(aEdge[i].vex2 == nVex)
            cout << graph.m_aVexs[aEdge[i].vex2].name << "->" << graph.m_aVexs[aEdge[i].vex1].name << " " << aEdge[i].weight << endl;
    }
    return true;
}
*/

int FindEdge(int nVex, Edge aEdge[])
{
    int k = 0;
    for (int i = 0; i < graph.m_nVexNum; i++)
    {
        if (graph.m_aAdjMatrix[i][nVex] > 0 && graph.m_aAdjMatrix[i][nVex] < 0xffff)
        {
            aEdge[k].vex1 = nVex;
            aEdge[k].vex2 = i;
            aEdge[k].weight = graph.m_aAdjMatrix[i][nVex];
            k++;
        }
    }
    return k;
}

int GetVexnum(void)
{
    return graph.m_nVexNum;
}
/*
//输出一行的深度优先搜索
void DFS(int nVex, bool isVisited[], int &nIndex, PathList &pList)
{//nIndex记录遍历的深度
    if (nIndex == graph.m_nVexNum - 1)
        pList->next = NULL;
    isVisited[nVex] = true;
    pList->vexs[nIndex++] = nVex;
    for (int i = 0; i < graph.m_nVexNum; i++)
    {
        if (graph.m_aAdjMatrix[nVex][i] > 0 && graph.m_aAdjMatrix[nVex][i] < 0xffff && !isVisited[i]&&pList->next)
        {
            DFS(i, isVisited, nIndex, pList);//递归调用DFS
            isVisited[i] = false;
            nIndex--;
        }
    }
}
*/
void DFS(int nVex, bool isVisited[], int &nIndex, PathList &pList)
{//nIndex记录遍历的深度


    //if (nIndex == graph.m_nVexNum -1 && TraverseOrNot(pList->vexs, graph.m_nVexNum))
    //{
    //  nIndex--;
    //}

    isVisited[nVex] = true;
    pList->vexs[nIndex++] = nVex;
    //判断是否所有的顶点都已被访问过
    int nVexNum = 0;
    for (int i = 0; i < graph.m_nVexNum; i++)
    {
        if (isVisited[i])
            nVexNum++;
    }
    if (nIndex == graph.m_nVexNum )
    {
        pList ->next= (PathList)malloc(sizeof(Path));
        for (int i = 0; i < graph.m_nVexNum; i++)
        {
            pList->next->vexs[i] = pList->vexs[i];
        }
        pList = pList->next;
        pList->next = NULL;
    }

    else 
    {
        for (int i = 0; i < graph.m_nVexNum; i++)
        {
            if (graph.m_aAdjMatrix[nVex][i] > 0 && graph.m_aAdjMatrix[nVex][i] < 0xffff && !isVisited[i])
            {
                DFS(i, isVisited, nIndex, pList);//递归调用DFS
                isVisited[i] = false;
                nIndex--;
            }
        }
    }

}

void DFSTraverse(int nVex, PathList &pList)
{
    int nIndex = 0;
    bool isVisited[20] = { false };
    DFS(nVex, isVisited, nIndex, pList);
}

int FindShortPath(int nVexStart, int nVexEnd, Edge aPath[])
{
    int nShortPath[20][20];//保存最短路径
    int nShortDistance[20];//保存最短距离
    bool isVisited[20];//判断某顶点是否已加入到最短路径
    int v;

    //初始化
    for (v = 0; v < graph.m_nVexNum; v++)
    {
        isVisited[v] = false;
        if (graph.m_aAdjMatrix[nVexStart][v])
        {
            //初始化该顶点到其他顶点的最短距离,默认为两顶点间的距离
            nShortDistance[v] = graph.m_aAdjMatrix[nVexStart][v];
        }
        else
        {
            //如果两顶点v和nVexStart不相连,则最短距离为最大值
            nShortDistance[v] = 0xffff;
        }
        nShortPath[v][0] = nVexStart;//起始点为nVexStart
        for (int w = 1; w < graph.m_nVexNum; w++)
        {
            nShortPath[v][w] = -1;//初始化最短路径
        }
    }
    //初始化,nVexStart顶点加入到集合中
    isVisited[nVexStart] = true;
    int min;
    for (int i = 1; i < graph.m_nVexNum; i++)
    {
        min = 0xffff;
        bool bAdd = false;//判断是否还有顶点可以加入集合
        for (int w = 0; w < graph.m_nVexNum; w++)
        {
            if (!isVisited[w])
            {
                if (nShortDistance[w] < min)
                {
                    v = w;//顶点离nVexStart最近
                    min = nShortDistance[w];//最短距离为min
                    bAdd = true;
                }
            }
        }
        //如果没有顶点可加入集合,则跳出循环
        if (!bAdd)
        {
            break;
        }
        isVisited[v] = true;//将w顶点加入到集合
        nShortPath[v][i] = v;
        for (int w = 0; w < graph.m_nVexNum; w++)
        {
            if (!isVisited[w] && (min + graph.m_aAdjMatrix[v][w] < nShortDistance[w]) /*&& (min + graph.m_aAdjMatrix[v][w]) < 0xffff*/)
            {
                //更新当前最短路径及距离
                nShortDistance[w] = min + graph.m_aAdjMatrix[v][w];
                for (int i = 0; i < graph.m_nVexNum; i++)
                {
                    //如果通过w到达顶点i的距离比较短,则将w的最短路径复制给i
                    nShortPath[w][i] = nShortPath[v][i];
                }
            }
        }
        for (int p = 0; p < graph.m_nVexNum; p++)
        {
            for (int j = 0; j < graph.m_nVexNum; j++)
            {
                cout<<nShortPath[p][j]<<" ";
            }
            cout << endl;
        }
        cout << endl;
    }
    int nNum=0;
    int finalpath[20];
    int onlypath[20] = { 0 };
    int q = 0;
    for (int i = 0; i < graph.m_nVexNum; i++)
    {
        finalpath[i] = nShortPath[nVexEnd][i];
    }
    for (int i = 0; i < graph.m_nVexNum; i++)
    {
        if (finalpath[i] != -1)
        {
            nNum++;
            onlypath[q++] = finalpath[i];
        }
    }
    for (int i = 0; i < nNum-1; i++)
    {
        aPath[i].vex1 = onlypath[i];
        aPath[i].vex2 = onlypath[i + 1];
//      aPath[i].weight = nShortDistance[onlypath[i+1]];
        aPath[i].weight = graph.m_aAdjMatrix[aPath[i].vex1][aPath[i].vex2];
    //  if (i > 0)
    //  {
    //      aPath[i].weight = nShortDistance[onlypath[i + 1]] - nShortDistance[onlypath[i]];
            
    //  }
    }
    return nNum;
}
/*
int FindMinTree(Edge aPath[])
{
    int before,after;//before为前一个已访问的点,after为下一个将要访问的点
    int lowcost[20];//保存着未被访问即(V-U)中编号为k的顶点到U中所有顶点的最小权值
    int closest[20];//保存着U中到V-U中编号为K的顶点权值最小的编号
    int used[20];//保存某点是否已经被访问
    int min;

    for (int i = 0; i < graph.m_nVexNum; i++)
    {
        lowcost[i] = graph.m_aAdjMatrix[0][i];//到i点的最小距离即为a点到i点的距离
        closest[i] = 0;//到i点最小距离的点是a点
        used[i] = 0;//所有点都未被访问
    }
    used[0] = 1;//a点已被访问
    before = 0;
    after = 0;
    for (int i = 0; i < graph.m_nVexNum - 1; i++)
    {

        min = 0xffff;

        for (int k = 1; k < graph.m_nVexNum; k++)
        {
            if (used[k] == 0 && lowcost[k] < min)
            {
                min = lowcost[k];
                after = k;
            }
        }
        cout << "before = " << before << "\tafter = " << after << endl;
        used[after] = 1;//j点已加入U集合
        aPath[i].vex1 = before;
        aPath[i].vex2 = after;
        aPath[i].weight = graph.m_aAdjMatrix[before][after];
        for (int j = 0; j < graph.m_nVexNum; j++)
        {
            for (int k = 0; k < graph.m_nVexNum; k++)
            {
                if ((used[j]==1)&&(used[k] == 0) && (graph.m_aAdjMatrix[j][k] < lowcost[k]))
                {
                    lowcost[k] = graph.m_aAdjMatrix[j][k];
                    closest[k] = after;
                    before = j;
                }
            }
        }
    }

    for (int i = 0; i < graph.m_nVexNum - 1; i++)
    {
        cout << aPath[i].vex1 << " -> " << aPath[i].vex2 << "\t" << aPath[i].weight << endl;
    }
    int sum = 0;
    for (int i = 0; i < graph.m_nVexNum - 1; i++)
    {
        cout << graph.m_aVexs[aPath[i].vex1].name << " - " << graph.m_aVexs[aPath[i].vex2].name << "\t" << aPath[i].weight << endl;
        sum += aPath[i].weight;
    }
    cout << endl << endl << "pop stack!" << endl;

    return 0;
}
*/

int FindMinTree(Edge aPath[])
{
    int before, after;//before为前一个已访问的点,after为下一个将要访问的点
    int used[20];//保存某点是否已经被访问
    int min;

    for (int i = 0; i < graph.m_nVexNum; i++)
    {
        used[i] = 0;//所有点都未被访问
    }
    used[0] = 1;//a点已被访问
    before = 0;
    after = 0;
    for (int i = 0; i < graph.m_nVexNum - 1; i++)
    {
        min = 0xffff;
        for (int j = 0; j < graph.m_nVexNum; j++)
        {
            for (int k = 0; k < graph.m_nVexNum; k++)
            {
                if ((used[j] == 1) && (used[k] == 0) && (graph.m_aAdjMatrix[j][k] < min))
                {
                    min = graph.m_aAdjMatrix[j][k];
                    before = j;
                    after = k;
                }
            }
        }
//      cout << i << "." << "before = " << before << "\tafter = " << after << endl;
        used[after] = 1;//j点已加入U集合
        aPath[i].vex1 = before;
        aPath[i].vex2 = after;
        aPath[i].weight = graph.m_aAdjMatrix[before][after];
    }
    return 0;
}
操作实现头文件Tourism.h
#ifndef TOURISM_H
#define TOURISM_H

void CreateGraph(void);
void GetSpotInfo(void);
void TravelPath(void);
void FindShortPath(void);
void DesignPath(void);
#endif
操作实现源文件Tourism.cpp
#include"Tourism.h"
#include"Graph.h"
#include<iostream>
using namespace std;
extern Graph graph;
extern int EdgeNum;
extern Edge aEdge[100];

//extern bool isVisited[20];
#pragma warning (disable : 4996)


void CreateGraph(void)
{
    Init();
    FILE *fp = NULL;
    fp = fopen("Vex.txt", "r");
    if (!fp)
    {
        printf("Failed to open the file!");
        exit(-1);
    }
    int num;
    Vex sVex;
    fscanf(fp, "%d", &num);
    cout << "===== 创建景区景点图 =====" << endl;
    cout << "顶点数目:" << num<<endl;
    cout << "----- 顶点 -----" << endl;
    for (int i = 0; i < num; i++)
    {
        fscanf(fp, "%d", &sVex.num);
        fscanf(fp, "%s", &sVex.name);
        fscanf(fp, "%s", &sVex.desc);
        cout << sVex.num << "-" << sVex.name << endl;
        InsertVex(sVex);
    }
    fclose(fp);
    fp = fopen("Edge.txt", "r");
    if (!fp)
    {
        printf("Failed to open this file!");
        exit(-1);
    }
    Edge sEdge;
    cout << "----- 边 -----" << endl;
    EdgeNum = 0;
    while (!feof(fp))
    {
//      printf("!!!");
        fscanf(fp, "%d", &sEdge.vex1);
        fscanf(fp, "%d", &sEdge.vex2);
        fscanf(fp, "%d", &sEdge.weight);
        printf("<v%d,v%d> %d\n", sEdge.vex1, sEdge.vex2, sEdge.weight);
        InsertEdge(sEdge);
        aEdge[EdgeNum++] = sEdge;
    }
    fclose(fp);
    cout << endl << endl;
}


void GetSpotInfo(void)
{
    cout << "===== 查询景点信息 =====" << endl;
    for (int i = 0; i < graph.m_nVexNum; i++)
    {
        cout << graph.m_aVexs[i].num << "-" << graph.m_aVexs[i].name << endl;
    }
    int nVex;
    cout << "输入想要查询的景点编号: ";
    cin >> nVex;
    Vex sVex=GetVex(nVex);
    printf("%s\n%s\n", sVex.name,sVex.desc);
    cout << "----- 周边景区 -----" << endl;
    int k = FindEdge(nVex, aEdge);
    for (int i = 0; i < k; i++)
    {
        cout << graph.m_aVexs[aEdge[i].vex1].name << "->" << graph.m_aVexs[aEdge[i].vex2].name << " " << aEdge[i].weight <<"m"<< endl;
    }
    cout << endl << endl;
}

void TravelPath(void)
{
    PathList pList;
    pList = (Path*)malloc(sizeof(Path));
    PathList PHead;
    PHead = pList;
//  pList->next = (Path*)malloc(sizeof(Path));
    cout << "===== 旅游景点导航 =====" << endl;
    for (int i = 0; i < graph.m_nVexNum; i++)
    {
        cout << graph.m_aVexs[i].num << "-" << graph.m_aVexs[i].name << endl;
    }
    cout << "请输入起始点编号:";
    int nVex;
    cin >> nVex;
    DFSTraverse(nVex, pList);
    cout << "导航路线为: " << endl;
//  cout << "路线1 : ";
//  cout<<graph.m_aVexs[nVex].name;
    pList = PHead;
    int i = 1;
    while (pList->next)
    {
        Vex sVex = GetVex(pList->vexs[0]);
        cout << "路线" << i++ << ":" << sVex.name;
        for (int j = 1; j<graph.m_nVexNum; j++)
        {
            printf(" -> %s", graph.m_aVexs[pList->vexs[j]].name);
//          sVex = GetVex(pList->vexs[j]);
//          cout << " -> " << sVex.name;
        }
        cout << endl;
        Path *temp = pList;
        pList = pList->next;
        free(temp);
    }
    free(pList);
    pList = NULL;
    PHead = NULL;
    cout << endl<<endl<<endl;
//  free(pList);
//  free(pList->next);
}

void FindShortPath(void)
{
    cout << "===== 搜索最短路径 =====" << endl;
    for (int i = 0; i < graph.m_nVexNum; i++)
    {
        cout << graph.m_aVexs[i].num << "-" << graph.m_aVexs[i].name << endl;
    }
    int nVexStart;
    int nVexEnd;
    cout << "请输入起点的编号: ";
    cin >> nVexStart;
    cout << "请输入终点的编号: ";
    cin >> nVexEnd;
    Edge aPath[20];
    int nNum=FindShortPath(nVexStart, nVexEnd, aPath);
    Vex sVex = GetVex(aPath[0].vex1);
    int nLength = 0;
    cout << "最短路线为: ";
    cout << graph.m_aVexs[nVexStart].name;
    for (int i = 0; i < nNum-1; i++)
    {
        sVex = GetVex(aPath[i].vex2);
        cout << "->" << sVex.name;
        nLength += aPath[i].weight;
    }
    cout << endl;
    cout << "最短距离为: " << nLength << endl;
    cout << endl << endl;
}

void DesignPath(void)
{
    cout << "===== 铺设电路规划 =====" << endl;
    cout << "在以下两个景点之间铺设电路:" << endl;
    Edge aPath[20];
    FindMinTree(aPath);
    int sum=0;
    for (int i = 0; i < graph.m_nVexNum - 1; i++)
    {
        cout << graph.m_aVexs[aPath[i].vex1].name << " - " << graph.m_aVexs[aPath[i].vex2].name << "\t" << aPath[i].weight << endl;
        sum += aPath[i].weight;
    }
    cout << "铺设电路的总长度为:" << sum;
    cout << endl << endl << endl;
}
主函数源文件Main.cpp
#include<iostream>
#include"Tourism.h"
using namespace std;
#pragma warning( disable : 4996)

int main()
{
    while (true)
    {
        //输出界面
        cout << "====景区信息管理系统====" << endl;
        cout << "1.创建景区景点图" << endl;
        cout << "2.查询景点信息" << endl;
        cout << "3.旅游景点导航" << endl;
        cout << "4.搜索最短路径" << endl;
        cout << "5.铺设电路规划" << endl;
        cout << "0.退出" << endl;
        int choice;
        cout << "请输入操作编号<0~5>: ";
        cin >> choice;
        switch (choice)
        {
        case 1:
        {
            CreateGraph();
            break;
        }
        case 2:
        {
            GetSpotInfo();
            break;
        }
        case 3:
        {
            TravelPath();
            break;
        }
        case 4:
        {
            FindShortPath();
            break;
        }
        case 5:
        {
            DesignPath();
            break;
        }
        case 0:
        {
            cout << "退出系统!" << endl;
            exit(0);
        }
        default:
        {
            cout << "请输入操作编号<0~5>: ";
            break;
        }
        }

    }
    return 0;
}

转载于:https://www.cnblogs.com/sgawscd/p/10888699.html

  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、项目简介本课程演示的是一套基于SSM实现的旅游管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。课程包含:1. 项目源码、项目文档、数据库脚本、软件工具等所有资料2. 带你从零开始部署运行本套系统3. 该项目附带的源码资料可作为毕设使用4. 提供技术答疑二、技术实现后台框架:Spring、SpringMVC、MyBatisUI界面:JSP、jQuery 、BootStrap数据库:MySQL 三、系统功能本系统分为前台旅游界面和后台管理,包含三种角色:注册用户、旅游公司和管理系统的功能模块如下: 1.登陆注册模块 管理员的登录模块:管理员登录系统对本系统其他管理模块进行管理。 用户的登录模块:用户登录本系统,对个人的信息等进行查询,操作可使用的功能。 用户注册模块:游客用户可以进行用户注册,系统会反馈是否注册成功。 添加管理员模块:向本系统中添加更多的管理人员,管理员包括普通管理员和超级管理员。 2.景点信息管理模块: 景点信息列表:将数据库的景点信息表以列表的形式呈现给管理员。 添加景点信息:实现管理员添加景点信息。 修改景点信息:实现管理员修改景点信息。 3.公告文章管理模块: 公告文章列表:将数据库的公告文章表以列表的形式呈现给管理员。 添加公告文章:实现管理员添加公告文章。 修改公告文章:实现管理员修改公告文章。 4.旅游线路管理模块: 旅游线路列表:显示系统的所有旅游线路,可以通过关键字查询。 旅游线路删除:对输入错误或过期的旅游线路删除。 5.变幻管理模块: 变幻列表:显示系统的所有变幻,可以通过关键字查询。 变幻删除:对输入错误或过期的变幻删除。 6.用户模块: 资料管理:用户登录本系统。可以对自己的个人主页进行查看。 系统信息:用户可以查看自己的系统提示信息。 修改资料:用户可以修改自己的账号密码。 信息搜索:用户可以通过关键字搜索站内信息。 密码修改:用户可以修改个人登录密码。 7.系统管理模块 8.退出模块该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。四、项目截1)前台首页2)旅游景点详情3)旅游线路报名4)系统后台登陆5)后台管理界面  更多Java毕设项目请关注【毕设系列课程】https://edu.csdn.net/lecturer/2104   

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值