图--图的存储【做题记录】c++

使用邻接矩阵存储无向图

【题目要求】

完成一个无向图的类,实现无向图的的创建和输出。

【输入输出】

第一行输入顶点的个数n

第二行输入n个顶点的信息,为字符型。

第三行输入边的条数m

下面m行输入边的起点下标,终点下标和权值

第一行输出图的顶点信息

第二行输出图的边的信息,边按照起点下标升序排列,边的起点坐标小于终点坐标,输出一次即可。

【测试数据】

输入:

4

A B C D

4

0 1

0 2

2 3

3 0

输出:

图的顶点有:A B C D

图的边有:A-B A-C A-D C-D

【代码】

/**使用邻接矩阵存储图--有向网*/
#include<iostream>
#include<limits.h>
#define MAX_V_NUM 20  //顶点的最大个数
using namespace std;
/**图类*/
template <class T>
class MGraph
{
private:
    T vertex[MAX_V_NUM];//图元素的一维数组
    int arc[MAX_V_NUM][MAX_V_NUM];//图的邻接矩阵,二维数组
    int vexNum, arcNum;//元素个数,边的个数
public:
    MGraph()//构造函数
    {
        cin >> vexNum;
        for (int i = 0; i < vexNum; i++)
        {
            cin >> vertex[i];  //输入图元素的一维数组
        }
        for (int i = 0; i < vexNum; i++)
        {
            for (int j = 0; j < vexNum; j++)
                arc[i][j] = 0;
        }
        cin >> arcNum;
        for (int i = 0; i < arcNum; i++)
        {
            int start, end;
            cin >> start >> end;
            arc[start][end] = 1;
            arc[end][start] = 1;
        }
    }
    
    ~MGraph() {};
    void DFSTraverse(int v);
    void BFSTraverse(int v);
    void printMG()
    {
        cout << "图的顶点有:";
        for (int i = 0; i < vexNum; i++)
            cout << vertex[i] << " ";
        cout << endl;
        cout << "图的边有:";
        for (int i = 0; i < vexNum; i++)
        {
            for (int j = i+1; j < vexNum; j++)
            {
                if (arc[i][j] == 1)
                    cout << vertex[i] << "-" << vertex[j]<<" ";
            }
        }
    }
};


int main()
{
    MGraph<char> graph;
    graph.printMG();
    return 0;
}

无向图的基本计算

【题目要求】

采用邻接矩阵存储有无向图后,如何计算图中有多少条边(不直接读arcNum属性)?输入i、j两个顶点的值(不是下标),判断两个顶点i到j是否有边相连?输入任意一个顶点,输出它的度?

【代码】

 /**使用邻接矩阵存储--无向图*/
#include<iostream>
#include<limits.h>
#define MAX_V_NUM 20  //顶点的最大个数
using namespace std;
/**图类*/
template <class T>
class MGraph
{
private:
    T vertex[MAX_V_NUM];//图元素的一维数组
    int arc[MAX_V_NUM][MAX_V_NUM];//图的邻接矩阵,二维数组
    int vexNum, arcNum;//元素个数,边的个数
public:

    MGraph()
    {
        cin>>vexNum;
        int i,j;
        for(i=0;i<vexNum;i++)
        {
            cin>>vertex[i];//图元素的一维数组
        }
        for(i=0;i<vexNum;i++)
            for(j=0;j<vexNum;j++)
            arc[i][j]=0;//初始化邻接矩阵
        cin>>arcNum;
        for(i=0;i<arcNum;i++)
        {
            int start,endi;
            cin>>start>>endi;
            arc[start][endi]=1;//对称矩阵
            arc[endi][start]=1;
        }
    }
    ~MGraph( ) {};
    void DFSTraverse(int v);
    void BFSTraverse(int v);
    void printMG()
    {
    cout<<"图的顶点有:";
    int i,j;
    for(i=0;i<vexNum;i++)
    {
        cout<<vertex[i]<<" ";
    }
    cout<<endl;
    cout<<"图的边有:";
    for(i=0;i<vexNum;i++)//
    {
        for(j=i+1;j<vexNum;j++)//
        {
            if(arc[i][j]==1)
            {
                cout<<vertex[i]<<"-"<<vertex[j]<<" ";
            }
        }
    }
    cout<<endl;
}
    int computeArcNum();//计算边的条数
    bool isConnected(T v1,T v2);//判断两个顶点是否有边相连
    int getIndex(T vertex);//获得顶点的下标
    int getDegree(T vertex);//求顶点的度

};

template <class T>
/**计算边的条数*/
int MGraph<T>::computeArcNum()
{
    int count=0;
    int i,j;
    for(i=0;i<vexNum;i++)
    {
        for(j=0;j<vexNum;j++)
        {
            if(arc[i][j]==1)
                count++;
        }
    }
    return count/2;
}

template <class T>
/**获取对应值的下标*/
int MGraph<T>::getIndex(T vertex1)
{
    int i;
    for(i=0;i<vexNum;i++)
    {
        if(vertex[i]==vertex1)
        {
            return i;
        }
    }
    return -1;//找不到对应的顶点
}

template <class T>
/** 判断两个顶点是否连接 */
bool MGraph<T>::isConnected(T v1,T v2)
{
    int index1=getIndex(v1);
    int index2=getIndex(v2);
    if(index1==-1||index2==-1)
    {
        return false;//如果有一个顶点不存在,返回false
    }
    return arc[index1][index2]==1;//根据邻接矩阵判断两个顶点是否相连
}

template <class T>
/**求顶点的度*/
int MGraph<T>::getDegree(T vertex)//求度
{
    int i;
    int index=getIndex(vertex);
    if(index==-1)
    {
        return -1;
    }
    int degree=0;
    for(i=0;i<vexNum;i++)
    {
        if(arc[index][i]==1)
        {
            degree++;
        }
    }
    return degree;
}


int main()
{

    MGraph<char> graph;
    //graph.printMG();

    cout<<"The number of edges: "<<graph.computeArcNum()<<endl;
    //cout<<"\n判断顶点是否相连,请输入两个顶点的值:";
    char v1,v2;
    cin>>v1>>v2;
    if(graph.isConnected(v1,v2))
        cout<<v1<<" and "<<v2<<" is connected."<<endl;
    else
        cout<<v1<<" and "<<v2<<" is not connected."<<endl;
    //cout<<"输出顶点的度,输入一个顶点";
    cin>>v1;
    cout<<v1<<" degree: "<<graph.getDegree(v1);
    return 0;
}

使用邻接表存储有向网

vertex:数据域,存放顶点信息。

firsteArc:指针域,指向边表中第一个结点。

adjvex:邻接点域,边的终点在顶点表中的下标。

nextArc:指针域,指向边表中的下一个结点。

边表还可以有权值域weight

【题目要求】

使用邻接表存储一个有向网,输出图的基本信息。构成链表时可以使用头插法

【输入输出】

第一行输入顶点的个数

第二行输入顶点的内容,为字符型

第三行输入边的条数

下面多行输入每条边的起点下标,终点下标和权值。

第一行输出图的顶点。

第二行输出图的边,输出权值。

【测试数据】

输入:

4

0 1 2 3

4

0 1 2

0 2 5

2 3 8

3 0 7

输出:

图的顶点有:0 1 2 3

图的边有:0-2:[5] 0-1:[2] 2-3:[8] 3-0:[7]

【代码】

#include<iostream>
#define  MAX_VERTEX_NUM 20//最大顶点个数
using namespace std;

/**边表的结构体*/
struct ArcNode
{
    int adjvex;//邻接点在数组中的位置下标
    struct ArcNode* nextArc;//指向下一个邻接点的指针
    int weight;//权值,网才有权值
};

/**顶点的结构体*/
template <class T>
struct VNode
{
    T vertex;//顶点的数据域
    ArcNode* firstArc;//指向邻接点的指针
};

/**邻接表类*/
template <class T>
class ALGraph
{
private:
    VNode<T> AdjList[MAX_VERTEX_NUM];//顶点表的数组
    int vexNum, arcNum;//记录图中顶点数和边或弧数
public:
    ALGraph();//构造函数
    ~ALGraph() {}; //析构函数
    void printALG();//打印函数
    void createDN();//构造有向网
    int getOutDegreeDN(T vertex);//根据指定的值求出度
    int getInDegreeDN(T vertex);//根据指定的值求入度
    void setVertex(int index, T value);
    void incrementVexNum();
};

template <class T>
ALGraph<T>::ALGraph() {
    // 将顶点数和边数初始化为0
    vexNum = 0;
    arcNum = 0;
    // 顶点表的数组初始化
    for (int i = 0; i < MAX_VERTEX_NUM; i++) {
        AdjList[i].firstArc = NULL;
    }
}
// 输出函数
template <class T>
void ALGraph<T>::printALG() {
    cout << "图的顶点有:";
    // 依次遍历顶点表,输出顶点
    for (int i = 0; i < vexNum; i++) {
        cout << AdjList[i].vertex << " ";
    }
    cout << endl;
    // 遍历边表
    cout << "图的边有:";
    for (int i = 0; i < vexNum; i++) {
        ArcNode* p = AdjList[i].firstArc; //定义一个p指针,初始化指向顶点表的第一个指向邻接表的指针
        // 遍历边表,p不为空的话
        while (p) {
            cout << AdjList[i].vertex << "-" << AdjList[p->adjvex].vertex << ":[" << p->weight << "] ";  //就输出边表对应的数据:起始位置-终点位置:【权值】
            p = p->nextArc; //p移到下一位
        }
    }
    cout << endl;
}
// 构建有向图
template <class T>
void ALGraph<T>::createDN() {
    int u, v, w;
    // 输入起点下标,终点下标,权值
    cin >> u >> v >> w; 
    ArcNode* p = new ArcNode; //定义邻接表的p指针
    p->adjvex = v; //传入邻接点在数组中的终点位置下标
    p->weight = w; //传入对应的权值
    // 头插法插入新的数据
    p->nextArc = AdjList[u].firstArc; 
    AdjList[u].firstArc = p;
    arcNum++; //边数增加
}

//更改顶点表的数据域,传入下标和数据
template <class T>
void ALGraph<T>::setVertex(int index, T value) {
    if (index >= 0 && index < MAX_VERTEX_NUM) {
        AdjList[index].vertex = value;
    }
}
//vexNum为私有属性,不能直接访问
template <class T>
void ALGraph<T>::incrementVexNum() {
    if (vexNum < MAX_VERTEX_NUM) {
        vexNum++;
    }
}
int main() {
    ALGraph<char> graph;
    int n, m;
    // 输入顶点的个数
    cin >> n;
    // 输入顶点
    for (int i = 0; i < n; i++) {
        char v;
        cin >> v;
        graph.setVertex(i, v);
        graph.incrementVexNum();
    }
    // 输入边的个数
    cin >> m;
    // 输入边的起点下标,终点下标和权值。
    for (int i = 0; i < m; i++) {
        graph.createDN();
    }
    // 打印输出
    graph.printALG();
    return 0;
}

构造函数可以像下面这样写,会更简洁。这样大部分输入操作就在构造函数中完成,不用再在主函数中输入,也就不需要

void setVertex(int index, T value);

void incrementVexNum();

这两个函数来传值。

ALGraph()//构造函数
    {
        vexNum=0;
        arcNum=0;
        int i;
        for(i=0; i<MAX_VERTEX_NUM; i++)
        {
            AdjList[i].firstArc=NULL;//初始化操作
        }
        int n, m;
        cin >> n;
        vexNum=n;
        for (int i = 0; i < n; i++)
        {
            char vertex;
            cin >> vertex;
            AdjList[i].vertex = vertex;
        }
        cin >> m;
        for (int i = 0; i < m; i++)
        {
            int u, v, w;
            cin >> u >> v >> w;
            ArcNode *p = new ArcNode;
            p->adjvex = v;
            p->weight = w;
            p->nextArc = AdjList[u].firstArc;
            AdjList[u].firstArc = p;
        }

有向网的基本计算

【题目要求】

采用邻接表存储有向网后,如何计算图中有多少条边(不直接读arcNum属性)?输入i、j两个顶点的值(不是下标),判断两个顶点i到j是否有边相连?输入任意一个顶点,输出它的入度和出度?

这里提供了以下函数:

  1. int getIndex(T vertex);//获得顶点的下标
  2. int getOutDegreeDN(T vertex);//根据指定的值求出度
  3. int getInDegreeDN(T vertex);//根据指定的值求入度
  4. int computeArcNum();//计算边的条数
  5. bool isConnected(T v1,T v2);//判断两个顶点是否有边相连

【代码】

获得顶点下标
//获取顶点的下标
template <class T>
int ALGraph<T>::getIndex(T vertex) { //传入顶点
    for (int i = 0; i < vexNum; i++) { //遍历顶点表
        if (AdjList[i].vertex == vertex) { //如果顶点表的数据域与传入要查找的顶点相同的话,就返回此时的下标
            return i;
        }
    }
    return -1; //如果没找到,就返回-1
}
根据指定的值求出度
template <class T>
int ALGraph<T>::getOutDegreeDN(T vertex) {
    int index = getIndex(vertex);
    if (index == -1) { //如果传入的数据不属于顶点表,就返回-1
        return -1;
    }
    int count = 0;
    ArcNode* p = AdjList[index].firstArc;
    while (p) {
        count++;
        p = p->nextArc;
    }
    return count;
}
根据指定的值求入度
template <class T>
int ALGraph<T>::getInDegreeDN(T vertex) {
    int count = 0;
    for (int i = 0; i < vexNum; i++) {
        ArcNode* p = AdjList[i].firstArc;
        while (p) {
            if (p->adjvex == getIndex(vertex)) {
                count++;
            }
            p = p->nextArc;
        }
    }
    return count;
}
计算边的条数
template <class T>
int ALGraph<T>::computeArcNum() {
    int count = 0;
    //遍历边表
    for (int i = 0; i < vexNum; i++) {
        ArcNode* p = AdjList[i].firstArc;
        while (p) {
            count++;
            p = p->nextArc;
        }
    }
    return count;
}
判断两个顶点是否有边相连
template <class T>
bool ALGraph<T>::isConnected(T v1, T v2) {
    //获取两个顶点的下标
    int index1 = getIndex(v1);
    int index2 = getIndex(v2);
    if (index1 == -1 || index2 == -1) {
        return false; //如果没找到该顶点,就返回假
    }
    //遍历下标为index1的顶点对应的边表
    ArcNode* p = AdjList[index1].firstArc;
    while (p) {
        if (p->adjvex == index2) { //邻接点在数组中的位置下标等于要找的顶点在数组中的下标,说明能找到这个顶点,所以两个顶点有关联,返回真
            return true;
        }
        p = p->nextArc;
    }
    return false;
}

  • 27
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值