图的基本、常见操作

学数据结构学到图,把图的操作整理成类,下面贴出代码。
基本操作:
1. 通过邻接矩阵创建图
2. 计算某个元素的入度、出度、度
3. 打印邻接矩阵
4. 深度优先DFS
5. 广度优先BFS
6. 最小生成树Prim算法
7. 访问元素

关键路径等其他操作后续会给出…
注:这些常见操作都是按照邻接矩阵来写的。邻接矩阵转换为邻接表还没来得及写,应该问题不大。后续会给出完整版。

以下是类成员

#ifndef graph_hpp
#define graph_hpp

#include <iostream>


template<class Type>        //这棵树是存放最小生成树的
struct Tree
{
    Type element;
    int Vi;
};

struct  Aedge       ////用于prim算法的辅助数组
{
    int Vi;         //顶点序号
    int Wi;         //邻接边的最小权值

};


template<class T1>
class Graph_with_list;


template <class T1>
class Graph_with_matrix {
private:
    int vertex_num;
    int edge_num;
    int **matrix;
    T1 *element;      //数据元素

    int First_AdjVex(int v);     //返回第一个邻接点
    int Next_AdjVex(int v,int w);        //返回下一个邻接点

    void Visit(T1 v);                      //访问的是元素而不是元素的位置
    void DFS(int v,bool* visited);         //递归函数,被DFS Traverse 调用


public:
    Graph_with_matrix():vertex_num(0),edge_num(0),matrix(NULL),element(NULL){};
    ~Graph_with_matrix();    
    void Create_Graph();        //创建图
    Tree<T1>* Prim(T1 start);                //prim算法,用于生成最小生成树
    void DFS_Traverse();
    void BFS_Traverse();
    void Print_matrix();          //打印邻接矩阵
 //   Graph_with_list<T1> Convert_to_list();                //转换为邻接表,后续给出
    int ID(T1 e);               //入度
    int OD(T1 e);              //出度
    int TD(T1 e);               //度


};

以下是实现的代码

#include "graph.hpp"
#include <queue>
using namespace std;




template<class T1>
void Graph_with_matrix<T1>::Create_Graph()
{
    cout<<"Please input the elements :"<<endl;
    element=new T1[20];     //为了节省空间,只使用20个
    T1 in;
    while (cin>>in&&in!='#') {
        element[vertex_num]=in;
        vertex_num++;
    }

    cin.clear();
    cin.ignore(1,'\n');

    cout<<"Please input the weight of edges: "<<endl;

    int weight;
    matrix=new int*[vertex_num];
    for (int i=0; i<vertex_num; i++) {
        matrix[i]=new int[vertex_num];
    }


    for (int i=0; i<vertex_num; i++) {

        for (int j=0; j<vertex_num; j++) {
            cin>>weight;
            matrix[i][j]=weight;
            if (weight!=0) {
                edge_num++;
            }
        }
    }
}


template<class T1>
void Graph_with_matrix<T1>::Print_matrix()
{
    for (int i=0; i<vertex_num; i++) {
        cout<<element[i]<<" ";
    }
    cout<<endl;
    for (int i=0; i<vertex_num; i++) {
        for (int j=0; j<vertex_num; j++) {
            cout<<matrix[i][j]<<" ";
        }
        cout<<endl;
    }
}


template<class T1>
Tree<T1>* Graph_with_matrix<T1>::Prim(T1 start)
{
    Aedge cost[vertex_num];      //辅助数组
    Tree<T1>* tree=new Tree<T1>[vertex_num];



    //定位start在哪里,并赋值给u,u在之后记录权值最小的位置

    int u = 0;
    for (int i=0; i<vertex_num; i++) {
        if (element[i]==start) {
            u=i;
            break;
        }
    }


    tree[0].element=element[u];
    tree[0].Vi=u;

    int n=1;        //记录tree的位置


    //初始化辅助数组

    for (int i=0; i<vertex_num; i++) {
        (cost[i]).Wi=matrix[u][i];
        cost[i].Vi=i;
    }

    cost[u].Wi=-1;

    //开始遍历
    for (int i=0; i<vertex_num-1; i++) {

        //寻找辅助数组最小的值
        int v=u;        //记录u上次的值
        u=0;
        while (cost[u].Wi==0||cost[u].Wi==-1) {         //找到第一个u,其weight不为0和-1
            u++;
        }

        if (u==v) {                                 //如果u等于u上次的值,则++
            u++;
            while (cost[u].Wi==0&&cost[u].Wi==-1) {
                u++;
            }
        }

        for (int j=u+1; j<vertex_num; j++) {
            if ( cost[j].Wi!=0&&cost[j].Wi!=-1&&cost[u].Wi>cost[j].Wi) {
                u=j;
            }
        }

        tree[n].Vi=u;
        tree[n].element=element[u];
        n++;

        cost[u].Wi=-1;       //置为-1,表示不再用




        //修改最小边值
        for (int k=0; k<vertex_num; k++) {
            if (matrix[u][k]<cost[k].Wi) {
                cost[k].Wi=matrix[u][k];
                cost[k].Vi=u;
            }
            else if (cost[k].Wi==0) {
                cost[k].Wi=matrix[u][k];
                cost[k].Vi=u;
            }
        }
    }

    cout<<"The tree will be like: "<<endl;
    for (int i=0; i<vertex_num; i++) {
        cout<<tree[i].element<<" "<<tree[i].Vi<<" "<<endl;
    }

    return tree;
}





//以下几个都是深度和广度遍历的函数
template<class T1>
void Graph_with_matrix<T1>::Visit(T1 v)
{
    cout<<v<<" ";
}
template<class T1>
int Graph_with_matrix<T1>::First_AdjVex(int v)
{
    for (int i=0; i<vertex_num; i++) {
        if (matrix[v][i]&&i!=v) {
            return i;
        }
    }

    return -1;  //不存在
}
template<class T1>
int Graph_with_matrix<T1>::Next_AdjVex(int v,int w)
{
    for (int i=w+1; i<vertex_num; i++) {
        if (matrix[v][i]&&i!=v) {
            return i;
        }
    }

    return -1;
}
template<class T1>
void Graph_with_matrix<T1>::DFS(int v,bool* visited)
{
    int w;
    visited[v]=true;
    Visit(element[v]);

    for (w=First_AdjVex(v); w>=0; w=Next_AdjVex(v, w)) {
        if (!visited[w]) {
            DFS(w);
        }
    }

}
template<class T1>
void Graph_with_matrix<T1>::DFS_Traverse()
{
    int v;
    bool* visited=new bool[vertex_num];

    for (int i=0; i<vertex_num; i++) {      //对访问标记初始化
        visited[i]=false;
    }

    for (v=0; v<vertex_num; v++) {
        if (!visited[v]) {
            DFS(v,visited);
        }
    }

    delete []visited;

}
template<class T1>
void Graph_with_matrix<T1>::BFS_Traverse()
{
    int v,w;
    bool *visited=new bool[vertex_num];

    queue<int> q;
    for (v=0; v<vertex_num; v++) {      //初始化访问标记
        visited[v]=false;
    }

    for (v=0; v<vertex_num; v++) {
        if (!visited[v]) {
            visited[v]=true;
            Visit(element[v]);
            q.push(v);
            while (!q.empty()) {
                q.pop();
                for (w=First_AdjVex(v); w>=0; w=Next_AdjVex(v, w)) {
                    if (!visited[w]) {
                        visited[w]=true;
                        Visit(element[w]);
                        q.push(w);
                    }
                }
            }
        }
    }
    delete []visited;
}



template<class T1>
Graph_with_matrix<T1>::~Graph_with_matrix()
{
    //删除matrix
    for (int i=0; i<vertex_num; i++) {
        delete []matrix[i];
    }
    delete []matrix;

    //删除element
    delete []element;

}

template<class T1>
int Graph_with_matrix<T1>::OD(T1 e)
{
    int od=0;
    int u=-1;
    for (int i=0; i<vertex_num; i++) {      //找到
        if (element[i]==e) {
            u=i;
            break;
        }
    }
    if (u==-1) {
        return -1;              //表示找不到此元素
    }
    for (int i=0; i<vertex_num; i++) {
        if (!matrix[u][i]) {
            od++;
        }
    }
    return od;
}


template<class T1>
int Graph_with_matrix<T1>::ID(T1 e)
{
    int id=0;
    int u=-1;
    for (int i=0; i<vertex_num; i++) {
        if (element[i]==e) {
            u=i;
            break;
        }
    }
    if (u==-1) {
        return -1;
    }
    for (int i=0; i<vertex_num; i++) {          //按列找
        if (!matrix[i][u]) {
            id++;
        }
    }
    return id;
}

template<class T1>
int Graph_with_matrix<T1>::TD(T1 e)
{
    return ID(e)+OD(e);
}

第一次写,还有些稚嫩,欢迎大家提出意见,有任何代码上的问题随时可以联系我。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值