数据结构:一道实验题的想法(SDU实验七 图的操作)

一道实验题的想法(图)

这门课又双叒叕要写实验了…
好在是最后一个实验,做完了岂不就可以…(浮想联翩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 <iostream>
#include <string>
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,有要的就拿走吧。

不管是东南风,还是西北风,都是我的歌,我的歌…

原创文章 20 获赞 144 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_43714332/article/details/103294326