图的操作

图的操作:
1.图的存储结构使用邻接矩阵。
2.创建图操作类,支持BFS遍历、DFS遍历、求单源最短路径、求最小生成树、判断是否存在回路等五个功能,这些功能封装成图操作类的成员函数
3. 采用“起始节点,终止节点,权值”输入图的m条边,创建图。
4. 输出从节点1开始的BFS遍历、DFS遍历节点遍历顺序。
5. 输出从节点1到其余节点的最短路径及最短路径长度,如果没有路径,输出0。
6. 输出图的最小生成树包含的边,边用“起始节点,终止节点,权值”表示。
输入输出说明:
输入:
第1行输入2个整数,图的节点数n(不超过10个)、边数m。
接下来m行,每行3个整数。采用“起始节点,终止节点,权值”输入图的m条边。
输出:
第1行为图的BFS遍历
第2行为图的DFS遍历
接下来n-1行,为图中第1个节点到其他节点的最短路径,如果没有路径,路径长度输出“0”。格式为:最短路径 路径长度。
接下来输出图的最小生成树包含的边,边用“起始节点,终止节点,权值”表示,按权值从小到大输出最小生成树的边。
最后一行输出大写字母 YES 或 NO:YES代表图中有环,NO代表图中无环。
输入:
6 9
1 2 10
1 4 20
1 6 2
2 3 3
2 4 5
3 5 15
4 5 11
4 6 10
5 6 3
输出:
1 2 4 6 3 5
1 2 3 5 4 6
1 2 10
1 2 3 13
1 6 4 12
1 6 5 5
1 6 2
1 6 2
2 3 3
5 6 3
2 4 5
1 2 10
YES

#include <iostream>
#include <algorithm>
#include <memory.h>
#define INFINITY  99999
#define UNVISITED  0
#define VISITED  1
#define Max  10
using namespace std;
template<class E>
 class Queue {
    //队列ADT
    private:
        void operator = (const Queue&) {
    }
    Queue(const Queue&) {
    }
    int maxsize;
    int front;
    int rear;
    E* listArray;
    public:
        Queue(int size = 99) {
        //构造函数
        maxsize = size;
        rear = 0;
        front = 1;
        listArray = new E[size];
    }
    ~Queue() {
        delete[] listArray;
    }
    //析构函数
    void clear() {
        //清空
        rear = 0;
        front = 1;
    }
    int length() {
        //返回队列长度
        return ((rear + maxsize) - front + 1) % maxsize;
    }
    void enqueue(const E& it) {
        //入队
        if (((rear + 2) % maxsize) != front) {
            rear = (rear + 1) % maxsize;
            listArray[rear] = it;
        }
    }
    E dequeue() {
        //出队
        if (length() != 0) {
            E it = listArray[front];
            front = (front + 1) % maxsize;
            return it;
        }
    }
    const E& frontValue() {
        //获取队尾值
        if (this.length() != 0)
                    return listArray[front]; else
                    exit(0);
    }
};
class Graphm {//图类
private:
    int numVertex;//顶点数
    int numEdge;//边数
    int (**matrix);//邻接矩阵
    int *mark;//记录
public:
        Graphm(int n) {//图的构造函数
        numVertex = n;
        numEdge=0;
        matrix =(int **) new int*[n];//初始化图
        for (int i=0;i<n;i++)
                    matrix[i]=new int[n];
        for (int i=0;i<n;i++)
                    for (int j=0;j<n;j++)
                        matrix[i][j]=0;
        mark= new int[n];
    }
    ~Graphm() {//析构图
        for (int i=0;i<numVertex;i++)
                    delete []matrix[i];
        delete []matrix;
        delete []mark;
    }
    public:
    void setMark(int v, int val) {//标记
        mark[v]=val;
    }
    int getMark(int v) {//获取标记
        return mark[v];
    }
    void setEdge(int v1, int v2, int weight) {//加边
        if (matrix[v1][v2]==0) numEdge++;
        matrix[v1][v2] = matrix[v2][v1] =  weight;
    }
    void delEdge(int v1, int v2) {//删除边
        matrix[v1][v2] = matrix[v2][v1]=0;
    }
    int weight(int v1, int v2) {//获取边上的权值
        return matrix[v1][v2];
    }
    bool isEdge(int v1, int v2) {//判断是否有边
        if (matrix[v1][v2]!=0) return true;
        return false;
    }
    int n() {//获取顶点数
        return numVertex;
    }
    int e() {//获取边数
        return numEdge;
    }
    int first(int v) {//获取顶点的第一个邻接点
        for (int i=0;i<numVertex;i++) {
            if (matrix[v][i]!=0)
            return i;
        }
        return numVertex;
    }
    int next(int v, int w) {//获取顶点的下一个邻接点
        for (int i=w+1;i<numVertex;i++) {
            if (matrix[v][i]!=0)
                return i;
        }
        return numVertex;
    }
};
class OpertaionG{//图操作类
private:
    Graphm *G;//图
    Graphm *MST;
    int cnt;
    struct e {
        int s;
        int e;
        int w;
    }
    ;
    int *father;
public:
    OpertaionG(Graphm *g){
        G = g;
    }
    void DFS() {//深度优先遍历
        for (int i=0;i<G->n();i++)
            G->setMark(i,UNVISITED);
        for (int i=0;i<G->n();i++)
            if (G->getMark(i)== UNVISITED)
        helpDfs(i,0);
    }
    void BFS() {//广度优先遍历
        cnt=0;
        Queue<int>* q= new Queue<int>;
        for (int i=0;i<G->n();i++)
            G->setMark(i,UNVISITED);
        for (int i=0;i<G->n();i++)
        if(G->getMark(i)==UNVISITED)
        helpBfs(i,q);
        delete q;
    }
    void Dijkstra(int start) {//单元最短路径
        int n = G->n();
        for (int i=0;i<n;i++)
            G->setMark(i,UNVISITED);
        int D[n];//最短路径距离
        int pre[n];//存储最短路径
        memset(pre,-1,sizeof (pre));
        for (int i=0;i<n;i++)
            D[i]=INFINITY;
        D[start]=0;
        for (int i=0;i<n;i++) {
            int v = minVertex(D);
            if (v==-1) return;
            G->setMark(v,VISITED);
            for (int i=G->first(v);i<n;i=G->next(v,i)) {
                if (G->getMark(i)==UNVISITED && D[i]>D[v]+G->weight(v,i)) {
                    D[i]=D[v]+G->weight(v,i);
                    pre[i]=v;
                }
            }
        }
        for (int i=1;i<n;i++) {
            if(D[i]==INFINITY) cout<<0+1<<" "<<i+1<<0<<endl; else {
                cout << 0+1<<" ";
                string s="";
                int x = i;
                while (pre[x]!=-1) {
                    s=std::to_string(x+1)+" "+s;
                    //输出+1
                    x = pre[x];
                }
                cout<<s<<D[i]<<endl;
            }
        }
    }
    void Prim() {//获取最小生成树
        int n = G->n();
        for (int i=0;i<n;i++)
            G->setMark(i,UNVISITED);
        int D[n];
        for (int i=0;i<n;i++)
            D[i]=INFINITY;
        D[0]=0;
 
        struct e E[n];
        E[0].s=0;
        E[0].e=0;
        E[0].w=INFINITY;
 
        for (int i=0;i<n;i++) {
            int min = minVertex(D);
            if (min==-1)  return;
            G->setMark(min,VISITED);
            for (int i=G->first(min);i<n;i=G->next(min,i))
                if (G->getMark(i)==UNVISITED&& D[i]>G->weight(min,i)) {
                D[i]=G->weight(min,i);
                E[i].s=min;
                E[i].e=i;
                E[i].w=G->weight(min,i);
            }
        }
        sort(E,E+n,cmp);
        for (int i=0;i<n-1;i++)
        if (E[i].s<E[i].e)
        cout<<E[i].s+1<<" "<<E[i].e+1<<" "<<E[i].w<<endl;
         else
                        cout<<E[i].e+1<<" "<<E[i].s+1<<" "<<E[i].w<<endl;
    }
    void hasCircle() {//判断图是否有环
        int n = G->n();
        father = new int[n];
        for (int i=0;i<n;i++)
            father[i]=-1;
        for (int i=0;i<n;i++)
        for (int j=i;j<n;j++) {
            if (G->weight(i,j)!=0) {
                int y1 = find(i);
                int y2 = find(j);
                if (y1==y2)
                    cout<<"NO";
            }
        }
        cout<<"YES";
        delete[] father;
    }
    int find(int v) {
        if (father[v]==-1) return v;
        return father[v]=find(father[v]);
    }
    bool static cmp(struct e e1,struct e e2) {
        return e1.w<e2.w;
    }
    int minVertex(int *D) {//获取最小的邻接点
        int minCost=INFINITY;
        int flag=-1;
        for (int i=0;i<G->n();i++) {
            if (minCost>D[i] && G->getMark(i)==UNVISITED) {
                minCost=D[i];
                flag=i;
            }
        }
        return flag;
    }
    void helpDfs(int v, int cnt) {//深度优先遍历的主要实现
        if(cnt!=G->n()-1) {
            cout<<v+1<<" ";
            cnt+=1;
        } else cout<<v+1<<endl;
        G->setMark(v,VISITED);
        for (int i = G->first(v); i<G->n();i=G->next(v,i)) {
            if (G->getMark(i)==UNVISITED)
            helpDfs(i,cnt);
        }
    }
    void helpBfs(int v, Queue<int>* q) {//广度优先遍历的主要实现
        q->enqueue(v);
        G->setMark(v,VISITED);
        while (q->length() != 0) {
            int a = q->dequeue();
            if (cnt!=G->n()-1) {
                cout<<a+1<<" ";
                cnt+=1;
            } else cout<<a+1<<endl;
            for (int i=G->first(a);i<G->n();i=G->next(a,i))
                if (G->getMark(i)==UNVISITED) {
                q->enqueue(i);
                G->setMark(i,VISITED);
            }
        }
    }
};
int main() {
    int n,m;
    cin>>n>>m;
    Graphm *G = new Graphm(n);
    int s,e,w;
    for (int i=0;i<m;i++) {
        cin>>s>>e>>w;
        G->setEdge(s-1,e-1,w);
    }
    OpertaionG *O = new OpertaionG(G);
    //广度优先遍历
    O->BFS();
    //深度优先遍历
    O->DFS();
    //最短路径
    O->Dijkstra(1-1);
    //最小生成树
    O->Prim();
    //判断是否有环
    O->hasCircle();
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mxmevol

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值