图的基本概念、存储及基本操作(邻接矩阵法与邻接表法)

【数据结构】图的构建(邻接表法) 最近整理电脑,发现了以前写的数据结构的代码,由于时间久了,好多代码都找不到了,现在扒出来复习一下。 如果看不懂下面关于图的术语或者压根就不知道图。建议看一下严蔚敏版的《数据结构》中对图的介绍 图的构建方法有好几种,如邻接矩阵法,邻接表法,十字链表法,邻接多重表。今天介绍邻接表法。 邻接表(Adjacency List) 是图的一种链式存储结构,在邻接表中,对图中每个顶点建立一个单链表 阅读详情

图的基本概念、存储及基本操作(邻接矩阵法与邻接表法)

1. 图的基本概念

1.1 图的定义

图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G (V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。

在这里插入图片描述

图的定义与线性表定义的对比:

  • 线性表中我们把数据元素叫元素,树中将数据元素叫结点,在图中数据元素,我们则称之为顶点(Vertex)。
  • 线性表中可以没有数据元素,称为空表。树中可以没有结点,叫做空树。但是在图结构中,不允许没有顶点。在定义中,若V是顶点的集合,则强调了顶点集合V有穷非空。
  • 线性表中,相邻的数据元素之间具有线性关系,树结构中,相邻两层的结点具有层次关系,而图中,任意两个顶点之间都可能有关系,顶点之间的逻辑关系用边来表示,边集可以是空的。

1.2 图的分类

1.2.1 无向图

无向边: 若顶点vi到vj之间的边没有方向,则称这条边为无向边(Edge),用无序偶对(vi,vj)来表示。

**若E是无向边(简称边)的优先集合时,则图G为无向图。**如下图所示:

在这里插入图片描述

  • G=(V,E)
  • V = {V1,V2,V3,V4,V5,V6}
  • E = {<V1,V2>,<V1,V4>,<V2,V5>,<V1,V3>,<V3,V4>,<V3,V5>,<V3,V6>,<V4,V6>,<V5,V6>}
1.2.2 有向图

有向边: 若从顶点vi到vj的边有方向,则称这条边为有向边,也称为弧(Arc)。用有序偶来表示,vi称为弧尾(Tail),vj称为弧头(Head)。

若E是有向边(也称弧)的有限集合时,则G为有向图。如下图所示:

See the source image
  • G=(V,E)
  • V = {1, 2, 3, 4, 5}
  • E = {<1,3>,<1,2>,<2,3>,<2,4>,❤️,5>,<4,3>,<4,5>}
1.2.3 简单图

在图中,若不存在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图。满足以下两个条件

  1. 无重复边
  2. 不存在结点到自身的边
1.2.4 多重图

若图G中某两个顶点之间的边数大于1条,又允许顶点通过一条边和自身关联,则称图为多重图。

1.2.5 完全图

完全图又分无向完全图与有向完全图。

​ 无向完全图: 在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。

含有n个顶点的无向完全图有n(n-1)/2条边。

有向完全图: 在有向图中,如果任意两个顶点之间都存在方向互为相反的两条弧,则称该图为有向完全图。

含有n个顶点的有向完全图有n×(n-1)条边。

对于具有n个顶点和e条边数的图,无向图 0 ≤ e ≤ n ( n − 1 ) / 2 0≤e≤n(n-1)/2 0≤e≤n(n−1)/2, 有向图 0 ≤ e ≤ n ( n − 1 ) 0≤e≤n(n-1) 0≤e≤n(n−1)。

稀疏图与稠密图: 有很少条边或弧的图称为稀疏图,反之称为稠密图。这里稀疏和稠密是模糊的概念,都是相对而言的。
权: 有些图的边或弧具有与它相关的数字,这种与图的边或弧相关的数叫做权(Weight)。这些权可以表示从一个顶点到另一个顶点的距离或耗费。
网: 带权的图通常称为网(Network)。
子图: 设有两个图G=(V,{E})和G’=(V’,{E’}),如果$V’∈V且E’∈E,则称G’为G的子图(Sub-graph)。

1.3. 概念

1.3.1 图的顶点与边间关系

邻接点: 对于无向图G=(V,{E}),如果边(v,v’)∈E,则称顶点v和v’互为邻接点(Adjacent),即v和v’相邻接。

边(v,v’)依附(incident)于顶点v和v’,或者说(v,v’)与顶点v和v’相关联。

度: 顶点v的度(Degree)是和v相关联的边的数目,记为TD(v)。

对于有向图G=(V,{E}),如果弧∈E,则称顶点v邻接到顶点v’,顶点v’邻接自顶点v。弧和顶点v,v’相关联。以顶点v为
头弧的数目称为v的入度(InDegree),记为ID(v);以v为尾的弧的数目称为v的出度(OutDegree),记为OD(v);顶点v的度为TD(v)=ID(v)+OD(v)。

路径: 无向图G=(V,{E})中从顶点v到顶点v’的路径(Path)是一个顶点序列 ( v = v i 0 , v i 1 , . . . , v i m = v ′ ) , 其 中 ( v i , j − 1 , v i , j ) ∈ E , 1 ≤ j ≤ m (v=v_{i0},v_{i1},...,v_{im}=v'),其中(v_{i,j-1},v_{i,j})∈E,1≤j≤m (v=vi0​,vi1​,...,vim​=v′),其中(vi,j−1​,vi,j​)∈E,1≤j≤m,其中,。如果G是有向图,则路径也是有向的,顶点序列应满足 < v i , j − 1 , v i , j > ∈ E , 1 ≤ j ≤ m 。 <v_{i,j-1},v_{i,j}>∈E,1≤j≤m。 <vi,j−1​,vi,j​>∈E,1≤j≤m。。

路径的长度是路径上的边或弧的数目。

回路: 第一个顶点和最后一个顶点相同的路径称为回路或环(Cycle)。
简单路径: 序列中顶点不重复出现的路径称为简单路径。
简单回路: 除了第一个顶点和最后一个顶点之外,其余顶点不重复出现的回路,称为简单回路或简单环。

1.3.2 连通图相关术语

连通: 在无向图G中,如果从顶点v到顶点v’有路径,则称v和v’是连通的。
连通图: 如果对于图中任意两个顶点vi、vj∈V,vi和vj都是连通的,则称G是连通图(Connected Graph)。
连通分量: 无向图中的极大连通子图称为连通分量。连通分量的概念强调:

  • 要是子图;
  • 子图要是连通的;
  • 连通子图含有极大顶点数;
  • 具有极大顶点数的连通子图包含依附于这些顶点的所有边。

强连通:在有向图中,如果有一对顶点v和w,从v到w和从w到v之间都有路径,则称这两个顶点是强连通的。

强连通图: 在有向图G中,如果对于每一对vi、vj∈V、vi≠vj,从vi到vj和从vj到vi都存在路径,即图中任何一对顶点都是强连通的,则称G是强连通图。
强连通分量: 有向图中的极大强连通子图称做有向图的强连通分量。
如下图,图1不是强连通图,因为顶点A到顶点D存在路径,而D到A就不存在,但图2是强连通图,图2是图1的极大强连通子图即强连通分量。

在这里插入图片描述

连通图的生成树: 所谓的一个连通图的生成树是一个极小的连通子图,它含有图中全部的n个顶点,但只有足以构成一棵树的n-1条边。

如下图所示:图G1即为图G的最小生成树。

image-20210930204254925

.

如果一个图有n个顶点和小于n-1条边,则是非连通图,如果它多于n-1条边,必定构成一个环,因为这条边使得它依附的那两个顶点之间有了第二条路径。随便加哪两顶点的边都将构成环。不过有n-1条边并不一定是生成树。

有向树: 如果一个有向图恰有一个顶点的入度为0,其余顶点的入度均为1,则是一个有向树。

对有向树的理解比较容易,所谓入度为0其实就相当于树中的根结点,其余顶点入度为1就是说树的非根结点的双亲只有一个。

有向图的生成森林: 一个有向图的生成森林由若干棵有向树组成,含有图中全部顶点,但只有足以构成若干棵不相交的有向树的弧。

2. 图的存储与基本操作

图的存储必须要完整、准确地反映顶点集与边集的信息。

2.1 邻接矩阵存储

定义:

用一个有一位数组存储图中顶点得信息,用一个二维数组存储图中边的信息(即各顶点之间的邻接关系),存储顶点之间邻接关系的二维数组称为邻接矩阵。

图解:

邻接矩阵表示有向图如下图所示:

邻接矩阵表示无向图如下图所示:

See the source image

邻接矩阵表示网如下图所示:

See the source image
特点:
  • 图的邻接矩阵是唯一的,适于存储边的数目较多的稠密图。
  • 无向图的邻接矩阵一定是一个对称矩阵,可采用压缩存储的思想,只存储上(下)三角形阵的元素即可。
  • 不带权的有向图的邻接矩阵一般是一个稀疏矩阵。
  • 矩阵中第 i 行或 第 i 列有效元素个数之和就是顶点的度。
  • 在有向图中 第 i 行有效元素个数之和是顶点的出度,第 i 列有效元素个数之和是顶点的入度。

邻接矩阵代码存储:

typedef int InfoType;
#define	MAXV 100				//最大顶点个数
#define INF 32767				//INF表示∞
//以下定义邻接矩阵类型
typedef struct 
{  	int no;						//顶点编号
	InfoType info;				//顶点其他信息
} VertexType;					//顶点类型
typedef struct  				//图的定义
{  	int edges[MAXV][MAXV]; 		//邻接矩阵
   	int n,e;   					//顶点数,边数
	VertexType vexs[MAXV];		//存放顶点信息
} MGraph;	

2.2 邻接表存储

定义:

图的邻接表存储方式是一种按顺序分配与链式分配相结合的存储方法.
为每个顶点建立一个单链表,边结点由三个域组成,adjvex指示与顶点i邻接的顶点的编号,nextarc指向对应下一条边的节点,info存储与边相关的信息,如权值等。表头节点有两个域组成,data存储顶点i对应的名称或其他信息,firstarc指向对应顶点i的链表中的第一个边节点。

图解

表示有向图的邻接表与逆邻接表如下图所示:

See the source image 表示无向图的邻接表如下图所示: See the source image
特点:
  1. 顶点 vi 的出度为第i个单链表中的结点个数。
  2. 顶点 vi 的入度为整个单链表中邻接点域值是i-1的结点个数。
  3. 找出度易,找入度难

邻接表代码存储:

//以下定义邻接表类型
typedef struct ANode           	//边的节点结构类型
{	int adjvex;              	//该边的终点位置
   	struct ANode *nextarc; 		//指向下一条边的指针
   	InfoType info;           	//该边的相关信息,这里用于存放权值
} ArcNode;
typedef int Vertex;
typedef struct Vnode      		//邻接表头节点的类型
{	Vertex data;            	//顶点信息
    ArcNode *firstarc;     		//指向第一条边
} VNode;
typedef VNode AdjList[MAXV];	//AdjList是邻接表类型
typedef struct 
{	AdjList adjlist;         	//邻接表
    int n,e;                 	//图中顶点数n和边数e
} ALGraph;                   	//图的邻接表类型

2.3 邻接矩阵与邻接表优缺点:

邻接矩阵的优缺点
  • 优点:
    • 可以快速判断两个顶点之间是否存在边
    • 可以快速添加边或者删除边。
  • 缺点:
    • 是如果顶点之间的边比较少,会比较浪费空间。因为是一个 n∗nn∗n 的矩阵。
邻接表的优缺点:
  • 优点:
    • 方便找任一顶点的所有“邻接点”
    • 节约稀疏图的空间:需要N个头指针+2E个结点(每个结点至少2个域)
    • 对无向图而言,方便计算任一顶点的度
  • 缺点:
    • 对有向图而言,只能计算“出度”,需要构造“逆邻接表”来方便计算“入度”。

2.4. 图的基本操作

图的基本操作与实现

(1)自选存储结构,输入含n个顶点(用字符表示顶点)和e条边的图G;

(2)求每个顶点的度,输出结果;

(3) 指定任意顶点x为初始顶点,对图G作DFS遍历,输出DFS顶点序列(提示:使用一个栈实现DFS);

(4) 指定任意顶点x为初始顶点,对图G作BFS遍历,输出BFS顶点序列(提示:使用一个队列实现BFS);

(5) 输入顶点x,查找图G:若存在含x的顶点,则删除该结点及与之相关连的边,并作DFS遍历(执行操作3);否则输出信息“无x”;

(6)判断图G是否是连通图,输出信息“YES”/“NO”;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define maxSize 100
using namespace std;
 
int Count=0;
const int Max=50;
typedef char type;
bool visited[100] = { false };
 
typedef struct                         ///定义数据结构:栈
{
    int *top;
    int *base;
    int Size;
}Stack;
 
typedef struct                        ///定义数据结构:队列
{
    int *Front;
    int *Rear;
    int Size;
} Queue;
 
typedef struct                       ///定义数据结构:图
{
    type vexs[Max];
    bool arcs[Max][Max];
    int vexnum,arcnum;
} graph;
 
void InitStack(Stack &s)             ///对栈进行初始化
{
    if(!(s.top=s.base=(int *)malloc(maxSize*sizeof(int))))
        return ;
    s.Size=maxSize;
}
 
void push(Stack &s,int e)            ///入栈:将元素e压入栈
{
    *s.top=e;
    s.top++;
}
 
void pop(Stack &s)                  ///出栈:栈顶指针减一
{
    if(s.base==s.top)
        return ;
    s.top--;
}
 
int top(Stack s)                    ///返回栈顶元素
{
    s.top--;
    return *s.top;
}
 
void InitQueue(Queue &q)            ///初始化队列
{
    if(!(q.Front=q.Rear=(int *)malloc(maxSize*sizeof(int))))
        return ;
    q.Size=maxSize;
}
 
void Q_push(Queue &q,int e)         ///入队列:将元素e入队列
{
    *q.Rear=e;
    q.Rear++;
}
 
int Q_pop(Queue &q)                 ///出队列:返回队头元素,队头指针加一
{
    int e;
    if(q.Front==q.Rear)
        return 0;
    e=*q.Front;
    q.Front++;
    return e;
}
 
void Create(graph *g)               ///建立邻接矩阵并输出
{
    int i,j;
    memset(g->arcs,0,sizeof(g->arcs));
    for(i=0; i<g->arcnum; ++i)
    {
        int x,y;
        cin>>x>>y;
        g->arcs[x][y]=1;
        g->arcs[y][x]=1;
    }
    cout<<"无向邻接表矩阵为:"<<endl;
    for(i=0; i<g->vexnum; i++)
    {
        for(j=0; j<g->vexnum; j++)
            cout<<g->arcs[i][j]<<" ";
        cout<<endl;
    }
}
 
void Du(graph *g)                    ///统计每个顶点的度
{
    int i,j;
    for(i=0; i<g->vexnum; i++)
    {
        int amount=0;
        for(j=0; j<g->vexnum; ++j)
            if(g->arcs[i][j])
                ++amount;
        cout<<"顶点"<<g->vexs[i]<<"的度为"<<amount<<endl;
    }
}
 
void DFS(graph *g,int k)            ///DFS深度优先搜索
{
    int t,i;
    Stack s;
    InitStack(s);
    cout<<g->vexs[k]<<" ";
    visited[k]=true;
    push(s,k);
    while(s.base!=s.top)
    {
        t=top(s);
        if(i==g->vexnum)                              ///如果內层循环未找到没被访问的元素,则出栈
            pop(s);
        for(i=0; i<g->vexnum; i++)
        {
            if(g->arcs[t][i]==1&&visited[i]==false)   ///找出邻接矩阵第t+1行中第一个未被访问的元素
            {
                visited[i]=true;                      ///找到后标志为1,并输出,入栈
                cout<<g->vexs[i]<<" ";
                push(s,i);
                break;                                ///找到之后跳出內层循环,返回外层循环起始处,重复之前操作
            }
        }
    }
}
 
void BFS(graph *g, int k)            ///BFS广度优先搜索
{
    Queue q;
    InitQueue(q);
    visited[k]=true;
    cout<<g->vexs[k]<<" ";
    Q_push(q,k);
    while(q.Front!=q.Rear)
    {
        int t=Q_pop(q);
        for(int w=0; w<g->vexnum; w++)
        {
            if (g->arcs[t][w]!=0&&visited[w]==false)   ///找出邻接矩阵中t+1行所有未被访问的元素
            {
                visited[w]=true;                       ///每找到一个标志为1并入队列
                cout<<g->vexs[w]<<" ";
                Q_push(q,w);
            }
        }
    }
}
 
void Is_in_graph(graph *g,char ch)      ///查询图中是否存在顶点ch
{
    int i,j,k;
    for(i=0; i<g->vexnum; i++)          ///遍历顶点数组
        if(ch==g->vexs[i])
            break;
    if(i==g->vexnum)                    ///如果循环正常结束则i=g->vexnum,此时说明不存在该顶点
    {
        printf("无%c",ch);
        return ;
    }
    else
    {
        for(j=0; j<g->vexnum; j++)     ///如果存在,则将与顶点相关的边覆盖
            for(k=0; k<g->vexnum; k++)
            {
                if(j>=i&&k>=i)
                    g->arcs[j][k]=g->arcs[j+1][k+1];
                if(j>=i&&k<i)
                    g->arcs[j][k]=g->arcs[j+1][k];
                if(j<i&&k>=i)
                    g->arcs[j][k]=g->arcs[j][k+1];
            }
    }
    for(j=0; j<g->vexnum; j++)         ///覆盖该顶点
        if(j>=i)
            g->vexs[j]=g->vexs[j+1];
    g->vexnum--;
    cout<<"删除该顶点后剩余顶点为:\n";
    for(j=0; j<g->vexnum; j++)
        cout<<g->vexs[j]<<" ";
    cout<<endl;
    cout<<"删除后邻接矩阵为:\n";
    for(j=0; j<g->vexnum; j++)
    {
        for(k=0; k<g->vexnum; k++)
            cout<<g->arcs[j][k]<<" ";
        cout<<endl;
    }
    cout<<"从第一个顶点开始的DFS遍历为:\n";
    DFS(g,0);
}
 
 
void Is_connect(graph *g,int k)        ///利用DFS搜索的思想遍历图,每遍历一个顶点计数加一
{
    visited[k]=true;
    Count++;
    for(int i=0; i<g->vexnum; i++)
        if(g->arcs[k][i]==1&&visited[i]==false)
        {
            Is_connect(g,i);
        }
}
 
void main_menu()                      ///主菜单
{
    cout<<"-----------------------------------\n";
    cout<<"---------程序主菜单----------------\n";
    cout<<"-----------------------------------\n";
    cout<<"---------1图的创立及邻接矩阵-------\n";
    cout<<"---------2查询图中各顶点的度-------\n";
    cout<<"---------3DFS遍历图----------------\n";
    cout<<"---------4BFS遍历图----------------\n";
    cout<<"---------5查询顶点是否在图中-------\n";
    cout<<"---------6判断是否为连通图---------\n";
    cout<<"---------7退出---------------------\n";
    cout<<"---------回车键返回菜单------------\n";
    cout<<"-----------------------------------\n";
    cout<<"---------请选择:(1-7)--------------\n";
}
 
int main()
{
    int i,num;
    char ch;
    graph g;
    while(1)
    {
        system("cls");
        main_menu();
        scanf("%d",&num);
        system("cls");
        switch(num)                                   ///通过输入1-7调用不同的功能
        {
        case 1:
            printf("1图的创立及邻接矩阵\n\n");
            printf("请输入顶点的个数:");
            cin>>g.vexnum;
            cout<<endl;
            printf("请输入边的条数:");
            cin>>g.arcnum;
            printf("请输入各顶点:");
            for(i=0; i<g.vexnum; ++i)
                cin>>g.vexs[i];
            cout<<endl;
            printf("请输入各条边i-j:\n");
            Create(&g);
            printf("输入任意键返回主菜单:");
            system("pause");
            break;
        case 2:
            printf("2查询图中各顶点的度\n\n");
            Du(&g);
            printf("输入任意键返回主菜单:");
            system("pause");
            break;
        case 3:
            printf("3DFS遍历图\n\n");
            printf("请输入开始的顶点:");
            cin>>ch;
            cout<<endl;
            for(i=0;i<g.vexnum;i++)
                if(ch==g.vexs[i])
                    break;
            if(i>=g.vexnum)
            {
                printf("输入数字有误!");
                printf("输入任意键返回主菜单:");
                system("pause");
                break;
            }
            printf("从该点开始DFS搜索为:");
            DFS(&g,i);
            cout<<endl;
            memset(visited,0,sizeof(visited));           ///将访问标志数组初始化为0
            printf("输入任意键返回主菜单:");
            system("pause");
            break;
        case 4:
            printf("4BFS遍历图\n\n");
            printf("请输入开始的顶点:");
            cin>>ch;
            cout<<endl;
            for(i=0;i<g.vexnum;i++)
                if(ch==g.vexs[i])
                    break;
            if(i>=g.vexnum)
            {
                printf("输入数字有误!");
                printf("输入任意键返回主菜单:");
                system("pause");
                break;
            }
            printf("从该点开始BFS搜索为:");
            BFS(&g,i);
            cout<<endl;
            memset(visited,0,sizeof(visited));         ///将访问标志数组初始化为0
            printf("输入任意键返回主菜单:");
            system("pause");
            break;
        case 5:
            printf("5查询顶点是否在图中\n\n");
            printf("请输入要查询的顶点:");
            cin>>ch;
            cout<<endl;
            Is_in_graph(&g,ch);
            cout<<endl;
            memset(visited,0,sizeof(visited));        ///将访问标志数组初始化为0
            printf("输入任意键返回主菜单:");
            system("pause");
            break;
        case 6:
            printf("6判断是否为连通图\n\n");
            Is_connect(&g,0);
            if(Count==g.vexnum)
                printf("YES!");
            else
                printf("NO!");
            cout<<endl;
            Count=0;
            memset(visited,0,sizeof(visited));         ///将访问标志数组初始化为0
            printf("输入任意键返回主菜单:");
            system("pause");
            break;
        case 7:
            printf("退出成功");
            return 0;
        }
    }
}
 
 
 

3. 扩展

逆邻接表
在邻接表中对于有向图有一个很大的缺陷,如果我们比较关心顶点入度那么就需要遍历所有链表。为了避免这种情况出现,我们可以采用逆邻接表来存储,它存储的链表是别的顶点指向它。这样就可以快速求得顶点的入度。

如何对有向图的入度和出度都关心,那么久可以采取十字链表的方式。相当于每一个顶点对应两个链表,一个是它指向别的顶点,一个是别的顶点指向它。

Reference

https://www.zybuluo.com/guoxs/note/257430

https://blog.youkuaiyun.com/JYL1159131237/article/details/78504961

https://blog.youkuaiyun.com/JD_coder/article/details/79954592

SCADA|用KingSCADA实现设备台账的查询功能 以上为用KingSCADA实现设备台账的查询功能,另外还有一些细节功能,比如当点击增加按钮时弹出的信息窗口内的信息希望是在选中的某行信息,只要找到差不多的设备,修改个别参数即可,避免增加时弹出空白页,所有信息都需要填写。以上为实现设备台账查询的最简单实现,实际项目中可能会更复杂,你做过哪些设备台账或相关的功能,有比较好的创意或高难度功能方法,欢迎在留言区评论,或在交流群探讨,互通有无,共同进步。首先完成界面的组态工作,主要是通过查询按钮,查询SQLServer数据库的设备台账数据,然后填充到报表内。 阅读详情

相关推荐

【chatgpt代码系列】磁导航纠偏算法推导

例如,可以根据AGV偏离路径的方向和距离,计算出需要进行的修正角度和移动距离,然后通过控制算法实现对AGV的纠偏。具体来说,磁导航AGV的行驶是通过磁场传感器感知地面磁场信号,然后根据信号的强度和方向来确定AGV的位置和方向,进而控制AGV的行驶。但是,在实际应用中,由于地面磁场信号的变化和干扰等因素,磁导航AGV可能会出现偏离路径的情况,导致行驶不稳定甚至出现误差。磁导航AGV纠偏公式是通过对AGV行驶中偏离路径的原因进行分析,结合磁导航AGV的工作原理和控制算法,推导出来的。假设AGV的目标方向为。

少磊的博客 2807

数据结构—统计有向图中每个顶点的出度和入度(以邻接矩阵和邻接表两种方式实现)

一、邻接矩阵实现 假设不带权有向图采用邻接矩阵 g 存储,设计实现以下功能的算法: (1) 求出图中每个顶点的入度。 (2) 求出图中每个顶点的出度。 (3) 求出图中出度为0 的顶点数。 #include <stdio.h> #include <stdlib.h> #include <iostream> using namespace ...

qq_42319367的博客 4万+

csp-j/s

CSP-J/S 是中国计算机学会(CCF)主办的 ‌‌(Certified Software Professional Junior/Senior),是信息学奥赛(NOI)体系的入门级选拔考试,也是国内最具权威性的青少年编程能力认证之一。

gxyxxrYYDS的博客 2025

邻接矩阵求有向图各顶点的入度和出度 (图论基础)

要求一个有向图各顶点的入度和出度: 先用一个二维数组Edge存储表示邻接矩阵,输入文件中顶点的序号是从1开始,当输入一条有向边时,将Edge[u-1][v-1] = 1就得啦; 第i+1个顶点的出度等于邻接矩阵中第i行所有元素中元素值为1的个数,把第i行所有元素值累加起来,得到的结果也是该顶点的出度,同理,在计算第i+1个顶点的入度时,也只需要将第i列所有元素值累加起来就可以了; n

Epic丶玖遇 4万+

华为昇腾Atlas 200I DK A2实战:从开箱到运行首个AI应用

本文详细介绍了华为昇腾Atlas 200I DK A2开发板从开箱到运行首个AI应用的全过程。包括硬件准备、系统烧录、开发板连接方案、AI应用运行及性能优化技巧,帮助开发者快速上手部署AI项目,提升开发效率。

weixin_27038245的博客 590

【ComfyUI 基础教程】ComfyUI 局部重绘工作流教程

本篇指南将带你了解 ComfyUI 中的局部重绘工作流,并带你完成一个局部重绘的示例,以及遮罩编辑器的使用等。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 301

【数据结构】图的基本操作

数据结构 C++ 邻接矩阵基本操作

dreaming_creator的博客 1万+

goahead(嵌入式Web服务器)之文件传输篇

goahead文件上传原理: 使用html form即表单提交文件上传请求,web服务器核心处理接收客户端Post过来的文件数据(注意post的是二进制数据),最后,web服务器把接收到文件数据以二进制格式写到服务器本端存储系统。 goahead文件上传步骤: 1、创建upload.html文件,内容如下: <html> <head> <meta charset="utf-8"/> <title>Upload</title> </head&g

weixin_40732273的博客 3495

数据结构之以邻接矩阵实现图的基本操作(一)

1.图的基本定义 此处使用了字符作为顶点表存储的数据类型,整型作为边表 数据类型 typedef struct{ VertexType Vex[MaxVertexNum]; //顶点表 EdgeType Edge[MaxVertexNum][MaxVertexNum]; //邻接矩阵,边表 int vexnum,arcnum; //当前顶点数和弧数 }MGraph; 2....

超级超级的博客 3656

【OpenClaw从入门到精通】第48篇:企业“养虾”合规手册——审批备案+专网隔离+全流程管控(2026企业版)

随着OpenClaw在企业场景的规模化应用,“无审批部署、无备案运行、无隔离防护”已成为安全事件的主要诱因。本文基于启明星辰《OpenClaw类智能应用安全指引V0.1》,结合金融、能源行业头部企业落地实践,构建“审批-评估-备案-管控”全流程合规框架。核心内容包括四步审批备案流程、专网隔离部署规范、3套可直接复用的合规文档模板(使用申请单、安全评估报告、备案登记表),以及个人使用备案简化方案。通过本文,企业可建立“有据可依、有章可循”的OpenClaw管理体系,实现“专网部署、数据隔离、最小权限、全程监控

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 461

MIPI D-PHY IP 使用说明(一)

目录 前言 一、IP 特点 二、IP 可用性 三、IP 总览 四、IP 声明 五、IP 结构 六、IP 分流桥 模式 七、端口描述 1、PPI 接口信号 1、常规 PPI控制信号 2、发送模式 时钟通道 高速 PPI 信号 3、发送模式 时钟通道 逃逸模式PPI 信号 4、发送模式 数据通道 高速 PPI 信号 5、发送模式 数据通道 控制接口PPI 信号 6、发送模式 ...

记录所学,分享知识,结识挚友 2503

图的存储方式——邻接矩阵和邻接表

目录1. 基本概念2. 图的存储方式2.1 邻接矩阵2.2 邻接表3.两种方式的比较 1. 基本概念 1.什么是图? 图由顶点和边组成,表示为G(V,E),其中G表示一个图,V是图G中顶点的集合,E是图G中边的集合。根据边是否有方向,可分为有向图和无向图。 2. 邻接点 两结点之间通过边相连,则互为邻接点。如在上面的无向图中,(1,3),(2,5)等都为邻接点。 3. 顶点的度 顶点的度指的是与顶点v相连的边的数目。对于无向图来讲,只有度的概念,而对于有向图来讲,可分为入度和出度。入度是指向该

syh的技术记录 7124

Python re库【正则表达式操作库】全面讲解及代码示例

以下是Pythonre库的全面讲解,包含主要功能、常用方法及代码示例。完整代码和注释附后。正则表达式(Regular Expression)是用于匹配、查找、替换字符串的工具,通过特定语法定义模式。?{n}[...][a-z]A|B\d[0-9]\D\s\S\w\Wre从字符串匹配模式,返回Match对象或None。在字符串中第一个匹配项,返回Match对象或None。返回所有匹配项的。返回所有匹配项的Match对象)。替换匹配项,返回新字符串。根据模式分割字符串,返回列表。通过。

记录点滴 1161

【数据结构】第六章:图

【数据结构】第六章:图

Lenhart001的博客 414

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

图的四种存储方式(邻接矩阵、邻接表、十字链表、邻接多重表)

介绍了邻接矩阵、邻接表、十字链表以及邻接多重表,并详细记录了用于有向图的十字链表以及用于无向图的邻接多重表的画法。

kusunoki的博客 1万+

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

数据结构(45)图的四种存储方法:邻接矩阵法、邻接表法、十字链表、邻接多重表

图的存储必须要完整、准确地反映顶点集合边集的信息,根据不同图的结构和算法,采用不同的存储方式将对程序的效率产生相当大的影响,因此所选的存储结构应适合于欲求解的问题。 目录 1、邻接矩阵法 2、邻接表法 3、十字链表 4、邻接多重表 1、邻接矩阵法 所谓邻接矩阵存储,是指用一个一维数组存储图中顶点的信息,用一个二维数组存储图中边的信息(即各顶点之间的邻接关系),存储顶点之间邻接关系的二维数组称为邻接矩阵。 结点数为n的图G=(V,E)的邻接矩阵A是n*n的。将G的顶点编号为v1,v2,...,

李白 4045

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

邻接矩阵法和邻接表法(图的存储)

邻接矩阵存储法和邻接表法

Lyhdreamer的博客 1169

【数据结构】第六章图:图的基本概念;邻接矩阵法、邻接表法存储;十字链表、邻接多重表法存储

6.1.1 图的基本概念 一、图的定义 图 G 由顶点集 V 和边集 E 组成,记为 G = (V, E),其中 V(G) 表示图 G 中顶点的有限非空集;E(G) 表示图 G 中顶点之间的关系(边)集合。 若 V = {v1, v2, ..., vn},则用 |V| 表示图 G 中顶点的个数,也称图 G 的阶;E = {(u, v) | u∈V, v∈V}(边所在的两个顶点都是在顶点集内的),用 |E| 表示图 G 中边的条数。 G:Graph 英 [ɡræf] n.图表;图;曲线图; V.

weixin_37706349的博客 1291

图 、图的存储

点到点的距离——从顶点u出发到顶点v之间的最短路径若存在,则此路径的长度称为从u到v的距离。带权路径长度——当图是带权图时,一条路径上所有边的带权之和,称为该路径的带权路径长度。有向图中,若从顶点v到顶点w和从顶点w到v之间都有路径,则称这两个顶点是强连通的。边的权——在一个图中,每条边都可以标上具有某种含义的数值,该数值称为该边的权值。用|v|表示图g中顶点的个数,也称图g的阶,用|e|表示图g中边的条数。有向图O(|v|+|e|)无向图中,若从顶点v到顶点w有路径存在,则称v和w是连通的。

2401_88455976的博客 1622

图的五种存储结构及其C语言实现

文章目录???? 一、图的基本概念????二、图的基本存储结构????1.邻接矩阵法????1.1 存储结构????1.2 创建邻接矩阵????1.3 打印邻接矩阵存储的图????1.4 测试函数????2.邻接表法????2.1 存储结构????2.2 创建邻接表????2.3 打印邻接表法存储的图????2.4 测试函数????️3.十字链表法????️3.1 存储结构????3.2 创建十字链表????3.3 打印十字链表存储的图????3.4 测试函数????4.邻接多重表法????4.1 存储结构

CS_boy的博客 5255

第六章——图(2)图的存储及基本操作

文章目录一、邻接矩阵法1.邻接矩阵的表示法1.1定义1.2无向图邻接矩阵表示法1.3有向图邻接矩阵表示法1.4网及其邻接矩阵表示法1.5注意点总结2.邻接矩阵的建立2.1邻接矩阵的存储表示2.2邻接矩阵的优缺点二、邻接表法1.1邻接表的引入1.2图的邻接表存储结构定义1.3图的邻接表存储特点三、十字链表四、邻接多重表五、图的基本操作 前言: 图没有顺序存储结构,但可以借助二维数组来表示元素之间的关系。 ———数组表示法(邻接矩阵) 链式存储结构: ①邻接表 ②邻接多重表 ③十字链表 一、邻接矩阵法 1.邻接

weixin_42705436的博客 1111

图的基本概念|存储

图G由顶点集V和边集E组成,记为G=(V,E)其中V(G)表示图G中顶点的有限非空集;E(G)表示图G中顶点之间的关系(边)集合。若V={v1v2vnv1​v2​vn​),则用∣V∣|V|∣V∣表示图G中顶点的个数E={uv∣u∈Vv∈Vuv∣u∈Vv∈V),则用∣E∣|E|∣E∣表示图G中边的条数图的顶点集V一定非空,但边集E可以为空,此时图中只有顶点而没有边。有向图。

ChoSeitaku的博客 1414

十一、考研数据结构笔记——图的基本概念,图的基本性质,图的存储结构

本文主要诉说, 1、图的基本概念,常见的易混淆点,完全图,简单图,度,距离和连通分量, 2、图的四种存储方式,邻接矩阵,邻接表。 3、图的常见概念性考点

Mr_GYF的博客 5024

《数据结构与算法》——图的基本概念、存储方式及基本操作 总结

《数据结构与算法》——图的基本概念、存储方式及基本操作 总结 emmm,今天本来只准备做一道算法题的,可是发现它的解题思路是利用图的遍历算法,所以我就开始复习图的遍历算法,刚把基本思想写出来,准备用代码实现却发现,我对图的结构一无所知,所以我又来了复习图的基本概念。???? 目录 《数据结构与算法》——图的基本概念、存储方式及基本操作 总结 定义 图的存储结构 1. 邻接矩阵法 2. 邻接...

Kwzc4的博客 1466

数据结构复习指导之图的存储及基本操作

图算法的难度较大,主要掌握深度优先搜索与广度优先搜索。掌握图的基本概念及基本性质、图的存储结构(邻接矩阵、邻接表、邻接多重表和十字链表)及特性、存储结构之间的转化、基于存储结构上的各种遍历操作和各种应用(拓扑排序、最小生成树、最短路径和关键路径)等。 图的相关算法较多,通常只需掌握其基本思想和实现步骤,而实现代码不是重点。

心碎烤肠的博客 1717

数据结构之图的存储结构:邻接表法

图的存储结构:邻接表法邻接表法的定义:邻接表法的特点:邻接表法的代码定义:邻接表法与邻接矩阵法的对比: 邻接表法的定义: 例: 邻接表法的特点: ps: 1、存储空间 = 节点占用空间 + 边占用空间 2、邻接表的长度表示该顶点的出度 3、邻接表出现某一顶点的次数为该顶点的入度 邻接表法的代码定义: #define MaxVertexTypeNum 100 typedef char Ve...

千寻瀑 1676
上一篇: 串的模式匹配算法-暴力、KMP算法详解
下一篇: 深度优先搜索(DFS)与广度优先搜索(BFS)算法详解
小枫学IT
博客等级 码龄8年 7500粉丝 32原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

小枫学IT

如果觉得有用的话,可以支持一下

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

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

打赏作者

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

抵扣说明:

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

余额充值