数据结构中的图表(使用C++)

132 阅读4分钟

数据结构中的图表(使用C++)

图是反映事物之间配对关系的数学结构。图是一种流动结构,显示几个对象的相互作用。它可以通过利用两个基本组成部分,即节点和边来表示。

  • 节点:这些是每个图中最关键的元素。边缘用来表示节点的连接。例如,一个有两个节点的图用一条无方向的边连接,表明这两个节点之间的双向联系。

  • :边是图形的一部分,显示节点之间的连接。一个边表示两个节点之间的连接。

在现实生活中的一个应用

  • 谷歌地图:将你的旅程从起点连接到终点。
  • 社交网络:朋友之间用一条边连接,每个用户代表一个顶点。
  • 推荐系统:用户的推荐之间的关系数据使用图进行连接。

图的类型

  • 无向的:无定向图中的所有边都是双向的,不指向任何特定的方向。

Undirected-graph

  • 有向图:在一个有向图中,所有的边都是单向的;它们指向一个方向。

Directed-graph

  • 加权图:加权图,每条边,都分配了一个权重或成本。考虑一个有四个节点的网络,如图所示。图中的每条边都有一些权重。

如果你想从顶点2到顶点1,你可以选择三条路线中的一条。

2->3->1
2->1
2->3->4->1

因此,每条路径的总成本如下。

The total cost of 2->3->1 is (2+1), or three units.

The total cost of getting from 2->1 is one unit.

The total cost of 2->3->4->1 is (2+2+3), or seven units.

Weighted-graph

  • 循环的。如果一个图形包含一条起点和终点都在同一个顶点的路径,那么它就被称为是循环的。这被称为一个循环。非循环图没有循环。

Cyclic-graph

下图描述了一个循环(0->1->2)。树是一种只有一条路径连接任何两个顶点的图形。图中的每个节点可能有一个或多个父节点。在树中,每个节点正好有一个父节点。

树不能有任何循环或周期,而图则可以。

tree-graph

图的表示

我们可以用几种方式来表示一个图。

以下是表达图的两种最常见的方式。

  1. 邻接矩阵一个V*V的二进制矩阵就是一个邻接矩阵。有一条连接顶点i和顶点j的边,元素Ai,j为1,否则Ai,j为0。

注意:二元矩阵的单元格只能有两个可能的值之一。0或1。

我们可以在加权图的邻接矩阵中存储Ai,j处的边缘成本,而不是存储0或1。

如果Ai,j在无定向图中是1,那么Ai,j也将是1。

如果Ai,j在有向图中是1,那么它可能是也可能不是1。

邻接矩阵提供了恒定的时间访问(O(1))来检测两个节点是否有一条边。因此,邻接矩阵的空间复杂度为O(V)2。

  1. 邻接列表这是我们在代码中实现图的时候最常用的表示方法。邻接列表是一个数组A中不同列表的集合。例如,一个图的每个节点Ai都是一个列表,它持有顶点i旁边的所有顶点的值。

如果我们有一个加权图,我们用对来存储与顶点的成本。当我们在代码中实现它时,你会得到更好的理解。如果顶点j在列表Ai中,在无向图中顶点i将在列表Aj中。

由于邻接列表中的这些信息只存储在图中存在的边上,其空间复杂度为O(V + E)。无向图的表示。

  • G是一个有5个顶点和7条边的无向图。

undirected-graph

  • G的邻接列表表示。

graphList

  • G的邻接矩阵表示法。

graphMartrix

图的邻接列表表示法的代码

#include <iostream>
#include<list>
using namespace std;

class graph{
public:
    list<int> *adjlist;
    int n;
    graph(int v){
        adjlist=new list<int> [v];
        n=v;
    }

    void addedge(int u,int v,bool bi){
        adjlist[u].push_back(v);
        if(bi){
            adjlist[v].push_back(u);
        }
    }

    void print(){
        for(int i=0;i<n;i++){
            cout<<i<<"-->";
            for(auto it:adjlist[i]){
                cout<<it<<" ";
            }
            cout<<endl;
        }
        cout<<endl;
    }


};

int main() {
    graph g(5);
    g.addedge(1,2,true);
    g.addedge(4,2,true);
    g.addedge(1,3,true);
    g.addedge(4,3,true);
    g.addedge(1,4,true);

    g.print();
}

输出结果

output

  • 在输出中,你可以看到邻接列表视图中的图的执行情况。

总结

通过从基础开始学习图,你在解决数据结构问题时将会有更多的分析性思维。现在的下一步是练习一些图的问题,因为我们现在对图的基础有了更好的理解。