数据结构(C++)<图的邻接矩阵存储>

1.图的概念

图是有顶点集合以及顶点的关系集合组成的一种数据结构。
a)完全图:由n个顶点组成的无向图,若有n*(n-1)/2条边,则称为无向图完全图。
在由n个顶点组成的有向图中,若有n*(n-1)条边,则称之为有向完全图。
b)权:在某些图中,边具有与之相关的数值,称为权重。权重可以表示从一个顶点到另一个顶点的距离、花费的代价等等。这种带权图也叫作网络。
c)度:与顶点v关联的边数称为度。在有向图中顶点的度数等于其入度加出度之和。入度是指以结点为终点的边 ,出度是指以结点为起点的边。
d)连通图:
在图论中,连通图基于连通的概念。在一个无向图 G 中,若从顶点vi到顶点vj有路径相连(当然从vj到vi也一定有路径),则称vi和vj是连通的。如果 G 是有向图,那么连接vi和vj的路径中所有的边都必须同向。如果图中任意两点都是连通的,那么图被称作连通图。如果此图是有向图,则称为强连通图(注意:需要双向都有路径)。
e)连通分量:连通分量:无向图 G的一个极大连通子图称为 G的一个连通分量(或连通分支)。连通图只有一个连通分量,即其自身;非连通的无向图有多个连通分量。

2.邻接矩阵:

所谓邻接矩阵(Adjacency Matrix)的存储结构,就是用一维数组存储图中顶点的信息,用矩阵表示图中各顶点之间的邻接关系。假设图G=(V,E)有n 个确定的顶点,即V={v0,v1,…,vn-1},则表示G 中各顶点相邻关系为一个n×n 的矩阵,矩阵的元素为:

这里写图片描述

用邻接矩阵表示法表示图如图8.7 所示:
这里写图片描述
3.代码 实现:
Graphmtx.h

#ifndef GRAPHMTX_H
#define GRAPHMTX_H
#include<Graph.h>
#include<iostream>
#include<stdlib.h>
using namespace std;

template <class T,class E>
class Graphmtx
{

public:
    E maxWeight;
    /** Default constructor */
    Graphmtx(int sz=DefaultVertices)
    {
        maxVertices=sz;
        numVertices=0;
        numEdges=0;
        VerticesList =new T[maxVertices];
        Edge =(E **)new E *[maxVertices];
        //初始化邻接矩阵
        for(int i=0; i<maxVertices; i++)
            Edge[i]=new E[maxVertices];
        for(int i=0; i<maxVertices; i++)
            for(int j=0; j<maxVertices; j++)
                Edge[i][j]=i==j?0:maxWeight;
    }
    /** Default destructor */
    ~Graphmtx()
    {
        delete []VerticesList;
        delete Edge;
    }
    //当前定点数
    int NumberOfvertices()
    {
        return numVertices;
    }
    //返回当前边数
    int NumberOfEdges()
    {
        return numEdges;
    }
//获取顶点的值
    T getValue(int i)
    {
        return i>=0&&i<numVertices?VerticesList[i]:NULL;
    }
    //获取边上的权值
    E getWeight(int v1,int v2)
    {
        return -1!=v1&&-1!=v2?Edge[v1][v2]:0;
    }
    //获取顶点v的第一个邻接顶点
    int getFirstNeighbor(int v)
    {
        if(-1!=v)
        {
            for(int col=0; col<numVertices; col++)
                if(Edge[v][col]>0&&Edge[v][col]<maxWeight)
                    return col;
        }
        return -1;
    }
    //获取v的邻接顶点w的下一邻接顶点
    int getNextNeighbor(int v,int w)
    {
        if(-1!=v&&-1!=w)
            for(int col=w+1; col<maxVertices; col++)
                if(Edge[v][col]>0&&Edge[v][col]<maxWeight)
                    return col;
        return -1;
    }
    //插入顶点
    bool insertVertex(const T &vertex)
    {
        if(numVertices==maxVertices)
            return false;
        VerticesList[numVertices++]=vertex;
        return true;
    }
    //插入边
    bool insertEdge(int v1,int v2,const E cost)
    {
        if(v1>-1&&v1<numVertices&&v2>-1&&v2<numVertices&&Edge[v1][v2]==maxWeight)
        {
            Edge[v1][v2]=Edge[v2][v1]=cost;
            numEdges++;
            return true;
        }
        return false;
    }
    //删除顶点v以及所有与之关联的边
    bool removeVertex(int v)
    {
        //v不在图中不删除
        if(v<0||v>numVertices)
            return false;
        //只剩下一个顶点,不删除
        if(1==numVertices)
        {
            return false;
        }
        VerticesList[v]=VerticesList[numVertices-1];
        //减去与v相关联的边
        for(int i=0; i<numVertices; i++)
            if(Edge[v][i]>0&&Edge[v][i]<maxWeight)
                numEdges--;
        //用最后一列填补第
        for(int i=0; i<numVertices; i++)
            Edge[i][v]=Edge[i][numVertices-1];
        numVertices--;
        //用最后一行填补第v行
        for(int i=0; i<numVertices; i++)
            Edge[v][i]=Edge[numVertices-1][i];
        return true;
    }
    //删除边(v1,v2)
    bool removeEdge(int v1,int v2)
    {

        if(v1>-1&&v1<numVertices&&v2>-1&&v2<numVertices&&Edge[v1][v2]>0&&Edge[v1][v2]<maxWeight)
        {
            Edge[v1][v2]=Edge[v2][v1]=maxWeight;
            numEdges--;
            return true;
        }
        return false;

    }
    template <class V,class W>
    friend istream& operator >>(istream & in,Graphmtx<V,W> &G);
    template <class V,class W>
    friend ostream& operator<<(ostream &out,Graphmtx<V,W> &G);
private:
    //最大的顶点树
    int maxVertices;
    //当前边数
    int numEdges;
    //当前顶点树
    int numVertices;
    //顶点表
    T *VerticesList;
    //邻接矩阵
    E **Edge;
    //给出顶点在图中的位置
    int getVertexPos(T vertex)
    {
        for(int i=0; i<numVertices; i++)
        {
            if(VerticesList[i]==vertex)
                return i;
        }
        return -1;
    }
};

#endif // GRAPHMTX_H

main.cpp

#include <iostream>
#include<Graphmtx.h>
using namespace std;

int main()
{
    Graphmtx<int,int> G(5);
    cin>>G;
    cout<<G;
    return 0;
}
template <class V,class W>
istream& operator >>(istream & in,Graphmtx<V,W> &G)
{
    //n是顶点数,m是边数
    int n,m;
    V e1,e2;
    W weight;
    cout<<"请输入顶点数、边数:"<<endl;
    in>>n>>m;
    cout<<"请输入顶点:"<<endl;
    for(int i=0; i<n; i++)
    {
        in>>e1;
        G.insertVertex(e1);
    }
    int i=0,j,k;
    cout<<"请输入边的两个顶点以及权值:"<<endl;
    while(i<m)
    {

        in>>e1>>e2>>weight;
        j=G.getVertexPos(e1);
        k=G.getVertexPos(e2);
        if(-1==j&&-1==k)
        {
            cout<<"边的两端信息有误,请重新输入。"<<endl;
        }
        else
        {
            G.insertEdge(j,k,weight);
            i++;
        }
    }
    return in;
}
template <class V,class W>
ostream& operator<<(ostream &out,Graphmtx<V,W> &G)
{
//输出所有顶点和边的信息
    int n,m;
    V e1,e2;
    W w;
    n=G.NumberOfvertices();
    m=G.NumberOfEdges();
    out<<"一共有顶点数:"<<n<<"个    边:"<<m<<"条"<<endl;
    for(int i=0; i<n; i++)
        for(int j=i+1; j<n; j++)
        {
            w=G.getWeight(i,j);
            if(w>0&&w<G.maxWeight)
            {
                e1=G.getValue(i);
                e2=G.getValue(j);
                out<<"("<<e1<<","<<e2<<","<<w<<")"<<endl;
            }
        }
    return out;
}

这里写图片描述
工程源码请点击我的GitHub

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值