文章目录

  • 整体架构
  • 类对应的实际问题
    • 实际问题的描述
    • 实际问题在类中的体现
    • graph.h
    • edge.h
    • node.h
    • vertexIterator.h
    • work.h
    • arrayWDigraph.h
    • 主函数文件
  • 使用的算法(数据结构)
  • 交互

数据结构三级项目,有向有权图的应用。

整体架构

项目设计7个类(图一),另外还有一个基础的graph类,这些类中最主要的就是arrayWDgraph这个类了,其他的类都是为它服务的,关于图的功能和操作也都是在arrayWDgraph这个类里。arrayWDgraph继承了抽象类graph,并且实现了graph中的方法,同时做出了一定的扩展,编写了其他的方法。

类对应的实际问题

实际问题的描述

项目所对应的实际问题是军事信息整合与处理,具体到项目里就是对军事中地点占领,路线,队伍的安排。计划解决两个主要的问题,就是队伍的顺序安排以及地点间最短路径的计算。队伍顺序的安排就是对队伍上前线的顺序的安排,对于军队来说上战场时的队伍是有一定的顺序安排的,前面的队伍为后面的队伍做好铺垫,后面的队伍就可以迅速地投入战场,取得宝贵的时机。另一个就是对地点间的最短路径的计算,战场上需要在不同的地点作战,所以地点间的转移的路线一定要是最短的才可以,这样就可以迅速地抵达目的地。

实际问题在类中的体现

node类代表的是图中的点,edge类代表的是图中的边,vertexIterator类代表的是迭代器,work代表的是队伍,nodefrom是点的另一种表示,works代表的是队伍系统,graph是基类,而arrayWDgraph是继承基类的代表有向有权图的类。
(1)类的实现中,node类所带有的信息仅仅是点的编号和边的权值,这样一个点会存在边所对应的邻接数组中,用来表示边。node类的方法也只有获取编号和获取权值。
(2)nodefrom类带有的信息包括点的编号,名字,入度,出度,以及占领情况。nodefrom类中除了构造函数没有别的方法。仅作为一个点的抽象。
(3)edge类表示的是边,带有的信息有边的起点和终点还有边的权值,含有的方法是返回起点、返回终点、返回权值,以及输出边的信息。
(4)vertexIterator类在定义的时候作为抽象类被定义,之后在后面被继承实现里面的方法,方法就是将游标移到下一位。
(5)work类仅作为队伍的抽象保存队伍的编号,名字,入度,出度。work类中只有构造函数一个方法。
(6)works类表示的是队伍安排系统,主要的功能就是对队伍的顺序的安排,用到的算法是拓扑排序,里面的队伍用到的数据结构也是邻接数组,来表示队伍之间的先后顺序。该类中也有其他的基础方法,包括加点,删点,加边,删边,以及嵌在它们中的一些小方法。
(7)arrayWDgraph类是最重要的类,其他的类都被它调用。作为有向有权图的类,它带有的信息包括有顶点数、边数、边对应的邻接数组、点对应的栈。它里面的方法大致分为四种,第一种基于图的能够被别的方法调用的基础方法,用来获取点或边的一些信息。包括有获取编号为x的点的索引,获取点的个数、获取边的个数、判断是否存在点x、判断是否存在边(a,b)、判断点x是否合法、判断边(a,b)是否合法、判断占领值是否合法、获取入度、获取出度、获取度、是否为有向图、是否为有权图、获取文件中第一部分字符串、获取文件中第二部分字符串、获取文件中第三部分字符串、获取点的占领情况。第二种是对图修改的方法,包括有增加点、删除点、增加边、删除边、更新权值、更新占领值、100个点初始化、5个点初始化、清空图。第三种是算法相关的方法有拓扑排序、佛洛依德算法、深度优先算法。第四种是方便用户互动的方法,为其他算法服务,有打印路线、删除点和边、增加点和边等方面的引导的方法。

graph.h

#ifndef graph_
#define graph_
#include"edge.h"
#include"vertexIterator.h"
template<class T>
class graph
{public:virtual ~graph() {}virtual int numberOfVertices() const = 0;//点的个数virtual int numberOfEdges() const = 0;//边的个数virtual bool existsEdge(int, int) const = 0;//判断是否存在从前面点到后面点的边virtual void insertEdge(edge<T>*) = 0;//插入边virtual bool eraseEdge(int, int) = 0;//删除边virtual int degree(int) const = 0;//度virtual int indegree(int) const = 0;//入度virtual int outdegree(int) const = 0;//出度virtual bool directed() const = 0;//方向virtual bool weighted() const = 0;//权重virtual vertexIterator<T>* iterator(int) = 0;//迭代器
};
#endif

edge.h

#pragma once
#ifndef edge_
#define edge_
#include<iostream>
using namespace std;
template<class T>
class edge {public:edge(int x=-1,int y=-1,T we=0) {v1 = x;v2 = y;w = we;}~edge() {}int getS1() {return v1;//返回点1}int getS2() {return v2;//返回点2}T getW() {return w;//返回权值}void output() {cout << "(" << v1 << "," << v2 << "," << w << ")";}
private:int v1;//点1int v2;//点2T w;//权值
};
#endif

node.h

#pragma once
#ifndef  node_
#define node_#include<iostream>
using namespace std;
template<class T>
class node {public:int number;//该点的编号T weight;//权值node(int num,int we=0) {number = num;weight = we;}int getn() {return number;}int getw() {return weight;}bool operator==(int y) {if (y == this->number)return true;else return false;}
};class nodeform {public:int ver;int occupy;//用来判断该点是否已经占领int indegree;//该点的入度int outdegree;//该点的出度string name;//该点所代表的地区的名字nodeform(int oc = 0,int ve = 0, string na = "",int in = 0, int out = 0 ){occupy = oc;name = na;ver = ve;indegree = in;outdegree = out;}};#endif

vertexIterator.h

#pragma once#ifndef vertexIterator_
#define vertexIterator_using namespace std;template<class T>
class vertexIterator
{public:virtual ~vertexIterator() {}virtual int next() = 0;virtual int next(T&) = 0;
};
#endif

work.h

#pragma once
#ifndef  work_
#define work_
#include<iostream>
#include<string>
#include<vector>
#include"node.h"
#include"edge.h"
#include<stack>
#include< fstream>
#include <sstream>
using namespace std;class work {public:int ver;//队伍编号int indegree;//该队伍的入度int outdegree;//该队伍的出度string name;//队伍名称work(int ve = 0, string na = "", int in = 0, int out = 0){name = na;ver = ve;indegree = in;outdegree = out;}
};
template<class T>
class works {public:struct VE {int ve;vector<node <T>> g;};vector<VE> E;//队伍先后联系图vector<work> W;//队伍图int num, edges;//分别是队伍数和队伍先后联系数works(int v = 0)//构造函数{while (1){if (v < 0){cout << "输入不标准!请重新输入:" << endl;cin >> v;}else{break;}}num = v;edges = 0;W = vector<work>(num + 1);E = vector<VE>{ (unsigned int)(num + 1),VE() };}~works() {}//获取编号为x的队伍的索引int reindex(int x) {for (int i = 1; i <= num; i++){if (W[i].ver == x){return i;}}}//判断联系v1->v2是否合法bool legaledge(int v1, int v2){if (v1 < 1 || v2 < 1){return false;}else{return true;}};//判断队伍v是否合法bool legalvertex(int v) {if (v >= 1){return true;}else{cout << "点不合法!" << endl;return false;}}//判断是否存在联系a->bbool existsEdge(int a, int b) const {int c = E[a].g.size();for (int i = 0; i < c; i++){if (E[a].g[i].number == b){return true;}}return false;};//判断是否已经存在队伍vbool existvertex(int v){for (int i = 0; i < W.size(); i++){if (v == W[i].ver){return true;}}return false;}//增加队伍void addvertex(int v, string na) {work node(v, na);W.push_back(node);VE nod;nod.ve = v;nod.g.clear();E.push_back(nod);num++;}//删除队伍void deletevertex(int v) {int x = reindex(v);int f = E[x].g.size();E.erase(E.begin() + x, E.begin() + x + 1);edges -= f;W.erase(W.begin() + x, W.begin() + x + 1);for (int i = 1; i < E.size(); i++){for (int j = 0; j < E[i].g.size(); j++){if (E[i].g[j].number == v){E[i].g.erase(E[i].g.begin() + j, E[i].g.begin() + j + 1);W[i].outdegree--;edges--;}}}num--;}//增加联系void insertEdge(edge<T>* Edge) {int v1 = Edge->getS1();int v2 = Edge->getS2();if (!legaledge(v1, v2)){return;}int v = reindex(v1);if (existsEdge(reindex(v1), v2)){auto p = E[v].g.begin();for (int i = 0; i < E[v].g.size(); i++){if (E[v].g[i].number == v2){p = find(E[v].g.begin(), E[v].g.end(), v2);}}}else{W[reindex(v2)].indegree++;W[v].outdegree++;node<T> no(v2);E[v].g.push_back(no);edges++;}};//删除联系bool eraseEdge(int v1, int v2) {int v = reindex(v1);if (!legaledge(v1, v2)){return false;}if (!existsEdge(reindex(v1), v2)){return false;}for (int i = 0; i < E[v].g.size(); i++){if (E[v].g[i].number == v2){E[v].g.erase(remove(E[v].g.begin(), E[v].g.end(), v2), E[v].g.end());W[v].outdegree--;W[v].indegree--;edges--;break;}}return true;};//返回第一部分的字符串string first(string s) {string f;for (int i = 0; i < s.size(); i++){if (s[i] == ' '){f = s.substr(0, i + 1);break;}}return f;}//返回第二部分的字符串string second(string s) {string f;int x;for (int i = 0; i < s.size(); i++){if (s[i] == ' '){f = s.substr(i + 1, s.size() - i - 1);}}return f;}//返回第一个空格位置的索引int reoneblank(string s) {int x;for (int i = 0; i < s.size(); i++){if (s[i] == ' '){x = i;break;}}return x;}//在文件中写入点xvoid advf(int x, string y) {ofstream outfile;outfile.open("workv.txt", ios::app);outfile << x << " " << y << endl;outfile.close();}//添加队伍void adv(){system("cls");cout << "当前功能为添加队伍" << endl;int n;cout << "请输入添加的队伍的个数:";cin >> n;int x;string y;for (int i = 0; i < n; i++){cout << "请输入队伍的编号:";while (1){cin >> x;if (!legalvertex(x)){cout << "输入不规范!请重新输入:";continue;}else if (existvertex(x)){cout << " 该队伍已经存在!" << endl;cout << "请重新输入:";continue;}break;}cout << "请输入队伍的名字:";cin >> y;addvertex(x, y);advf(x, y);cout << "队伍" << x << "增加成功!" << endl;break;}int a;cout << "返回主页请按0 继续添加请按1" << endl;cin >> a;if (a){adv();}else{return;}}//添加队伍重载函数void adv(int x){string y;cout << "请输入队伍的名字:";cin >> y;while (1){if (legalvertex(x)){addvertex(x, y);advf(x, y);cout << "队伍" << x << "增加成功!" << endl;break;}else{cout << "输入不规范,请重新输入:";cin >> x;continue;}}}//删除队伍的文件操作void devf(int x) {vector<string>vf;string s;fstream outfile;outfile.open("workv.txt");while (!outfile.eof()){getline(outfile, s);if (atoi(first(s).c_str()) != x && s != ""){vf.push_back(s);}}outfile.close();ofstream out("workv.txt");out.close();outfile.open("workv.txt", ios::app);for (int i = 0; i < vf.size(); i++){outfile << vf[i] << endl;}outfile.close();vf.clear();outfile.open("worke.txt");while (!outfile.eof()){getline(outfile, s);if (s != ""){if (atoi(first(s).c_str()) != x && atoi(second(s).c_str()) != x){vf.push_back(s);}}}outfile.close();ofstream out1("worke.txt");out1.close();outfile.open("worke.txt", ios::app);for (int i = 0; i < vf.size(); i++){outfile << vf[i] << endl;}outfile.close();}//删除队伍void dev(){system("cls");cout << "当前功能为删除地点" << endl;int n;cout << "请输入删除地点的个数:";cin >> n;int x;for (int i = 0; i < n; i++){cout << "请输入删除地点的编号:";while (1){cin >> x;if (existvertex(x)){deletevertex(x);devf(x);cout << "点" << x << "删除成功!" << endl;break;}else{cout << "点" << x << "不存在!请重新输入:" << endl;continue;}}}int a;cout << "返回主页请按0 继续删除请按1" << endl;cin >> a;if (a){dev();}else{return;}}//在文件中写入边x->yvoid adef(int x, int y) {ofstream outfile;outfile.open("worke.txt", ios::app);outfile << x << " " << y << endl;outfile.close();}//添加联系void ade(){system("cls");cout << "当前功能为添加联系" << endl;int n;cout << "请输入添加联系的个数:";cin >> n;int x, y;for (int i = 0; i < n; i++){while (1) {cout << "请输入起始队伍:";while (1) {cin >> x;if (legalvertex(x)){break;}else {cout << "队伍不规范!请重新输入:" << endl;}}if (!existvertex(x)){int p;cout << "不存在队伍" << x << ",是否要添加队伍" << x << "?" << endl;cout << "是请按1       否请按2" << endl;cin >> p;if (p == 1){this->adv(x);}else{if (p == 2){break;}}}cout << endl;cout << "请输入终点队伍:";while (1) {cin >> y;if (legalvertex(y)){break;}else {cout << "队伍不规范!请重新输入:" << endl;}}if (!existvertex(y)){int p;cout << "不存在队伍" << y << ",是否要添加队伍" << y << "?" << endl;cout << "是请按1       否请按2" << endl;cin >> p;if (p == 1){this->adv(y);}else{if (p == 2){break;}}}if (existsEdge(reindex(x), y)) {cout << "已经存在该联系! " << endl;continue;}else{edge<T>* ed = new edge<T>(x, y);insertEdge(ed); adef(x, y);cout << "联系(" << x << "," << y << ")添加成功!" << endl;break;}}}int a;cout << "返回主页请按0 继续添加请按1" << endl;cin >> a;if (a){ade();}else{return;}}//删除边的文件操作void deef(int x, int y) {vector<string>vf;string s;fstream outfile;outfile.open("worke.txt");while (!outfile.eof()){getline(outfile, s);if (s != ""){if (atoi(first(s).c_str()) != x || atoi(second(s).c_str()) != y){vf.push_back(s);}}}outfile.close();ofstream out("worke.txt");out.close();outfile.open("worke.txt", ios::app);for (int i = 0; i < vf.size(); i++){outfile << vf[i] << endl;}outfile.close();}//删除联系void dee(){system("cls");cout << "当前功能为删除联系" << endl;int n;cout << "请输入删除联系的个数:";cin >> n;int x, y;for (int i = 0; i < n; i++){cout << "请输入起始队伍:";while (1) {cin >> x;if (!existvertex(x)){cout << "不存在队伍" << x << endl;cout << "请重新输入:";}else{break;}}cout << "请输入终点队伍:";while (1) {cin >> y;if (!existvertex(y)){cout << "不存在队伍" << y << endl;cout << "请重新输入:";}else{break;}}if (existsEdge(reindex(x), y)){eraseEdge(x, y);deef(x, y);}cout << "边(" << x << "," << y << ")删除成功!" << endl;}int a;cout << "返回主页请按0 继续删除请按1" << endl;cin >> a;if (a){dee();}else{return;}}//拓扑排序int* Topologicalsorting() {int* in = new int[num + 1];int* result = new int[num + 1];int* visited = new int[num + 1];int j = 0;int k = 0;fill(visited, visited + num + 1, 0);stack<int>zero;for (int i = 1; i <= num; i++){in[i] = W[i].indegree;if (W[i].indegree == 0){zero.push(i);visited[i] = 1;}}while (!zero.empty()){j = zero.top();zero.pop();result[k++] = W[j].ver;for (int i = 0; i < E[j].g.size(); i++){in[reindex(E[j].g[i].number)]--;}for (int i = 1; i <= num; i++){if (visited[i] == 0 && in[i] == 0) {zero.push(i);visited[i] = 1;}}}for (int i = 1; i <= num; i++){if (visited[i] == 0){cout << "无法得出拓扑排序存在孤立点" << endl;return result;}}cout << "拓扑排序为:";for (int i = 0; i < num - 1; i++) {cout << W[reindex(result[i])].name << "->";}cout << W[reindex(result[num - 1])].name << endl;}//拓扑排序方法void tuopu() {system("cls");cout << "当前功能为拓扑排序,为任务进行排序" << endl;cout << "排序结果为:" << endl;if (edges == 0){for (int i = 1; i < W.size(); i++){cout << W[i].ver << " ";}cout << endl;cout << "返回主页面请按任意键" << endl;system("pause");return;}int* arr = Topologicalsorting();cout << endl;cout << "返回主页面请按任意键" << endl;system("pause");}//文件流初始化void Automaticinitialization() {system("cls");cout << "当前为自动初始化" << endl;cout << "初始化中......." << endl;fstream outfile;outfile.open("workv.txt");string s;int x, y;string na;while (!outfile.eof()){getline(outfile, s);if (s != ""){x = atoi(first(s).c_str());na = second(s);addvertex(x, na);}}outfile.close();fstream out;out.open("worke.txt");while (!out.eof()){getline(out, s);if (s != ""){x = atoi(first(s).c_str());y = atoi(second(s).c_str());edge<T>* ed = new edge<T>(x, y);insertEdge(ed);}}out.close();system("cls");cout << "初始化完成" << endl;system("pause");}//初始化void initialization() {int a;bool flag = false;while (1){if (flag) {break;}system("cls");cout << "********************************" << endl;cout << "**********队伍安排模块**********" << endl;cout << "功能如下:" << endl;cout << "1.增加队伍" << endl;cout << "2.增加队伍联系" << endl;cout << "3.删除队伍" << endl;cout << "4.删除队伍联系" << endl;cout << "5.队伍顺序安排" << endl;cout << "6.自动初始化" << endl;cout << "7.退出" << endl;cout << "选择您需要的功能:" << endl;cin >> a;switch (a){case 1:adv(); break;case 2:ade(); break;case 3:dev(); break;case 4:dee(); break;case 5:tuopu(); break;case 6:Automaticinitialization(); break;case 7:flag = true; break;}}}
};
#endif

arrayWDigraph.h

#pragma once
#ifndef arrayWDigraph_
#define  arrayWDigraph_
#include"graph.h"
#include"edge.h"
#include"node.h"
#include "vertexIterator.h"
#include"work.h"
#include<stack>
#include<string>
#include<vector>
#include<fstream>
#include <sstream>
#include<iostream>
template<class T>
class arrayWDgraph :public graph<T> {protected:struct VE {int ve;vector<node <T>> g;};const T mx = 10000;int vertex;//顶点数int edges;//边数vector<VE> G;//存储图中的边vector<nodeform>V;//存储图中的点int* visited;//是否访问过int length;//路径长度int** pa;//佛洛依德的路径T** dis;//佛洛依德的距离int* dpath;                                                      //储存路径//dijkstra专用bool* canreach;                                            //某点是否可达T* ddis;                                                           //到某点的最少费用stack<int>theShortest;
public://构造函数arrayWDgraph(int v = 0) {while (1){if (v < 0){cout << "输入不标准!请重新输入:" << endl;cin >> v;}else{break;}}vertex = v;edges = 0;visited = new int[vertex + 1];V = vector<nodeform>(vertex + 1);pa = NULL;dis = NULL;dpath = NULL;ddis = NULL;canreach = NULL;G = vector<VE>{ (unsigned int)(vertex + 1),VE() };};~arrayWDgraph() {};//string转化为TT stringToNum(const string& str){istringstream iss(str);T num;iss >> num;return num;}//获取编号为x的点的索引int reindex(int x) {for (int i = 1; i <= vertex; i++){if (V[i].ver == x){return i;}}}//获取点的个数int numberOfVertices() const {return vertex;};//获取边的个数int numberOfEdges() const {return edges;};//判断是否存在边a->bbool existsEdge(int a, int b) const {int c = G[a].g.size();for (int i = 0; i < c; i++){if (G[a].g[i].number == b){return true;}}return false;};//判断是否已经存在点vbool existvertex(int v){for (int i = 0; i < V.size(); i++){if (v == V[i].ver){return true;}}return false;}//判断边v1->v2是否合法bool legaledge(int v1, int v2){if (v1 < 1 || v2 < 1){return false;}else{return true;}};//判断点v是否合法bool legalvertex(int v) {if (v >= 1){return true;}else{cout << "点不合法!" << endl;return false;}}//用来判断输入的占领值是否合法bool legaloccupy(int x) {if (x == 1 || x == 0){return true;}return false;}//判断权值是否合法bool legalweight(T w) {if (w < 0){return false;}else{return true;}}//增加边void insertEdge(edge<T>* Edge) {int v1 = Edge->getS1();int v2 = Edge->getS2();T w = Edge->getW();if (!legaledge(v1, v2)){return;}int v = reindex(v1);if (existsEdge(reindex(v1), v2)){auto p = G[v].g.begin();for (int i = 0; i < G[v].g.size(); i++){if (G[v].g[i].number == v2){p = find(G[v].g.begin(), G[v].g.end(), v2);}}p->weight = w;}else{V[reindex(v2)].indegree++;V[v].outdegree++;node<T> no(v2, w);G[v].g.push_back(no);edges++;}};//删除边bool eraseEdge(int v1, int v2) {int v = reindex(v1);if (!legaledge(v1, v2)){return false;}if (!existsEdge(reindex(v1), v2)){return false;}for (int i = 0; i < G[v].g.size(); i++){if (G[v].g[i].number == v2){G[v].g.erase(remove(G[v].g.begin(), G[v].g.end(), v2), G[v].g.end());V[v].outdegree--;V[v].indegree--;edges--;break;}}return true;};//获取入度int indegree(int v) const {return V[v].indegree;};//获取入度子方法int idg(int x) {return indegree(reindex(x));}//获取出度int outdegree(int v) const {return V[v].outdegree;};//获取出度子方法int odg(int x) {return outdegree(reindex(x));}//获取度int degree(int v) const {return indegree(v) + outdegree(v);};//是否为有向图bool directed()  const { return true; };//是否为有权图bool weighted()  const { return true; };//被DFS调用void rDFS(int start, int label) {visited[start] = label;auto pointer = iterator(start);int now;while ((now = pointer->next()) != 0) {if (visited[now] == 0)rDFS(now, label);}delete pointer;}//被dfs调用void sdfs(int start, int label) {visited[start] = label;auto pointer = G[start].g.begin();int now;while (pointer != G[start].g.end()) {now = pointer->number;if (visited[now] == 0)sdfs(now, label);pointer++;}}//迭代器的继承class myIterator : public vertexIterator<T> {public:myIterator(VE& thelist) {//传入引用,减小开销newlist = thelist.g;size = newlist.size() - 1;//初始化cur = 0;};int next() {//取出当前,指向后一个if (cur > size)return 0;//终止int nextVertex = newlist[cur].number;//取出权值和下标 cur++;//游标后移return nextVertex;};int next(T& theWeight) {if (cur > size)return 0;   //终止                int nextVertex = newlist[cur].number;//取出权值和下标theWeight = newlist[cur].weight;cur++;//游标后移return nextVertex;};int next(T& theWeight, int& pos) {if (cur > size)return 0; //终止                int nextVertex = newlist[cur].number;//取出权值和下标theWeight = newlist[cur].weight;pos = cur++;//游标后移       return nextVertex;};void reset() { cur = 0; }//重置游标protected:vector<node<T>>newlist;int x;int cur;int size;};//迭代器的方法myIterator* iterator(int x) {if (legalvertex(x)) {return new myIterator(G[reindex(x)]);//为类中传入边表,因为该类无法使用主类中的nodes}};//自带的迭代器dfsvoid dfs(int start, int label) {if (!legalvertex(start))return;visited = new int[vertex + 1];fill(visited, visited + vertex + 1, 0);sdfs(start, label);}//课本的迭代器的DFSvoid DFS(int start, int label) {if (!legalvertex(start))return;visited = new int[vertex + 1];fill(visited, visited + vertex + 1, 0);rDFS(start, label);}//返回第一部分的字符串string first(string s) {string f;for (int i = 0; i < s.size(); i++){if (s[i] == ' '){f = s.substr(0, i + 1);break;}}return f;}//返回第二部分的字符串string second(string s) {string f;bool flag = false;int x;for (int i = 0; i < s.size(); i++){if (s[i] == ' ' && !flag){flag = true;x = i;}else{if (s[i] == ' ' && flag){f = s.substr(x + 1, i - x);break;}}}return f;}//返回第三部分的字符串string third(string s) {string f;bool flag = false;int x;for (int i = 0; i < s.size(); i++){if (s[i] == ' ' && !flag){flag = true;x = i;}else{if (s[i] == ' ' && flag){f = s.substr(i + 1, s.size() - i - 1);break;}}}return f;}//返回第一个空格位置的索引int reoneblank(string s) {int x;for (int i = 0; i < s.size(); i++){if (s[i] == ' '){x = i;break;}}return x;}//返回第二个空格的位置的索引int retwoblank(string s) {int x;bool flag = false;for (int i = 0; i < s.size(); i++){if (s[i] == ' ' && !flag){flag = true;}else{if (s[i] == ' ' && flag){x = i;break;}}}return x;}//在文件中更新权值void updwf(int x, int y, T z) {vector<string>vf;string s;fstream outfile;outfile.open("edges.txt");while (!outfile.eof()){getline(outfile, s);if (atoi(first(s)) == x && atoi(second(s)) == y){s = s.substr(0, retwoblank(s));string c = to_string(z);s += c;vf.push_back(s);}else{if (s != ""){vf.push_back(s);}}}outfile.close();ofstream out("edges.txt");out.close();outfile.open("edges.txt", ios::app);for (int i = 0; i < vf.size(); i++){outfile << vf[i] << endl;}outfile.close();}//更新权值void updateweight(int v1, int v2, T w) {int c = G[reindex(v1)].g.size();for (int i = 0; i < c; i++){if (G[reindex(v1)].g[i].number == v2){G[reindex(v1)].g[i].weight = w;}}cout << "更新成功!" << endl;int a;cout << "返回主页请按0 继续添加请按1" << endl;cin >> a;switch (a) {case 1:ade(); break;case 0:return;}}//增加点void addvertex(int v, string na, int ocu = 0) {nodeform node(ocu, v, na);V.push_back(node);VE nod;nod.ve = v;nod.g.clear();G.push_back(nod);vertex++;}//删除点void deletevertex(int v) {int x = reindex(v);int num = G[x].g.size();G.erase(G.begin() + x, G.begin() + x + 1);edges -= num;V.erase(V.begin() + x, V.begin() + x + 1);vertex--;for (int i = 1; i < G.size(); i++){for (int j = 0; j < G[i].g.size(); j++){if (G[i].g[j].number == v){G[i].g.erase(G[i].g.begin() + j, G[i].g.begin() + j + 1);V[i].outdegree--;}}}}//在文件中写入点xvoid advf(int x, string y, int z) {ofstream outfile;outfile.open("vertex.txt", ios::app);outfile << x << " " << y << " " << z << endl;outfile.close();}//添加地点void adv(){system("cls");cout << "当前功能为添加地点" << endl;int n;cout << "请输入添加的点的个数:";cin >> n;int x, o;string y;for (int i = 0; i < n; i++){cout << "请输入点的编号:";while (1){cin >> x;if (!legalvertex(x)){cout << "请重新输入:";continue;}else if (existvertex(x)){cout << " 该点已经存在!" << endl;cout << "请重新输入:";continue;}break;}cout << "请输入点的名字:";cin >> y;cout << "该点是否已经被占领(0为否,1为是):";cin >> o;while (1){if (legaloccupy(o)){addvertex(x, y, o);advf(x, y, o);cout << "点" << x << "增加成功!" << endl;break;}else{cout << "输入不规范,请重新输入:";cin >> o;}}}int a;cout << "返回主页请按0 继续添加请按1" << endl;cin >> a;switch (a) {case 1:adv(); break;case 0:return;}}//添加地点重载函数void adv(int x){string y;int o;cout << "请输入点的名字:";cin >> y;cout << "该点是否已经被占领(0为否,1为是):";cin >> o;while (1){if (legaloccupy(o)){addvertex(x, y, o);advf(x, y, o);cout << "点" << x << "增加成功!" << endl;break;}else{cout << "输入占领情况不规范,请重新输入:";cin >> o;continue;}}}//删除点的文件操作void devf(int x) {vector<string>vf;string s;fstream outfile;outfile.open("vertex.txt");while (!outfile.eof()){getline(outfile, s);if (atoi(first(s).c_str()) != x && s != ""){vf.push_back(s);}}outfile.close();ofstream out("vertex.txt");out.close();outfile.open("vertex.txt", ios::app);for (int i = 0; i < vf.size(); i++){outfile << vf[i] << endl;}outfile.close();vf.clear();outfile.open("edges.txt");while (!outfile.eof()){getline(outfile, s);if (s != ""){if (atoi(first(s).c_str()) != x && atoi(second(s).c_str()) != x){vf.push_back(s);}}}outfile.close();ofstream out1("edges.txt");out1.close();outfile.open("edges.txt", ios::app);for (int i = 0; i < vf.size(); i++){outfile << vf[i] << endl;}outfile.close();}//删除地点void dev(){system("cls");if (vertex == 0){cout << "一个点也没有!" << endl;system("pause");return;}else{cout << "当前功能为删除地点" << endl;int n;cout << "请输入删除地点的个数:";cin >> n;int x;for (int i = 0; i < n; i++){cout << "请输入删除地点的编号:";cin >> x;deletevertex(x);devf(x);cout << "点" << x << "删除成功!" << endl;}int a;cout << "返回主页请按0 继续删除请按1" << endl;cin >> a;switch (a) {case 1:dev(); break;case 0:return;}}}//在文件中写入边x->yvoid adef(int x, int y, T z) {ofstream outfile;outfile.open("edges.txt", ios::app);outfile << x << " " << y << " " << z << endl;outfile.close();}//添加路void ade(){system("cls");cout << "当前功能为添加路" << endl;int n;cout << "请输入添加路的个数:";cin >> n;int x, y;T w;for (int i = 0; i < n; i++){cout << "请输入起点:";while (1) {cin >> x;if (legalvertex(x)){break;}else {cout << "点不规范!请重新输入:" << endl;}}if (!existvertex(x)){int p;cout << "不存在点" << x << ",是否要添加点" << x << "?" << endl;cout << "是请按1       否请按2" << endl;cin >> p;switch (p) {case 1:this->adv(x); break;case 2:return;}}cout << endl;cout << "请输入终点:";while (1) {cin >> y;if (legalvertex(y)){break;}else {cout << "点不规范!请重新输入:" << endl;}}if (!existvertex(y)){int p;cout << "不存在点" << y << ",是否要添加点" << y << "?" << endl;cout << "是请按1       否请按2" << endl;cin >> p;switch (p) {case 1:this->adv(y); break;case 2:return;}}if (existsEdge(reindex(x), y)) {cout << "已经存在该路径,是否要更新权值? 否请按0,是请按1 " << endl;int p;cin >> p;switch (p){case 0:return;case 1: {cout << "请输入路径的权值:";while (1){cin >> w;if (legalweight(w)){break;}else{cout << "输入的权值不规范!请重新输入:" << endl;}}updateweight(x, y, w);return; }}}cout << "请输入路径的权值:";while (1){cin >> w;if (legalweight(w)){break;}else{cout << "输入的权值不规范!请重新输入:" << endl;}}edge<T>* ed = new edge<T>(x, y, w);insertEdge(ed);adef(x, y, w);cout << "边";ed->output();cout << "添加成功!" << endl;}int a;cout << "返回主页请按0 继续添加请按1" << endl;cin >> a;switch (a) {case 0:return;case 1:ade(); break;}}//删除路的文件操作void deef(int x, int y) {vector<string>vf;string s;fstream outfile;outfile.open("edges.txt");while (!outfile.eof()){getline(outfile, s);if (s != ""){if (atoi(first(s).c_str()) != x || atoi(second(s).c_str()) != y){vf.push_back(s);}}}outfile.close();ofstream out("edges.txt");out.close();outfile.open("edges.txt", ios::app);for (int i = 0; i < vf.size(); i++){outfile << vf[i] << endl;}outfile.close();}//删除路void dee(){system("cls");if (edges == 0){cout << "当前不存在路!" << endl;system("pause");return;}cout << "当前功能为删除路" << endl;int n;cout << "请输入删除路的个数:";cin >> n;int x, y;for (int i = 0; i < n; i++){cout << "请输入起点:";while (1) {cin >> x;if (!existvertex(x)){cout << "不存在点" << x << endl;cout << "请重新输入:";}else{break;}}cout << "请输入终点:";while (1) {cin >> y;if (!existvertex(y)){cout << "不存在点" << y << endl;cout << "请重新输入:";}else{break;}}if (existsEdge(reindex(x), y)){eraseEdge(x, y);deef(x, y);}cout << "边(" << x << "," << y << ")删除成功!" << endl;}return;}//拓扑排序void Topologicalsorting() {int* in = new int[vertex + 1];int* result = new int[vertex + 1];int j = 0;int k = 0;visited= new int[vertex + 1];fill(visited, visited + vertex + 1, 0);stack<int>zero;for (int i = 1; i <= vertex; i++){in[i] = V[i].indegree;if (V[i].indegree == 0){zero.push(i);visited[i] = 1;}}while (!zero.empty()){j = zero.top();zero.pop();result[k++] = V[j].ver;for (int i = 0; i < G[j].g.size(); i++){in[reindex(G[j].g[i].number)]--;}for (int i = 1; i <= vertex; i++){if (visited[i] == 0 && in[i] == 0) {zero.push(i);visited[i] = 1;}}}for (int i = 1; i <= vertex; i++){if (visited[i] == 0){cout << "无法得出拓扑排序!出现点之间的关系无法拓扑!" << endl;return;}}cout << "拓扑排序为:";for (int i = 0; i < vertex - 1; i++) {cout << V[reindex(result[i])].name << "->";}cout << V[reindex(result[vertex - 1])].name << endl;}//拓扑排序方法void tuopu() {system("cls");if (vertex == 0){cout << "一个点也没有!" << endl;system("pause");return;}cout << "当前功能为拓扑排序,为地点进行排序" << endl;cout << "排序结果为:" << endl;if (edges == 0){for (int i = 1; i < V.size(); i++){cout << V[i].ver << " ";}cout << endl;cout << "返回主页面请按任意键" << endl;system("pause");return;}Topologicalsorting();cout << endl;system("pause");}//更该点的占领情况的文件操作void alterocf(int x) {vector<string>vf;string s, n;fstream outfile;outfile.open("vertex.txt");while (!outfile.eof()){getline(outfile, s);if (s[0] - '0' == x && s != ""){n = s.substr(0, 4);if (s[4] - '0' == 0){n += "1";}else{n += "0";}vf.push_back(n);}else{vf.push_back(s);}}outfile.close();ofstream out("vertex.txt");out.close();outfile.open("vertex.txt", ios::app);for (int i = 0; i < vf.size(); i++){outfile << vf[i] << endl;}outfile.close();}//更改点的占领情况的文件操作void alteroc(int x) {if (V[x].occupy){V[x].occupy = 0;}else{V[x].occupy = 1;}}//更改点的占领情况void addoc() {system("cls");if (vertex == 0){cout << "一个点也没有!" << endl;system("pause");return;}cout << "当前功能为更改点的占领情况" << endl;cout << "请输入要更改的点的编号:";int x;cin >> x;while (1){if (!existvertex(x)){cout << "目标点不存在!请重新输入:";cin >> x;continue;}if (V[reindex(x)].occupy) {cout << "点" << x << "当前的占领情况为:已被占领" << endl;}else{cout << "点" << x << "当前的占领情况为:未被占领" << endl;}cout << "是否要更改占领情况?(是请按1 否请按0)" << endl;int p;cin >> p;switch (p){case 1: {alteroc(reindex(x));alterocf(x);cout << "更改成功!" << endl;system("pause");return; }case 0:return;}}system("pause");}//连通集void Connected() {visited = new int[vertex + 1];fill(visited, visited + vertex + 1, 0);int a, b;b = 0;vector<vector<int>>lian;stack<int>sl;vector<int>du;for (int i = 1; i <= vertex; i++){if (visited[i] == 0&&V[i].occupy==1){sl.push(i);du.push_back(i);visited[i] = 1;}while (!sl.empty()){a = sl.top();sl.pop();for (int j = 0; j < G[a].g.size(); j++){int re = reindex(G[a].g[j].number);if (visited[re] == 0 && V[re].occupy == 1){sl.push(re);du.push_back(re);visited[re] = 1;}}}if (!du.empty()) {lian.push_back(du);b++;du.clear();}}if (!lian.empty()){cout << "已经占领了的点的连通集:" << endl;for (int i = 0; i < b; i++) {int x = 0;cout << "第" << i + 1 << "部分:";while (x<lian[i].size()) {cout << V[lian[i][x++]].ver << " ";}cout << endl;}cout << endl;}else{cout << "没有已占领的点!" << endl;}lian.clear();b = 0;for (int i = 1; i <= vertex; i++){if (visited[i] == 0 && V[i].occupy == 0){sl.push(i);du.push_back(i);visited[i] = 1;}while (!sl.empty()){a = sl.top();sl.pop();for (int j = 0; j < G[a].g.size(); j++){int re = reindex(G[a].g[j].number);if (visited[re] == 0 && V[re].occupy == 0){sl.push(re);du.push_back(re);visited[re] = 1;}}}if (!du.empty()) {lian.push_back(du);b++;du.clear();}}if (!lian.empty()){cout << "未占领的点的连通集:" << endl;for (int i = 0; i < b; i++) {int x = 0;cout << "第" << i + 1 << "部分:";while (x < lian[i].size()) {cout << V[lian[i][x++]].ver << " ";}cout << endl;}cout << endl;}else{cout << "没有未占领的点!" << endl;}}//每个点的占领情况void everyoc() {system("cls");if (vertex == 0){cout << "一个点也没有!" << endl;system("pause");return;}for (int i = 1; i < V.size(); i++){cout << "编号:" << V[i].ver << "占领情况:";if (V[i].occupy)cout << "已占领" << endl;else cout << "未占领" << endl;}Connected();system("pause");}//打印最短路径子方法void print_path(int i, int j) {int k = pa[i][j];if (k == -1)//说明没有中转顶点,直接返回.return;print_path(i, k);//寻找i和k之间cout << V[k].ver << "->";print_path(k, j);//寻找k和j之间}//打印最短路径void print_result() {int i, j;for (i = 1; i < vertex + 1; i++) {for (j = 1; j < vertex + 1; j++) {if (dis[i][j] == mx) {//无法到达设置距离为无穷大,则他们之前没有路径cout << V[i].ver << "和" << V[j].ver << "之间没有路径" << endl;}else {cout << V[i].ver << "和" << V[j].ver << "的最短路径为" << dis[i][j] << endl;cout << "路径方案为:" << V[i].ver << "->";print_path(i, j);cout << V[j].ver << endl;}}}}//佛洛依德算法void floyed() {dis = new  T * [vertex + 1];for (int i = 0; i < vertex + 1; i++){dis[i] = new T[vertex + 1];}pa = new int* [vertex + 1];for (int i = 0; i < vertex + 1; i++){pa[i] = new int[vertex + 1];for (int j = 0; j < vertex + 1; j++){pa[i][j] = -1;}}for (int i = 0; i < vertex + 1; i++) {for (int j = 0; j < vertex + 1; j++) {if (i == j)dis[i][j] = 0;else dis[i][j] = mx;}}for (int i = 1; i < G.size(); i++){for (int j = 0; j < G[i].g.size(); j++){dis[i][reindex(G[i].g[j].number)] = G[i].g[j].weight;}}for (int k = 1; k < vertex + 1; k++) {//不断插点for (int i = 1; i < vertex + 1; i++) {for (int j = 1; j < vertex + 1; j++) {//对图中所有点之间的最短距离进行更新。if (dis[i][j] > dis[i][k] + dis[k][j]) {pa[i][j] = k;//记录中转顶点。dis[i][j] = dis[i][k] + dis[k][j];//更新。}}}}}//最短路径方法void foluo() {system("cls");if (vertex == 0){cout << "图中没有点!" << endl;system("pause");return;}cout << "当前功能为每个地点间的最短路径" << endl;cout << "结果为:";floyed();print_result();cout << "***************************" << endl;system("pause");}//迪杰斯特拉算法void rdijkstra(int start){int cnt = 1;for (int i = 1; i <= vertex - 1; i++) {//更新n-1次  T min = mx;int minnode = 0;for (int j = 1; j <= vertex; j++) {//j是下标if (ddis[j] < min && visited[j] == 0) {min = ddis[j];minnode = V[j].ver;//中转点的编号}}if (minnode == 0){continue;}//没有可更新的点//path[minnode] = start;//没有路径的情况visited[reindex(minnode)] = 1;//已找到到达minnode的最短路径auto pointer = iterator(minnode);int next, pos;T weight;while ((next = pointer->next(weight, pos)) != 0) {if (visited[reindex(next)] == 0 && ddis[reindex(next)] > G[reindex(minnode)].g[pos].weight + ddis[reindex(minnode)]) {ddis[reindex(next)] = G[reindex(minnode)].g[pos].weight + ddis[reindex(minnode)];dpath[reindex(next)] = reindex(minnode);}}}}T* short_path_dijkstra(int start, int end){ddis = new T[vertex + 1];fill(ddis, ddis + vertex + 1, mx);ddis[0] = vertex;ddis[start] = 0;dpath = new int[vertex + 1];dpath[start] = start;visited= new int[vertex + 1];fill(visited, visited + vertex + 1, 0);visited[start] = 1;auto pointer = iterator(V[start].ver);int next;T weight;while ((next = pointer->next(weight)) != 0) {ddis[reindex(next)] = weight;dpath[reindex(next)] = start;}rdijkstra(start);canreach = new bool[vertex + 1];for (int i = 1; i <= vertex; i++){canreach[i] = true;if (ddis[i] == mx){canreach[i] = false;}}if (canreach[end] == false){return NULL;}stack<int>nothing;theShortest.swap(nothing);int cnt = 0;while (end != start) {theShortest.push(end);cnt++;end = dpath[end];}ddis[0] = cnt;canreach = NULL;return ddis;}void dijkstra_result(int start, int end){start = reindex(start);//转换为索引end = reindex(end);T* distance = short_path_dijkstra(start, end);if (!distance) {cout << "不存在从" << V[start].ver << "到" << V[end].ver << "的路径" << endl;return;}T mindis = distance[0];cout << "从" << V[start].ver << "到" << V[end].ver << "的最短路径为" << ddis[end] << endl;cout << "其路径为:" << V[start].ver << "->";for (int i = 1; i <= mindis; i++){cout << V[theShortest.top()].ver;if (i != mindis){cout << "->";}theShortest.pop();}cout << endl;}void dijkstra(){system("cls");cout << "当前功能为单点最短路径" << endl;cout << "请输入作为单点的起点编号:" << endl;int qidian = 0;int zhongdian = 0;while (1) {cin >> qidian;if (!existvertex(qidian)){cout << "输入的起点不存在,请重新输入!" << endl;}else{break;}}cout << "请输入作为单点的终点编号:" << endl;while (1) {cin >> zhongdian;if (!existvertex(zhongdian)){cout << "输入的起点不存在,请重新输入!" << endl;}else{break;}}if (qidian == zhongdian){cout << "输入的起点与终点一致!" << endl;system("pause");return;}else {dijkstra_result(qidian, zhongdian);}system("pause");}//队伍模块void ranks() {works<double>K(0);K.initialization();}//清空图void allclear() {system("cls");if (vertex == 0){cout << "图中没有点!" << endl;system("pause");return;}system("cls");cout << "正在清空......." << endl;G.clear();V.clear();vertex = 0;edges = 0;visited = new int[vertex + 1];V = vector<nodeform>(vertex + 1);pa = NULL;dis = NULL;dpath = NULL;ddis = NULL;canreach = NULL;G = vector<VE>{ (unsigned int)(vertex + 1),VE() };system("cls");cout << "清空完成" << endl;system("pause");}//文件流初始化void Automaticinitialization() {system("cls");if (vertex != 0){cout << "图还未清空,请勿初始化!" << endl;cout << "是否要清空图?是请按1,否请按0" << endl;int a;cin >> a;switch (a){case 1:allclear(); break;case 0:return;}}system("cls");cout << "当前为自动初始化" << endl;cout << "初始化中......." << endl;fstream outfile;outfile.open("vertex.txt");string s;int x, y, z;string na;while (!outfile.eof()){getline(outfile, s);if (s != ""){x = atoi(first(s).c_str());na = second(s);z = atoi(third(s).c_str());addvertex(x, na, z);}}outfile.close();fstream out;out.open("edges.txt");string c;while (!out.eof()){getline(out, s);if (s != ""){x = atoi(first(s).c_str());y = atoi(second(s).c_str());c = third(s);T p = stringToNum(c);edge<T>* ed = new edge<T>(x, y, p);insertEdge(ed);}}out.close();system("cls");cout << "初始化完成" << endl;system("pause");}//初始化5个点void Ainitialization() {system("cls");if (vertex != 0){cout << "图还未清空,请勿初始化!" << endl;cout << "是否要清空图?是请按1,否请按0" << endl;int a;cin >> a;switch (a){case 1:allclear(); break;case 0:return;}}system("cls");cout << "当前为自动初始化" << endl;cout << "初始化中......." << endl;fstream outfile;outfile.open("vertex2.txt");string s;int x, y, z;string na;while (!outfile.eof()){getline(outfile, s);if (s != ""){x = atoi(first(s).c_str());na = second(s);z = atoi(third(s).c_str());addvertex(x, na, z);}}outfile.close();fstream out;out.open("edges2.txt");string c;while (!out.eof()){getline(out, s);if (s != ""){x = atoi(first(s).c_str());y = atoi(second(s).c_str());c = third(s);T p = stringToNum(c);edge<T>* ed = new edge<T>(x, y, p);insertEdge(ed);}}out.close();system("cls");cout << "初始化完成" << endl;system("pause");}//性能测试void performCompare() {//定制的system("cls");if (vertex == 0){cout << "请先初始化!" << endl;system("pause");return;}system("cls");cout << "测试中........." << endl;clock_t start1, finish1;int label = 1, count1 = 0;start1 = clock();do{DFS(1, label);count1++;} while (((finish1 = clock()) - start1) < 1000);double x1 = ((double)finish1 - (double)start1) / count1;//自带的label = 1;int n = 0;clock_t start2, finish2;int count2 = 0;start2 = clock();do{dfs(1, label);count2++;} while (((finish2 = clock()) - start2) < 1000);double x2 = ((double)finish2 - (double)start2) / count2;system("cls");cout << "课本DFS运行时间:" << x1 << endl << "定制的的DFS运行时间:" << x2 << endl;system("pause");}//初始化void initialization() {bool flag = false;while (1){int a;if (flag) {break;}system("cls");cout << "********************************" << endl;cout << "**********军事信息系统**********" << endl;cout << "功能如下:" << endl;cout << "1.增加地点" << endl;cout << "2.增加路" << endl;cout << "3.删除地点" << endl;cout << "4.删除路" << endl;cout << "5.更改点的占领情况" << endl;cout << "6.地点拓扑安排" << endl;cout << "7.单点最短路径" << endl;cout << "8.所有地点间最短路径" << endl;cout << "9.每个点的占领情况" << endl;cout << "10.队伍安排模块" << endl;cout << "11.自动初始化(100个点)" << endl;cout << "12.自动初始化(5个点)" << endl;cout << "13.清空全部" << endl;cout << "14.性能测试" << endl;cout << "15.退出" << endl;cout << "选择您需要的功能:" << endl;cin >> a;switch (a){case 1:adv(); break;case 2:ade(); break;case 3:dev(); break;case 4:dee(); break;case 5:addoc(); break;case 6:tuopu(); break;case 7:dijkstra(); break;case 8:foluo(); break;case 9:everyoc(); break;case 10:ranks(); break;case 11:Automaticinitialization(); break;case 12:Ainitialization(); break;case 13:allclear(); break;case 14:performCompare(); break;case 15:flag = true; break;}}}
};
#endif

主函数文件

#include <iostream>
#include "arrayWDigraph.h"
int main()
{arrayWDgraph<double> W(0);W.initialization();return 0;
}

使用的算法(数据结构)

1.拓扑排序
2.佛洛依德算法
3.迪杰斯特拉算法
4.深度优先算法
5.广度优先算法
6.采用邻接数组的方式存储有向有权图

交互

该项目采用文件流的方式,交互所对应的结果会反映到文件中去。

数据结构三级项目c++代码,基于有向有权图的信息管理系统相关推荐

  1. java克鲁斯卡尔算法_Java语言基于无向有权图实现克鲁斯卡尔算法代码示例

    所谓有权图,就是图中的每一条边上都会有相应的一个或一组值.通常情况下,这个值只是一个数字 如:在交通运输网中,边上的权值可能表示的是路程,也可能表示的是运输费用(显然二者都是数字).不过,边上的权值也 ...

  2. Java毕业设计、课程设计、实战项目之[含源码等]基于SSM+Vue的SSM学业预警平台信息管理系统[包运行成功]

    基于SSM+Vue的SSM学业预警平台信息管理系统> 后台框架:Spring.SpringMVC.MyBatis 前端:HTML+CSS+JavaScript+vue 数据库:MySQL 管理员 ...

  3. 基于 Servlet+jsp+mysql 开发 javaWeb 养老院信息管理系统

    你知道的越多,你不知道的越多 点赞再看,养成习惯 如果您有疑问或者见解,或者没有积分想获取项目,欢迎指教: 企鹅:869192208 文章目录 一.开发背景 二. 需求分析 三.开发环境 四.运行效果 ...

  4. java学籍管理系统课设报告,基于SSM+Redis+LayUI的大学生学籍信息管理系统-java学生学籍信息管理系统mysql数据源...

    "基于SSM+Redis+LayUI的大学生学籍信息管理系统-java学生学籍信息管理系统mysql数据源 1.包含源程序,数据库脚本.代码和数据库脚本都有详细注释. 2.课题设计仅供参考学 ...

  5. java毕业设计基于BS架构的疫情包联信息管理系统的设计与实现mybatis+源码+调试部署+系统+数据库+lw

    java毕业设计基于BS架构的疫情包联信息管理系统的设计与实现mybatis+源码+调试部署+系统+数据库+lw java毕业设计基于BS架构的疫情包联信息管理系统的设计与实现mybatis+源码+调 ...

  6. 基于JAVA预装箱式净水站可视化信息管理系统计算机毕业设计源码+系统+数据库+lw文档+部署

    基于JAVA预装箱式净水站可视化信息管理系统计算机毕业设计源码+系统+数据库+lw文档+部署 基于JAVA预装箱式净水站可视化信息管理系统计算机毕业设计源码+系统+数据库+lw文档+部署 本源码技术栈 ...

  7. 基于javaweb+jsp的手机店销售信息管理系统(JavaWeb JSP MySQL Servlet SSM SpringBoot Layui Ajax)

    基于javaweb+jsp的手机店销售信息管理系统(JavaWeb JSP MySQL Servlet SSM SpringBoot Layui Ajax) 运行环境 Java≥8.MySQL≥5.7 ...

  8. 基于SSM+Vue的SSM学业预警平台信息管理系统

    <基于SSM+Vue的SSM学业预警平台信息管理系统> 后台框架:Spring.SpringMVC.MyBatis 前端:HTML+CSS+JavaScript+vue 数据库:MySQL ...

  9. 基于springboot+jsp的服装穿搭信息管理系统

    项目架构:B/S架构 开发语言:Java语音 前端技术:Layui.Html.CSS.JS 后端技术:Java.mybatis.Springmvc 运行环境:win10/win11.jdk1.8 数据 ...

最新文章

  1. JZOJ 5639. 【NOI2018模拟4.8】秘密袭击
  2. shutdown()函数:优雅地断开TCP连接
  3. VTK:Texture之TextureThreshold
  4. conductor任务域
  5. windows系统-程序加载时生成栈和堆的过程
  6. SQL2012 附加数据库提示5120错误解决方法
  7. Pytorch —— BN、LN、IN、GN
  8. 微软力挺 Go,宣布参与 Athens 项目和 GopherSource
  9. Netflix的快速产品集成测试
  10. 通过JAVA获取优酷视频
  11. PS2模拟器 PCSX2 新手向
  12. 收集一些电子书下载的网站
  13. 为知笔记Typora编辑器上传图片失效(20.5.16)
  14. [LeetCode] 969. 煎饼排序
  15. 前端战五渣学前端——模板引擎(Handlebars.js)
  16. 破解中国汽车未来,BAT及车企各巨头汇聚世界智能网联汽车大会
  17. sql中将字符串数字转换成数字
  18. 《运营力——微信公众号 设计 策划 客服 管理 一册通》一一1.1 创博公众号团队简介...
  19. 用手写板向计算机输入汉字是什么技术,手写板是什么
  20. android 默认勾选权限_Android系统Framework定制默认值预置修改

热门文章

  1. 小程序-记一次二进制文档流文件下载功能;
  2. 这款全网热评的无线路由器,到底有什么特别?
  3. Devops 基础介绍
  4. 提问的智慧(中文版)-----转
  5. 初探occ+osg开发的CAD系统之模型装配颜色(2)
  6. 派生词 计算机英语,英语词缀tele- (afar; operating over a distance) 与派生词
  7. 面试中各个类型项目讲解
  8. VR+全景播放器+头控讲解-04
  9. 编译FCL库报错:recompile with -fPIC
  10. android手机刷ios6,管你iOS6还是WP8 市场Android强机盘点