【C 数据结构】图的存储结构

news2024/11/23 8:01:29

文章目录

  • 【 1. 图的顺序存储结构 】
    • 1.1 基本原理
    • 1.2 顺序存储结构的 C 实现
  • 【 2. 图的链式存储结构 】
    • 2.1 图的临接表存储结构
      • 2.1.1 临接表的 基本原理
      • 2.1.2 临接表的 链表节点
      • 2.1.3 邻接表 各结构体的C实现
      • 2.1.4 临接表 计算顶点的出度和入度
        • 邻接表计算 无向图的出度和入度
        • 邻接表计算 有向图的出度和入度
    • 2.2 图的十字链表存储结构
      • 2.2.1 十字链表的 基本原理
      • 2.2.2 十字链表的 链表节点
      • 2.2.3 十字链表的 C实现
    • 2.3 图的临接多重表存储结构
      • 2.3.1 临接多重表的 基本原理
      • 2.3.2 临接多重表的 链表节点
      • 2.3.3 临接多重表的 C 实现
  • 【 3. 图的各存储结构的对比 】

【 1. 图的顺序存储结构 】

1.1 基本原理

  • 图可以采用顺序存储(也就是使用 数组 有效地存储),使用数组存储图时,需要使用 两个数组
    • 数据数组:存放图中顶点本身的数据(一维数组:存储图中各顶点本身数据,使用一维数组就足够了);
    • 临接矩阵(关系数组):用于存储各顶点之间的关系(二维数组:存储顶点之间的关系时,要记录每个顶点和其它所有顶点之间的关系,所以需要使用二维数组)。临接矩阵中值的确定如下:
      • 在使用二维数组存储 无权值 的图 中顶点之间的关系时,如果顶点之间 存在边或弧,在相应位置用 1 表示,反之用 0 表示
      • 如果使用二维数组存储 有权值 的图即网 中顶点之间的关系,顶点之间如果 有边或者弧的存在,在数组的相应位置存储其权值;反之用 0 表示
  • 数组 可用于存储 无向图有向图

例如:存储下图中的两张图时,除了存储图中各顶点本身具有的数据外,还需要使用二维数组存储任意两个顶点之间的关系。
在这里插入图片描述

  • 存储上图中的有向图(A)时,对应的二维数组如下图所示:
    例如,arcs[0][1] = 1 ,证明从 V1 到 V2 有弧存在。且通过该矩阵,可以很轻松得知各顶点的出度和入度,出度为该行非 0 值的和,入度为该列非 0 值的和。例如,V1 的出度为第一行两个 1 的和 为 2 ; V1 的入度为第一列中 1 的和 为 1 。所以 V1 的出度为 2 ,入度为 1 ,度为两者的和 3 。
    在这里插入图片描述
  • 存储上上图中的无向图(B)时,由于各顶点没有权值,所以如果两顶点之间有关联,相应位置记为 1 ;反之记为 0 。构建的二维数组如下图所示:
    在此二维数组中,每一行代表一个顶点,依次从 V1 到 V5 ,每一列也是如此。比如 arcs[0][1] = 1 ,表示 V1 和 V2 之间有边存在;而 arcs[0][2] = 0,说明 V1 和 V3 之间没有边。通过该矩阵,可以直观地判断出各个顶点的度,为该行(或该列)非 0 值的和。例如,第一行有两个 1,说明 V1 有两个边,所以度为 2。
    在这里插入图片描述

1.2 顺序存储结构的 C 实现

  • 在此程序中,构建无向网或有向网时,对于之间没有边或弧的顶点,相应的二阶矩阵中存放的是 0,目的只是为了方便查看运行结果。而实际上 如果顶点之间没有关联,则关系数组对应位置上的值应该是无穷大 ∞,以表示距离无穷远,根本无法到达
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define MAX_VERtEX_NUM 20  //顶点的最大个数
#define VertexType int     //顶点的数据类型
#define VRType int         //表示顶点之间的关系的变量类型
#define InfoType char      //存储弧或者边额外信息的指针变量类型
typedef enum { DG, DN, UDG, UDN }GraphKind;  //枚举图的 4 种类型:0无权有向、1无权无向、2有权有向、3有权无向

// 边/弧 的信息结构体,包括权值和附加其他信息
typedef struct {
    VRType adj;     //对于无权图,用 1 或 0 表示是否相邻;对于带权图,直接为权值。
    InfoType* info; //弧或边额外含有的信息指针
}ArcCell, AdjMatrix[MAX_VERtEX_NUM][MAX_VERtEX_NUM];

//图结构体
typedef struct {
    VertexType vexs[MAX_VERtEX_NUM];  //一维数据数组
    AdjMatrix arcs;                   //二维关系数组(邻接矩阵),每个元素为1个ArcCell信息结构体
    int vexnum, arcnum;               //图的顶点数和 弧/边 数
    GraphKind kind;                   //图的种类
}MGraph;

//根据顶点本身数据值,判断出顶点在二维数组中的位置
int LocateVex(MGraph* G, VertexType v) {
    int i = 0;
    //遍历一维数组,找到变量v
    for (; i < G->vexnum; i++) {
        if (G->vexs[i] == v) {
            break;
        }
    }
    //如果找不到,输出提示语句,返回-1
    if (i > G->vexnum) {
        printf("no such vertex.\n");
        return -1;
    }
    return i;
}
//构造无权有向图
void CreateDG(MGraph* G) {
    //输入图含有的顶点数和弧的个数
    scanf("%d,%d", &(G->vexnum), &(G->arcnum));
    //依次输入顶点本身的数据
    for (int i = 0; i < G->vexnum; i++) {
        scanf("%d", &(G->vexs[i]));
    }
    //初始化二维矩阵,全部归0,指针指向NULL
    for (int i = 0; i < G->vexnum; i++) {
        for (int j = 0; j < G->vexnum; j++) {
            G->arcs[i][j].adj = 0;
            G->arcs[i][j].info = NULL;
        }
    }
    //在二维数组中添加弧的数据
    for (int i = 0; i < G->arcnum; i++) {
        int v1, v2;
        //输入弧头和弧尾
        scanf("%d %d", &v1,&v2);
        //确定顶点位置
        int n = LocateVex(G, v1);
        int m = LocateVex(G, v2);
        //排除错误数据
        if (m == -1 || n == -1) {
            printf("no this vertex\n");
            return;
        }
        //将正确的弧的数据加入二维数组
        G->arcs[n][m].adj = 1;
    }
}
//构造无权无向图
void CreateDN(MGraph* G) {
    scanf("%d %d", &(G->vexnum), &(G->arcnum));
    for (int i = 0; i < G->vexnum; i++) {
        scanf("%d", &(G->vexs[i]));
    }
    for (int i = 0; i < G->vexnum; i++) {
        for (int j = 0; j < G->vexnum; j++) {
            G->arcs[i][j].adj = 0;
            G->arcs[i][j].info = NULL;
        }
    }
    for (int i = 0; i < G->arcnum; i++) {
        int v1, v2;
        scanf("%d,%d", &v1, &v2);
        int n = LocateVex(G, v1);
        int m = LocateVex(G, v2);
        if (m == -1 || n == -1) {
            printf("no this vertex\n");
            return;
        }
        G->arcs[n][m].adj = 1;
        G->arcs[m][n].adj = 1;//无向图的二阶矩阵沿主对角线对称
    }
}
//构造有权有向网
void CreateUDG(MGraph* G) {
    scanf("%d %d", &(G->vexnum), &(G->arcnum));
    for (int i = 0; i < G->vexnum; i++) {
        scanf("%d",&(G->vexs[i]));
    }
    for (int i = 0; i < G->vexnum; i++) {
        for (int j = 0; j < G->vexnum; j++) {
            G->arcs[i][j].adj = 0;
            G->arcs[i][j].info = NULL;
        }
    }
    for (int i = 0; i < G->arcnum; i++) {
        int v1, v2, w;
        scanf("%d %d %d", &v1, &v2, &w);
        int n = LocateVex(G, v1);
        int m = LocateVex(G, v2);
        if (m == -1 || n == -1) {
            printf("no this vertex\n");
            return;
        }
        G->arcs[n][m].adj = w;
    }
}
//构造有权无向网
void CreateUDN(MGraph* G) {
    scanf("%d %d", &(G->vexnum), &(G->arcnum));
    for (int i = 0; i < G->vexnum; i++) {
        scanf("%d", &(G->vexs[i]));
    }
    for (int i = 0; i < G->vexnum; i++) {
        for (int j = 0; j < G->vexnum; j++) {
            G->arcs[i][j].adj = 0;
            G->arcs[i][j].info = NULL;
        }
    }
    for (int i = 0; i < G->arcnum; i++) {
        int v1, v2, w;
        scanf("%d %d %d", &v1, &v2, &w);
        int m = LocateVex(G, v1);
        int n = LocateVex(G, v2);
        if (m == -1 || n == -1) {
            printf("no this vertex\n");
            return;
        }
        G->arcs[n][m].adj = w;
        G->arcs[m][n].adj = w;//矩阵对称
    }
}
void CreateGraph(MGraph* G) {
    //选择图的类型
    scanf("%d", &(G->kind));
    //根据所选类型,调用不同的函数实现构造图的功能
    switch (G->kind) 
    {
	case DG:
		return CreateDG(G);
		break;
	case DN:
		return CreateDN(G);
		break;
	case UDG:
		return CreateUDG(G);
		break;
	case UDN:
		return CreateUDN(G);
		break;
	default:
		break;
	}
}
//输出函数
void PrintGrapth(MGraph G)
{
    for (int i = 0; i < G.vexnum; i++)
    {
        for (int j = 0; j < G.vexnum; j++)
        {
            printf("%d ", G.arcs[i][j].adj);
        }
        printf("\n");
    }
}

int main()
{
    MGraph G;//建立一个图的变量,对象
    CreateGraph(&G);//调用创建函数,传入地址参数,进行初始化
    PrintGrapth(G); //输出图的二阶矩阵
    return 0;
}
  • 例如,使用上述程序存储下图 (a)的有向网时,存储的两个数组如下图 (b)所示:
    在这里插入图片描述
//输入下列数据:
2
6 10
1
2
3
4
5
6
1 2 5
2 3 4
3 1 8
1 4 7
4 3 5
3 6 9
6 1 3
4 6 6
6 5 1
5 4 5

在这里插入图片描述

【 2. 图的链式存储结构 】

  • 通常,图更多的是采用链表存储,具体的存储方法有 3 种,分别是邻接表、邻接多重表和十字链表。

2.1 图的临接表存储结构

2.1.1 临接表的 基本原理

  • 如果图中的两个点相互连通,即通过其中一个顶点,可直接找到另一个顶点,则称它们互为 邻接点 邻接 指的是图中顶点之间有边或者弧的存在。邻接表 可用于存储 无向图有向图
  • 邻接表的实现方式:
    • 给图中的各个顶点独自建立一个链表,用 首元节点存储该顶点,用链表中 其他节点存储各自的临接点
    • 同时,为了便于管理这些链表,通常会将所有 链表的头节点存储到数组中(也可以用链表存储), 各链表在存储顶点的临接点时,仅需存储该邻接点位于数组中的下标 即可。
  • 例如,存储下图 a 所示的有向图,其对应的邻接表如下图 b 所示:
    以顶点 V1 为例,与其相关的邻接点分别为 V2 和 V3,因此存储 V1 的链表中存储的是 V2 和 V3 在数组中的位置下标 1 和 2。
    在这里插入图片描述
  • 对于具有 n 个顶点和 e 条边的无向图,邻接表中需要存储 n 个头结点和 2e 个链表中的结点。在图中边或者弧稀疏的时候,使用邻接表(所有链表中的节点总数为 n + 2 e n+2e n+2e)要比图的顺序存储结构中的邻接矩阵(数组大小为 n 2 n^2 n2) 更加节省空间。

2.1.2 临接表的 链表节点

  • 存储各顶点的节点结构分为两部分,数据域和指针域。data 数据域用于存储顶点数据信息,next 指针域用于指向下一个临接点,如下图所示:
    在这里插入图片描述
  • 在实际应用中,除了上图这种节点结构外,对于用临接表存储网(边或弧存在权)结构,还需要节点存储权的值,因此需使用下图中的节点结构:adjvex为邻接点在数组中的下标,next指针指向下一个节点,info 表示 adjvex 所代表的顶点与临接表表头所代表顶点的权值。
    在这里插入图片描述

2.1.3 邻接表 各结构体的C实现

  • 邻接表 各结构体的 C 实现:
#define  MAX_VERTEX_NUM 20	//顶点的最大个数
#define  VertexType int		//顶点的数据类型
#define  InfoType int		//弧或者边包含的信息的类型

//各顶点的临接点结构体
typedef struct ArcNode{
    int adjvex;//邻接点在数组中的下标
    struct ArcNode * nextarc;//指向下一个邻接点
    InfoType * info;//信息域
}ArcNode;

//图的顶点结构体
typedef struct VNode{
    VertexType data;   //顶点的数据域
    ArcNode * firstarc;//指向邻接点的指针
}VNode,AdjList[MAX_VERTEX_NUM];//存储各链表头结点的数组

//图结构体
typedef struct {
    AdjList vertices;  //图中顶点的数组
	int vexnum,arcnum; //图中顶点数和边/弧数
    int kind; //图的种类
}ALGraph;

2.1.4 临接表 计算顶点的出度和入度

邻接表计算 无向图的出度和入度
  • 使用邻接表 计算 无向图 中顶点的入度和出度只需从数组中 找到该顶点然后统计此链表中节点的数量 即可
邻接表计算 有向图的出度和入度
  • 使用 邻接表存储 有向图 时,通常各个顶点的链表中存储的都是以该顶点为弧尾的邻接点,因此 通过统计各顶点链表中的节点数量, 只能计算出该顶点的出度,而无法计算该顶点的入度
  • 对于利用邻接表求某顶点的入度,有两种方式:
    ① 遍历整个邻接表中的节点,统计除了该顶点外所有的链表中与该顶点所在数组位置下标相同的节点数量,即为该顶点的入度;
    ② 建立一个 逆邻接表,该表中的各顶点链表专门用于存储以此顶点为弧头的所有顶点在数组中的位置下标。
    比如说,建立一张2.1.1中图 a 对应的逆邻接表,如下图所示:
    以 V1 为例,其他顶点中能到达 V1 的顶点为V4,故 顶点V1的链表中第二个节点存储的是 V4 所在数组的下标3。
    在这里插入图片描述

2.2 图的十字链表存储结构

2.2.1 十字链表的 基本原理

  • 十字链表法 仅适用于 存储有向的,即 有向图有向网。不仅如此,十字链表法还 解决了邻接表不方便计算有向图顶点入度的问题
  • 十字链表存储有向图(网)的方式与邻接表有一些相同,都 以图(网)中各顶点为首元节点 建立多条链表,同时为了便于管理,还将所有链表的首元节点存储到同一数组(或链表)中。
  • 十字链表实质上就是为每个顶点建立两个链表,分别存储以该顶点为弧头的所有顶点和以该顶点为弧尾的所有顶点 。对于各个链表中节点来说,由于表示的都是该顶点的出度或者入度,因此 十字链表中的节点没有先后次序之分

2.2.2 十字链表的 链表节点

  • 十字链表中用于存储顶点的 顶点结构体 节点如下图所示:
    • data :用于存储该顶点中的数据;
    • firstin 指针:用于连接以当前顶点为弧头的其他顶点构成的链表;
    • firstout 指针:用于连接以当前顶点为弧尾的其他顶点构成的链表;
      在这里插入图片描述
  • 十字链表中 弧结构体 节点如下图所示:
    • tailvex: 存储该弧弧尾的顶点位于数组中的下标;
    • headvex:存储该弧弧头的顶点位于数组中的下标;
    • hlink 指针:指向下一个与该弧弧头相同的弧的节点;
    • tlink 指针:指向下一个与该弧弧尾相同的弧的节点;
    • info 指针(可选):用于存储与该顶点相关的信息,例如两顶点之间的权值;
      在这里插入图片描述
  • 例如,用十字链表存储下图 a 中的有向图,存储状态如下图 b 所示:
    • 以顶点 V1 为例,以 V1 为弧头的弧只有 V4→V1。因此,V1 的 firstin 指针指向 V4→V1 这条弧,而在 剩下的弧中没有与 V4→V1 这条弧弧头相同的节点,故 V4→V1 这条弧的 hlink 指针指向空。如图中红色颜色所示。
    • 同样,以 V1 为弧尾的弧有 V1→V2 和 V1→V3(不区分先后次序)这两条弧。因此,V1 的 firstout 指针指向 V1→V2 这条弧的节点, V1→V2 这条弧的 tlink 指针指向 V1→V3 这条弧, V1→V3 这条弧的 tlink 指针指向空。如图中棕色颜色所示。

在这里插入图片描述

2.2.3 十字链表的 C实现

#define  MAX_VERTEX_NUM 20
#define  InfoType int//图中弧包含信息的数据类型
#define  VertexType int

//链表中的其他节点结构体
typedef struct ArcBox 
{
    int tailvex, headvex;//弧尾、弧头对应顶点在数组中的位置下标
    struct ArcBox* hlik, * tlink;//分别指向弧头相同和弧尾相同的下一个弧
    InfoType* info;//存储弧相关信息的指针
}ArcBox;

//链表的首元节点结构体
typedef struct VexNode 
{
    VertexType data;//顶点的数据域
    ArcBox* firstin, * firstout;//指向以该顶点为弧头和弧尾的链表首个结点
}VexNode;

//图结构体
typedef struct 
{
    VexNode xlist[MAX_VERTEX_NUM];//存储顶点的一维数组
    int vexnum, arcnum;//记录图的顶点数和弧数
}OLGraph;

int LocateVex(OLGraph* G, VertexType v)
{
    int i = 0;
    //遍历一维数组,找到变量v
    for (; i < G->vexnum; i++) {
        if (G->xlist[i].data == v) {
            break;
        }
    }
    //如果找不到,输出提示语句,返回 -1
    if (i >= G->vexnum) {
        printf("no such vertex.\n");
        return -1;
    }
    return i;
}
//构建十字链表函数
void CreateDG(OLGraph* G) {
    //输入有向图的顶点数和弧数
    scanf("%d,%d", &(G->vexnum), &(G->arcnum));
    //使用一维数组存储各顶点数据,初始化指针域为NULL
    for (int i = 0; i < G->vexnum; i++) {
        scanf("%d", &(G->xlist[i].data));
        G->xlist[i].firstin = NULL;
        G->xlist[i].firstout = NULL;
    }
    //构建十字链表
    for (int k = 0; k < G->arcnum; k++) {
        int v1, v2;
        scanf("%d,%d", &v1, &v2);
        //确定v1、v2在数组中的位置下标
        int i = LocateVex(G, v1); //弧的尾的下标
        int j = LocateVex(G, v2); //弧的头的下标  i→j
        //建立弧的其他节点
        ArcBox* p = (ArcBox*)malloc(sizeof(ArcBox));
        p->tailvex = i;
        p->headvex = j;
        //采用头插法插入新的p结点
        p->tlink = G->xlist[i].firstout;
        p->hlik =  G->xlist[j].firstin;
        G->xlist[j].firstin = G->xlist[i].firstout = p;
    }
}

2.3 图的临接多重表存储结构

2.3.1 临接多重表的 基本原理

  • 问题背景
    无向图的存储可以使用邻接表,但在实际使用时,如果想对图中某顶点进行实操(修改或删除),由于邻接表中存储该顶点的节点有两个,因此需要操作两个节点。
    而无向图的另一种存储结构—— 邻接多重表 可以提高无向图中操作顶点的效率
  • 邻接多重表 仅适用于 存储无向的,即无向图或无向网。
  • 邻接多重表存储无向图的方式,可看作是邻接表和十字链表的结合。同邻接表和十字链表存储图的方法相同,都是独自为图中各顶点建立一张链表,存储各顶点的节点作为各链表的首元节点,同时为了便于管理将各个首元节点存储到一个数组中。

2.3.2 临接多重表的 链表节点

  • 邻接多重表采用与邻接表相同的首元节点结构, 顶点结构体 节点 如下图所示:
    • data:存储此顶点的数据;
    • firstedge:指针域,指向同该顶点有直接关联的存储其他顶点的节点。
      在这里插入图片描述
  • 临接多重表的各链表中 边结构体 节点如下图所示:
    • mark:标志域,用于标记此节点是否被操作过,例如在对图中顶点做遍历操作时,为了防止多次操作同一节点,mark 域为 0 表示还未被遍历;mark 为 1 表示该节点已被遍历;
    • ivex 和 jvex:数据域,分别存储图中各边两端的顶点所在数组中的下标;
    • ilink:指针域,指向下一个以 ivex 为顶点的边结构体;
    • jlink:指针域,指向下一个以 jvex 为顶点的边结构体;
    • info:指针域,用于存储与该顶点有关的其他信息,比如无向网中各边的权;
      在这里插入图片描述
  • 如果我们想使用邻接多重表存储下图 a 中的无向图,则与之对应的邻接多重表如下图 b 所示:
    • 以顶点 V1 为例,以 V1 为顶点的边有 V1-V2 和 V1-V4(不区分先后次序)这两条边。因此,V1 的 firstedge 指针指向 V1-V2 这条边的节点, V1-V2 这条边的 ilink 指针指向 V1-V4 这条边的节点, V1-V4 这条边的 ilink 指针指向空。如图中棕色颜色所示。

在这里插入图片描述

2.3.3 临接多重表的 C 实现

#define MAX_VERTEX_NUM 20                   //图中顶点的最大个数
#define VertexType int                      //图顶点的数据类型
#define InfoType int                        //边含有的信息域的数据类型
typedef enum { unvisited, visited }VisitIf; //边标志域

//边结构体
typedef struct EBox {
    VisitIf mark;                  //标志域
    int ivex, jvex;                //边的两个顶点在数组中的位置下标
    struct EBox* ilink, * jlink;   //分别指向与ivex、jvex相关的下一个边
    InfoType* info;                //边包含的其它的信息域的指针
}EBox;

//顶点的首元节点结构体
typedef struct VexBox {
    VertexType data;               //顶点数据域
    EBox* firstedge;               //顶点相关的第一条边的指针域
}VexBox;

//图结构体
typedef struct {
    VexBox adjmulist[MAX_VERTEX_NUM]; //图中顶点的数组
    int vexnum, degenum;              //图中顶点的个数和边的个数
}AMLGraph;

【 3. 图的各存储结构的对比 】

图的存储结构可存储的图的类型核心实现优点缺点
数组有向、无向一维数组存储顶点数据,二维数组存储各顶点间的关系。\\
临接表有向、无向一维数组存储各顶点的结构体(顶点结构体存储该顶点的数据和指向该顶点临接点结构体的指针);
临接点结构体中包括该临接点的数据下标和指向下一个临接点结构体的指针。
\不方便计算有向图中顶点的入度;
不方便操作无向图的顶点
十字链表有向一维数组存储各顶点的结构体(顶点结构体存储各顶点的数据和两个分别指向以该顶点为弧头和弧尾的弧结构体的指针);
弧结构体中存储该弧弧头和弧尾的数据下标、两个分别指向下一个与该弧弧头或弧尾相同的弧的弧结构体。
解决了邻接表不方便计算有向图顶点入度的问题。不能存储无向的
临接多重表无向一维数组存储各顶点的结构体(顶点结构体存储各顶点的数据和指向以该顶点为端点的边结构体的指针);
边结构体存储该边是否被操作过的标记位、该边两个顶点的数据下标、两个分别指向下一个与该边顶点相同的边结构体。
解决了临接表不方便操作无向图顶点的问题。不能存储有向的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1634449.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript+C#云LIS系统源码JQuery+EasyUI+Bootstrap云LIS系统应用于哪些行业领域?区域云LIS系统源码

JavaScriptC&#xff03;云LIS系统源码JQueryEasyUIBootstrap云LIS系统应用于哪些行业领域&#xff1f;区域云LIS系统源码 云LIS是为区域医疗提供临床实验室信息服务的计算机应用程序&#xff0c;可协助区域内所有临床实验室相互协调并完成日常检验工作&#xff0c;对区域内的检…

应用在电位器中的磁性旋转编码器芯片

电位器是具有三个引出端、阻值可按某种变化规律调节的电阻元件。电位器通常由电阻体和可移动的电刷组成。当电刷沿电阻体移动时&#xff0c;在输出端即获得与位移量成一定关系的电阻值或电压。电位器既可作三端元件使用也可作二端元件使用。后者可视作一可变电阻器&#xff0c;…

MATLAB中功率谱密度计算pwelch函数使用详解

MATLAB中功率谱密度计算pwelch函数使用详解 目录 前言 一、pwelch函数简介 二、pwelch函数参数说明 三、pxx pwelch(x)示例 四、[pxx,f]pwelch(x,window,noverlap,nfft,fs)示例 四、[pxx,f] pwelch(x,window,noverlap,nfft,fs,freqrange,spectrumtype)示例 五、多通道功…

CI/CD:基于kubernetes的Gitlab搭建

1. 项目目标 &#xff08;1&#xff09;熟悉使用k8s环境搭建Gitlab &#xff08;2&#xff09;熟练应用Gitlab基本配置 2. 项目准备 2.1. 规划节点 主机名 主机IP 节点规划 k8s-master 10.0.1.1 kube_master k8s-node1 10.0.1.2 kube_node k8s-node2 10.0.1.3 k…

Java 源码 - DelayQueue 源码解析

文章目录 1. 整体设计1.1 类注释1.2、类图1.3 延迟队列的属性1.4 DelayQueue 的主要方法1.4.1 offer 添加元素1.4.2 take 取出元素1.4.3 poll 取出元素 1. 整体设计 DelayQueue 延迟队列底层使用的是锁的能力&#xff0c;比如说要在当前时间往后延迟 5 秒执行&#xff0c;那么…

UnityWebGL获取话筒实时数据

看了木子李大佬的数字人https://digital.lkz.fit/之后&#xff0c;我也想搞一个&#xff0c;于是开始研究起来&#xff0c;先从WebGL录音开始&#xff0c;一共试了三个插件&#xff0c;个个都有问题…… 1、UnityWebGLMicrophone 用起来没啥问题&#xff0c;但是只能录音&#…

【百度Apollo】探索自动驾驶:Apollo 新版本 Beta 全新的Dreamview+,便捷灵活更丰富

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《linux深造日志》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引入一、Dreamview介绍二、Dreamview 新特性2.1、基于模式的多场景——流程更简洁地图视角调节&#xff1a;调试流…

创业两个月以来我的思想感悟和日志记录

截止目前&#xff0c;出来创业差不多两个月时间了&#xff0c;写篇文章记录总结一下吧&#xff0c;给大家讲讲这两个来&#xff0c;我的感受和心路历程吧。 先来说说我为什么要出来创业&#xff0c;在如今市场环境这么差的情况下&#xff0c;很多身边的朋友都找不到工作&#…

财报解读:汽车销售基本盘,承载了特斯拉的“高科技梦”

“即使外星人明天绑架了我&#xff0c;特斯拉也要解决掉自动驾驶问题。”在自动驾驶业务布局上&#xff0c;马斯克的决心坚定。 不过&#xff0c;想要做好自动驾驶&#xff0c;马斯克可能还需解决最紧要的业绩问题。日前&#xff0c;特斯拉正式发布了其2024年第一季度财报&…

salesforce 如何访问lwc组件

访问lwc有哪些途径呢? Action ButtonTabAura use lwc(拓展)如何区分是新建页面还是编辑页面 Action Button xml文件中要配置tab<?xml version"1.0" encoding"UTF-8"?> <LightningComponentBundle xmlns"http://soap.sforce.com/2006/04/…

AI小白使用Macbook Pro安装llama3与langchain初体验

1. 背景 AI爆火了2年有余&#xff0c;但我仍是一个AI小白&#xff0c;最近零星在学&#xff0c;随手记录点内容供自己复习。 上次在Macbook Pro上安装了Stable Diffusion&#xff0c;体验了本地所心所欲地生成各种心仪的图片&#xff0c;完全没有任何限制的惬意。今天想使用M…

Pandas数据可视化 - Matplotlib、Seaborn、Pandas Plot、Plotly

可视化工具介绍 让我们一起探讨Matplotlib、Seaborn、Pandas Plot和Plotly这四个数据可视化库的优缺点以及各自的适用场景。这有助于你根据不同的需求选择合适的工具。 1. Matplotlib 优点: 功能强大&#xff1a;几乎可以用于绘制任何静态、动画和交互式图表。高度可定制&a…

《HCIP-openEuler实验指导手册》1.6 Apache静态资源配置

知识点 常用用途&#xff1a; 软件仓库镜像及提供下载服务&#xff1a; 配置步骤 删除网站主目录中的文件&#xff08;本实验机目录为/home/source ip为192.168.12.137 端口为81&#xff09; cd /home/source rm -rf *在主目录中新建6个文件夹如下图 mkdir test{1..6}新建…

深入浅出一文图解Vision Mamba(ViM)

文章目录 引言&#xff1a;Mamba第一章&#xff1a;环境安装1.1安装教程1.2问题总结1.3安装总结 第二章&#xff1a;即插即用模块2.1模块一&#xff1a;Mamba Vision代码&#xff1a;models_mamba.py运行结果 2.2模块二&#xff1a;MambaIR代码&#xff1a;MambaIR运行结果 第三…

【MyBatis】进阶使用 (动态SQL)

动态SQL \<if>\<trim>\<where>\<set>\<foreach>\<include> 在填写表单时&#xff0c;有些数据是非必填字段&#xff08;例如性别&#xff0c;年龄等字段&#xff09;&#xff0c;那就需要在接收到参数时判断&#xff0c;根据参数具体的情况…

ROS2 学习笔记(二)常用小工具

1. rqt_console #启动 ros2 run rqt_console rqt_console日志级别&#xff1a;Fatal --> Error --> Warn --> Info --> Debug #修改允许发布的日志级别 ros2 run <package_name> <executable_name> --ros-args --log-level WARN2. launch文件 ROS2中…

TMS320F280049 EQEP模块--QCAP(3)

功能框图 如上图所示&#xff0c;QCAP的核心功能块是CTCU捕获事件控制单元。CTCU以CAPCLK为时钟来计数&#xff0c;在UPEVNT事件时QCTMR值会锁存到QCPRD并重置。此时软件可以读取该QCPRD来计算速度。 速度计算公式 公式 QCAP主要为了在低速模式下使用&#xff0c;速度计算公…

49. 【Android教程】HTTP 使用详解

在你浏览互联网的时候&#xff0c;绝大多数的数据都是通过 HTTP 协议获取到的&#xff0c;也就是说如果你想要实现一个能上网的 App&#xff0c;那么就一定会和 HTTP 打上交道。当然 Android 发展到现在这么多年&#xff0c;已经有很多非常好用&#xff0c;功能非常完善的网络框…

无人机+低空经济:释放中国低空经济动力的必要条件

无人机与低空经济的结合&#xff0c;对于释放中国低空经济动力具有重要的意义。无人机作为低空经济的重要组成部分&#xff0c;可以为低空经济提供新的动力和发展方向。以下是无人机与低空经济结合释放中国低空经济动力的必要条件&#xff1a; 1. 无人机技术的不断发展和创新&a…

InternVL——GPT-4V 的开源替代方案

您的浏览器不支持 video 标签。 在人工智能领域&#xff0c;InternVL 无疑是一颗耀眼的新星。它被认为是最接近 GPT-4V 表现的可商用开源模型&#xff0c;为我们带来了许多惊喜。 InternVL 具备强大的功能&#xff0c;不仅能够处理图像和文本数据&#xff0c;还能精妙地理解…