一道实验题的想法(图)
这门课又双叒叕要写实验了…
好在是最后一个实验,做完了岂不就可以…(浮想联翩ing)
言归正传,先来看看题目:
实验七 图的操作
一、 要求完成时间
实验开始后的第八周之前完成
二、 实验目的
掌握无向图的创建、遍历方法。
三、 实验内容
1、创建图类,存储结构使用邻接矩阵。
2、输入图的节点数 n(不超过 10 个)、边数 m,节点分别用 1-n 代表。
3、采用“起始节点,终止节点,权值”输入图的 m 条边,创建图。
4、输出从节点 1 开始的 BFS 遍历,在遍历过程中,如有多个可以选择
的节点,则优先选择编号较小的节点。
5、输出从节点 1 开始的 DFS 遍历,在遍历过程中,如有多个可以选择
的节点,则优先选择编号较小的节点。
6、输出从第 1 节点到第 n 节点最短路径的长度,如果没有路经,输出 0。
四、 测试用例及答案
测试如下所有用例及答案,且确保运行后出现完全一样的输出,
(操作系统提示“请按任意键继续….”等,可以不一样。)
看起来貌似很容易是吧,本大少打了半天,看了看样例,结果他长着样:
这输入的是个啥…
好吧,做完了实验,开始想了想图的一些东西,嗯,有那味儿了。
关于图的知识,应该会在另一篇博文中写道(写不写其实还是看本大少心情2333333333)
单纯来讲讲实验吧
创建图类,那我们就得了解图的组成,题目要求说无向加权图,那么我们的三个要素:顶点,边,权值,那我们先来定义一个边得类:
class edge{
public:
edge(string str);//构造函数
int begin;
int end;
int length;
};
edge::edge(string str) {
int n1,n2,theLength;
int strLength = str.length();
char strChar[strLength];
for(int i=0;i<strLength;i++)
strChar[i] = str.at(i);
n1 = strChar[0]-'0';
n2 = strChar[2]-'0';
int b = strLength-4;
if(b==1){
theLength = strChar[4]-'0';
} else if(b==2){
theLength = (strChar[4]-'0')*10 + (strChar[5]-'0');
} else if(b==3){
theLength = (strChar[4]-'0')*100+(strChar[5]-'0')*10+(strChar[6]-'0');
}
begin = n1;
end = n2;
length = theLength;
}
那个构造函数是为了解析题目的输入,不要在意这种细节23333333
既然边有了,那么该来构造图了:
class WGraph
{
public:
int n;//顶点个数
int e;//边数
int **a;
int noEdge = 0;
WGraph(int numberOfVer);//构造函数
};
初始化一个图只需要知道它的点集,而且我们是使用邻接矩阵来表示图,那么我们要对图进行操作:插入带权值的边,进行宽度优先搜索,深度优先搜索,求最短路径,接下来就好办了,写几个方法并扩充刚刚定义的WGraph类:
class WGraph
{
public:
int n;//顶点个数
int e;//边数
int **a;
int noEdge = 0;
public:
WGraph(int numberOfVer);
void insertEdge(edge *theEdge);
void bfs();//宽度优先搜索
void dfs();//深度优先搜索
void rdfs(int v,int reach[]);//深度优先搜索递归函数
void path();//最短路径
};
WGraph::WGraph(int numberOfVer) {
n=numberOfVer;
a = new int *[n+1];
for(int i=0;i<n+1;i++){
a[i] = new int[n+1];
}
for(int i=1;i<n+1;i++)
for(int j=1;j<n+1;j++)
a[i][j] = noEdge;
}
void WGraph::insertEdge(edge *theEdge) {
int v1 = theEdge->begin;
int v2 = theEdge->end;
int length = theEdge->length;
if(a[v1][v2]==noEdge){
a[v1][v2] = length;
a[v2][v1] = length;
}
}
void WGraph::bfs() {
arrayQueue q;
arrayQueue out;
int v = 1;
int label = 1;
int reach[n+1];
for(int i=0;i<n+1;i++)
reach[i] = 0;
reach[v] = label;
q.push(v);
while (!q.empty()){
int w = q.front();
q.pop();
out.push(w);
for(int u=1;u<=n;u++){
if(a[w][u]!=0&&reach[u]==0){
q.push(u);
reach[u] = label;
}
}
}
int temp = out.size();
for(int i=0;i<temp;i++){
if(i==temp-1){
cout<<out.front()<<endl;
} else{
cout<<out.front()<<",";
}
out.pop();
}
}
void WGraph::dfs() {
int reach[n+1];
for(int i=0;i<=n;i++){
reach[i] = 0;
}
rdfs(1,reach);
int temp = m->size();
for(int i=0;i<temp;i++){
if(i==temp-1){
cout<<m->front()<<endl;
} else{
cout<<m->front()<<",";
}
m->pop();
}
}
void WGraph::rdfs(int v, int *reach) {
reach[v] = 1;
m->push(v);
for(int u = 1;u<=n;u++){
if(a[v][u]!=0&&reach[u]==0){
rdfs(u,reach);
}
}
}
void WGraph::path() {
int max = 1000;
int min,x;
int len[n+1];
len[1] = 0;
int reach[n+1];
for(int i=0;i<=n;i++){
reach[i] = 0;
}
reach[1]=1;
for(int i=2;i<=n;i++) {
len[i] = max;
}
for(int i=1;i<=n;i++){
if(a[1][i]!=0){
len[i] = a[1][i];
}
}
for(int i=1;i<n;i++){
min = max;
for(int j=1;j<=n;j++){
if(reach[j]==0&&len[j]<min){
min = len[j];
x = j;
}
}
reach[x] = 1;
for(int y=1;y<=n;y++){
if(a[x][y]!=0){
if(len[y]>len[x]+a[x][y]){
len[y] = len[x]+a[x][y];
}
}
}
}
if(len[n]==max){
cout<<0<<endl;
} else{
cout<<len[n]<<endl;
}
}
这便是关于图的全部代码,有些地方为了契合题目输出的需要,可能会有一些多余(咬我啊)
接下来放上实验的全部代码:
#include
#include
using namespace std;
//边
class edge{
public:
edge(string str);
public:
int begin;
int end;
int length;
};
edge::edge(string str) {
int n1,n2,theLength;
int strLength = str.length();
char strChar[strLength];
for(int i=0;i<strLength;i++)
strChar[i] = str.at(i);
n1 = strChar[0]-'0';
n2 = strChar[2]-'0';
int b = strLength-4;
if(b==1){
theLength = strChar[4]-'0';
} else if(b==2){
theLength = (strChar[4]-'0')*10 + (strChar[5]-'0');
} else if(b==3){
theLength = (strChar[4]-'0')*100+(strChar[5]-'0')*10+(strChar[6]-'0');
}
begin = n1;
end = n2;
length = theLength;
}
//队列
class arrayQueue
{
public:
arrayQueue(int initialCapacity = 50);
~arrayQueue() {delete [] queue;}
bool empty() const {return theFront == theBack;}
int size() const
{return (theBack - theFront + arrayLength) % arrayLength;}
int& front()
{
return queue[(theFront + 1) % arrayLength];
}
int& back()
{
return queue[theBack];
}
void pop()
{
theFront = (theFront + 1) % arrayLength;
}
void push(const int& theElement);
private:
int theFront;
int theBack;
int arrayLength;
int *queue;
};
arrayQueue::arrayQueue(int initialCapacity)
{
arrayLength = initialCapacity;
queue = new int[arrayLength];
theFront = 0;
theBack = 0;
}
void arrayQueue::push(const int& theElement)
{
if ((theBack + 1) % arrayLength == theFront)
{
int* newQueue = new int[2 * arrayLength];
int start = (theFront + 1) % arrayLength;
if (start < 2)
copy(queue + start, queue + start + arrayLength - 1, newQueue);
else
{
copy(queue + start, queue + arrayLength, newQueue);
copy(queue, queue + theBack + 1, newQueue + arrayLength - start);
}
theFront = 2 * arrayLength - 1;
theBack = arrayLength - 2;
arrayLength *= 2;
queue = newQueue;
}
theBack = (theBack + 1) % arrayLength;
queue[theBack] = theElement;
}
arrayQueue *m = new arrayQueue;
//加权无向图
class WGraph
{
public:
int n;//顶点个数
int e;//边数
int **a;
int noEdge = 0;
public:
WGraph(int numberOfVer);
void insertEdge(edge *theEdge);
void bfs();
void dfs();
void rdfs(int v,int reach[]);
void path();
};
WGraph::WGraph(int numberOfVer) {
n=numberOfVer;
a = new int *[n+1];
for(int i=0;i<n+1;i++){
a[i] = new int[n+1];
}
for(int i=1;i<n+1;i++)
for(int j=1;j<n+1;j++)
a[i][j] = noEdge;
}
void WGraph::insertEdge(edge *theEdge) {
int v1 = theEdge->begin;
int v2 = theEdge->end;
int length = theEdge->length;
if(a[v1][v2]==noEdge){
a[v1][v2] = length;
a[v2][v1] = length;
}
}
void WGraph::bfs() {
arrayQueue q;
arrayQueue out;
int v = 1;
int label = 1;
int reach[n+1];
for(int i=0;i<n+1;i++)
reach[i] = 0;
reach[v] = label;
q.push(v);
while (!q.empty()){
int w = q.front();
q.pop();
out.push(w);
for(int u=1;u<=n;u++){
if(a[w][u]!=0&&reach[u]==0){
q.push(u);
reach[u] = label;
}
}
}
int temp = out.size();
for(int i=0;i<temp;i++){
if(i==temp-1){
cout<<out.front()<<endl;
} else{
cout<<out.front()<<",";
}
out.pop();
}
}
void WGraph::dfs() {
int reach[n+1];
for(int i=0;i<=n;i++){
reach[i] = 0;
}
rdfs(1,reach);
int temp = m->size();
for(int i=0;i<temp;i++){
if(i==temp-1){
cout<<m->front()<<endl;
} else{
cout<<m->front()<<",";
}
m->pop();
}
}
void WGraph::rdfs(int v, int *reach) {
reach[v] = 1;
m->push(v);
for(int u = 1;u<=n;u++){
if(a[v][u]!=0&&reach[u]==0){
rdfs(u,reach);
}
}
}
void WGraph::path() {
int max = 1000;
int min,x;
int len[n+1];
len[1] = 0;
int reach[n+1];
for(int i=0;i<=n;i++){
reach[i] = 0;
}
reach[1]=1;
for(int i=2;i<=n;i++) {
len[i] = max;
}
for(int i=1;i<=n;i++){
if(a[1][i]!=0){
len[i] = a[1][i];
}
}
for(int i=1;i<n;i++){
min = max;
for(int j=1;j<=n;j++){
if(reach[j]==0&&len[j]<min){
min = len[j];
x = j;
}
}
reach[x] = 1;
for(int y=1;y<=n;y++){
if(a[x][y]!=0){
if(len[y]>len[x]+a[x][y]){
len[y] = len[x]+a[x][y];
}
}
}
}
if(len[n]==max){
cout<<0<<endl;
} else{
cout<<len[n]<<endl;
}
}
int main()
{
cout<<"Input"<<endl;
string str1;
cin>>str1;
int str1Length = str1.length();
int n,m;
n = str1.at(0)-'0';
if(str1Length==3){
m = str1.at(2)-'0';
} else if(str1Length==4){
m = (str1.at(2)-'0')*10+(str1.at(3)-'0');
}
WGraph wg(n);
for(int i=0;i<m;i++){
string str2;
cin>>str2;
edge *e = new edge(str2);
wg.insertEdge(e);
}
cout<<"Output"<<endl;
wg.bfs();
wg.dfs();
wg.path();
cout<<"End";
return 0;
}
造福SDUers,有要的就拿走吧。
不管是东南风,还是西北风,都是我的歌,我的歌…