C语言-数据结构 有向图拓扑排序TopologicalSort(邻接表存储)

news/2024/9/20 18:24:48 标签: c语言, 数据结构, 开发语言

        拓扑排序算法的实现还是比较简单的,我们需要用到一个顺序栈辅助,采用邻接表进行存储,顶点结点存储入度、顶点信息、指向邻接结点的指针,算法过程是:我们先将入度为0的顶点入栈,然后弹出栈顶结点,记录结点个数的count+1,然后遍历所有邻接结点将其入度都减1,如果有入度为0的顶点那么就进栈,当栈不为空就继续循环,最后通过判断弹出栈的元素个数count是否小于全部顶点数,如果小于说明有环,否则无环(即构成拓扑排序)。注意:拓扑排序的情况在邻接表确定的情况下是唯一的。看文字理解确实有点费劲,不过这个实现的代码不难,如果你理解了栈的情况下,那么直接跟着TopologicalSort代码走一遍很快就能领悟到拓扑排序的奥妙!

下面我们将创建一个有向无环图和一个有向有环图

有向无环图如下:

        d6763b7371eb46aeb833bc0a6e510754.png

代码中我们使用头插法进行创建有向无环图邻接表:

#define MAXVEX 8    // 最大顶点数
typedef char VertexType;  // 顶点类型,使用字符表示
typedef int EdgeType;     // 边上的权值类型,使用整数表示
// 边表结点
typedef struct EdgeNode {
    int adjvex;         // 顶点下标,表示该边的终点
    struct EdgeNode* next;  // 指向下一条边的指针
} EdgeNode;

// 顶点结点
typedef struct VertexNode {
    int in;
    VertexType data;     // 顶点数据
    EdgeNode* first;     // 指向该顶点的第一条边
} VertexNode, AdjList[MAXVEX];

// 图的邻接表表示
typedef struct {
    AdjList adjList;    // 顶点数组
    int numNodes;       // 图的顶点数
    int numEdges;       // 图的边数
} GraphAdjList;

//有向无环图邻接表创建
void CreateALGraphNotEncircle(GraphAdjList* G) {
    int i, j;
    EdgeNode* e = NULL;
    char str[] = "ABCDEFGH"; // 顶点数据

    // 初始化邻接表
    for (i = 0; i < G->numNodes; i++) {
        G->adjList[i].data = str[i]; // 设置顶点数据
        G->adjList[i].first = NULL;  // 边表初始化为空
    }
    G->adjList[0].in = 1;
    G->adjList[1].in = 1;
    G->adjList[2].in = 1;
    G->adjList[3].in = 1;
    G->adjList[4].in = 3;
    G->adjList[5].in = 0;
    G->adjList[6].in = 2;
    G->adjList[7].in = 1;
    // 添加边 A->B
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 1; // 邻接顶点序号为B
    e->next = G->adjList[0].first; // 插入到邻接表的第一个位置
    G->adjList[0].first = e;

    // 添加边 B->C->G
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 6; // 邻接顶点序号为G
    e->next = G->adjList[1].first;
    G->adjList[1].first = e;

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 2; // 邻接顶点序号为C
    e->next = G->adjList[1].first;
    G->adjList[1].first = e;

    // 添加边 C->D
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 3; // 邻接顶点序号为D
    e->next = G->adjList[2].first;
    G->adjList[2].first = e;

    // 添加边 D->H
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 7; // 邻接顶点序号为H
    e->next = G->adjList[3].first;
    G->adjList[3].first = e;

    // 添加边 F->A->E->G
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 6; // 邻接顶点序号为G
    e->next = G->adjList[5].first;
    G->adjList[5].first = e;

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 4; // 邻接顶点序号为E
    e->next = G->adjList[5].first;
    G->adjList[5].first = e;

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 0; // 邻接顶点序号为A
    e->next = G->adjList[5].first;
    G->adjList[5].first = e;

    // 添加边 G->E
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 4; // 邻接顶点序号为E
    e->next = G->adjList[6].first;
    G->adjList[6].first = e;

    // 添加边 H->E
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 4; // 邻接顶点序号为E
    e->next = G->adjList[7].first;
    G->adjList[7].first = e;

    // 打印邻接表(字母)和入度
    EdgeNode* p = NULL;
    printf("边结点按邻接顶点字母打印 (入度):\n");
    for (i = 0; i < G->numNodes; i++) {
        printf("%c (入度: %d)", G->adjList[i].data, G->adjList[i].in);
        p = G->adjList[i].first;
        while (p != NULL) {
            printf("->%c", G->adjList[p->adjvex].data); // 打印邻接顶点字母
            p = p->next;
        }
        printf("\n");
    }

    // 打印邻接表(下标)和入度
    printf("\n边结点按邻接下标打印 (入度):\n");
    for (i = 0; i < G->numNodes; i++) {
        printf("%c (入度: %d)", G->adjList[i].data, G->adjList[i].in);
        p = G->adjList[i].first;
        while (p != NULL) {
            printf("->%d", p->adjvex); // 打印邻接顶点下标
            p = p->next;
        }
        printf("\n");
    }
}

293e527c7a0e4844ab67b0cddd0a044f.png

        

        有向有环图如下:

52ca7d4673f2431daf71d429b3b21aee.png

代码中我们使用头插法进行创建有向有环图邻接表:

#define MAXVEX 8    // 最大顶点数
typedef char VertexType;  // 顶点类型,使用字符表示
typedef int EdgeType;     // 边上的权值类型,使用整数表示
// 边表结点
typedef struct EdgeNode {
    int adjvex;         // 顶点下标,表示该边的终点
    struct EdgeNode* next;  // 指向下一条边的指针
} EdgeNode;

// 顶点结点
typedef struct VertexNode {
    int in;
    VertexType data;     // 顶点数据
    EdgeNode* first;     // 指向该顶点的第一条边
} VertexNode, AdjList[MAXVEX];

// 图的邻接表表示
typedef struct {
    AdjList adjList;    // 顶点数组
    int numNodes;       // 图的顶点数
    int numEdges;       // 图的边数
} GraphAdjList;

//有向有环图邻接表创建
void CreateALGraphHaveEncircle(GraphAdjList* G) {
    int i, j;
    EdgeNode* e = NULL;
    char str[] = "ABCDEFGH"; // 顶点数据

    // 初始化邻接表
    for (i = 0; i < G->numNodes; i++) {
        G->adjList[i].data = str[i]; // 设置顶点数据
        G->adjList[i].first = NULL;  // 边表初始化为空
    }
    G->adjList[0].in = 1;
    G->adjList[1].in = 1;
    G->adjList[2].in = 1;
    G->adjList[3].in = 1;
    G->adjList[4].in = 3;
    G->adjList[5].in = 1;
    G->adjList[6].in = 2;
    G->adjList[7].in = 1;
    // 添加边 A->B
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 1; // 邻接顶点序号为B
    e->next = G->adjList[0].first; // 插入到邻接表的第一个位置
    G->adjList[0].first = e;

    // 添加边 B->C->G
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 6; // 邻接顶点序号为G
    e->next = G->adjList[1].first;
    G->adjList[1].first = e;

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 2; // 邻接顶点序号为C
    e->next = G->adjList[1].first;
    G->adjList[1].first = e;

    // 添加边 C->D
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 3; // 邻接顶点序号为D
    e->next = G->adjList[2].first;
    G->adjList[2].first = e;

    // 添加边 D->H
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 7; // 邻接顶点序号为H
    e->next = G->adjList[3].first;
    G->adjList[3].first = e;

    // 添加边 F->A->E

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 4; // 邻接顶点序号为E
    e->next = G->adjList[5].first;
    G->adjList[5].first = e;

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 0; // 邻接顶点序号为A
    e->next = G->adjList[5].first;
    G->adjList[5].first = e;

    // 添加边 G->E->F
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 5; // 邻接顶点序号为F
    e->next = G->adjList[6].first;
    G->adjList[6].first = e;

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 4; // 邻接顶点序号为E
    e->next = G->adjList[6].first;
    G->adjList[6].first = e;

    // 添加边 H->E
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 4; // 邻接顶点序号为E
    e->next = G->adjList[7].first;
    G->adjList[7].first = e;

    // 打印邻接表(字母)和入度
    EdgeNode* p = NULL;
    printf("边结点按邻接顶点字母打印 (入度):\n");
    for (i = 0; i < G->numNodes; i++) {
        printf("%c (入度: %d)", G->adjList[i].data, G->adjList[i].in);
        p = G->adjList[i].first;
        while (p != NULL) {
            printf("->%c", G->adjList[p->adjvex].data); // 打印邻接顶点字母
            p = p->next;
        }
        printf("\n");
    }

    // 打印邻接表(下标)和入度
    printf("\n边结点按邻接下标打印 (入度):\n");
    for (i = 0; i < G->numNodes; i++) {
        printf("%c (入度: %d)", G->adjList[i].data, G->adjList[i].in);
        p = G->adjList[i].first;
        while (p != NULL) {
            printf("->%d", p->adjvex); // 打印邻接顶点下标
            p = p->next;
        }
        printf("\n");
    }
}

ed961009ec2d4e2aa72f7a1fd78dbd7f.png

拓扑排序(TopologicalSort)算法,里面包括顺序栈的实现代码非常简洁:

int TopologicalSort(GraphAdjList GL) {
    EdgeNode* e;           // 边节点指针,用于遍历邻接表中的边
    int i, k, gettop;      // 迭代变量和临时变量
    int top = 0;           // 栈顶指针,初始值为0
    int count = 0;         // 已输出的节点计数
    int* stack;            // 存储拓扑排序的栈
    stack = (int*)malloc(sizeof(int) * MAXVEX); // 动态分配栈空间

    // 遍历所有节点,将入度为0的节点入栈
    for (i = 0; i < GL.numNodes; i++) {
        if (0 == GL.adjList[i].in) {
            stack[++top] = i; // 入栈,并更新栈顶指针
        }
    }

    printf("\n拓扑排序序列为:\n");

    // 当栈不为空时,进行拓扑排序
    while (top != 0) {
        gettop = stack[top--]; // 出栈操作,获取栈顶元素,并更新栈顶指针
        printf("%c -> ", GL.adjList[gettop].data); // 打印当前节点的值
        count++; // 已处理节点计数器加1

        // 遍历当前节点的所有邻接节点
        for (e = GL.adjList[gettop].first; e; e = e->next) {
            k = e->adjvex; // 获取邻接节点的索引
            if (!(--GL.adjList[k].in)) { // 将邻接节点的入度减1,并检查是否变为0
                stack[++top] = k; // 如果入度为0,将邻接节点入栈
            }
        }
    }

    // 如果已处理的节点数小于图中节点总数,说明存在环
    if (count < GL.numNodes) {
        return FALSE; // 拓扑排序失败
    }
    return TRUE; // 拓扑排序成功
}

完整代码(有向无环图、有环图的邻接表创建、TopologicalSort算法)

#include<stdio.h>
#include<stdlib.h>

#define MAXVEX 8    // 最大顶点数
#define TRUE 1 
#define FALSE 0

typedef char VertexType;  // 顶点类型,使用字符表示
typedef int EdgeType;     // 边上的权值类型,使用整数表示
typedef int Boolean;      // 布尔类型

// 边表结点
typedef struct EdgeNode {
    int adjvex;         // 顶点下标,表示该边的终点
    struct EdgeNode* next;  // 指向下一条边的指针
} EdgeNode;

// 顶点结点
typedef struct VertexNode {
    int in;
    VertexType data;     // 顶点数据
    EdgeNode* first;     // 指向该顶点的第一条边
} VertexNode, AdjList[MAXVEX];

// 图的邻接表表示
typedef struct {
    AdjList adjList;    // 顶点数组
    int numNodes;       // 图的顶点数
    int numEdges;       // 图的边数
} GraphAdjList;


//有向无环图邻接表创建
void CreateALGraphNotEncircle(GraphAdjList* G) {
    int i, j;
    EdgeNode* e = NULL;
    char str[] = "ABCDEFGH"; // 顶点数据

    // 初始化邻接表
    for (i = 0; i < G->numNodes; i++) {
        G->adjList[i].data = str[i]; // 设置顶点数据
        G->adjList[i].first = NULL;  // 边表初始化为空
    }
    G->adjList[0].in = 1;
    G->adjList[1].in = 1;
    G->adjList[2].in = 1;
    G->adjList[3].in = 1;
    G->adjList[4].in = 3;
    G->adjList[5].in = 0;
    G->adjList[6].in = 2;
    G->adjList[7].in = 1;
    // 添加边 A->B
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 1; // 邻接顶点序号为B
    e->next = G->adjList[0].first; // 插入到邻接表的第一个位置
    G->adjList[0].first = e;

    // 添加边 B->C->G
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 6; // 邻接顶点序号为G
    e->next = G->adjList[1].first;
    G->adjList[1].first = e;

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 2; // 邻接顶点序号为C
    e->next = G->adjList[1].first;
    G->adjList[1].first = e;

    // 添加边 C->D
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 3; // 邻接顶点序号为D
    e->next = G->adjList[2].first;
    G->adjList[2].first = e;

    // 添加边 D->H
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 7; // 邻接顶点序号为H
    e->next = G->adjList[3].first;
    G->adjList[3].first = e;

    // 添加边 F->A->E->G
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 6; // 邻接顶点序号为G
    e->next = G->adjList[5].first;
    G->adjList[5].first = e;

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 4; // 邻接顶点序号为E
    e->next = G->adjList[5].first;
    G->adjList[5].first = e;

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 0; // 邻接顶点序号为A
    e->next = G->adjList[5].first;
    G->adjList[5].first = e;

    // 添加边 G->E
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 4; // 邻接顶点序号为E
    e->next = G->adjList[6].first;
    G->adjList[6].first = e;

    // 添加边 H->E
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 4; // 邻接顶点序号为E
    e->next = G->adjList[7].first;
    G->adjList[7].first = e;

    // 打印邻接表(字母)和入度
    EdgeNode* p = NULL;
    printf("边结点按邻接顶点字母打印 (入度):\n");
    for (i = 0; i < G->numNodes; i++) {
        printf("%c (入度: %d)", G->adjList[i].data, G->adjList[i].in);
        p = G->adjList[i].first;
        while (p != NULL) {
            printf("->%c", G->adjList[p->adjvex].data); // 打印邻接顶点字母
            p = p->next;
        }
        printf("\n");
    }

    // 打印邻接表(下标)和入度
    printf("\n边结点按邻接下标打印 (入度):\n");
    for (i = 0; i < G->numNodes; i++) {
        printf("%c (入度: %d)", G->adjList[i].data, G->adjList[i].in);
        p = G->adjList[i].first;
        while (p != NULL) {
            printf("->%d", p->adjvex); // 打印邻接顶点下标
            p = p->next;
        }
        printf("\n");
    }
}

//有向有环图邻接表创建
void CreateALGraphHaveEncircle(GraphAdjList* G) {
    int i, j;
    EdgeNode* e = NULL;
    char str[] = "ABCDEFGH"; // 顶点数据

    // 初始化邻接表
    for (i = 0; i < G->numNodes; i++) {
        G->adjList[i].data = str[i]; // 设置顶点数据
        G->adjList[i].first = NULL;  // 边表初始化为空
    }
    G->adjList[0].in = 1;
    G->adjList[1].in = 1;
    G->adjList[2].in = 1;
    G->adjList[3].in = 1;
    G->adjList[4].in = 3;
    G->adjList[5].in = 1;
    G->adjList[6].in = 2;
    G->adjList[7].in = 1;
    // 添加边 A->B
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 1; // 邻接顶点序号为B
    e->next = G->adjList[0].first; // 插入到邻接表的第一个位置
    G->adjList[0].first = e;

    // 添加边 B->C->G
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 6; // 邻接顶点序号为G
    e->next = G->adjList[1].first;
    G->adjList[1].first = e;

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 2; // 邻接顶点序号为C
    e->next = G->adjList[1].first;
    G->adjList[1].first = e;

    // 添加边 C->D
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 3; // 邻接顶点序号为D
    e->next = G->adjList[2].first;
    G->adjList[2].first = e;

    // 添加边 D->H
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 7; // 邻接顶点序号为H
    e->next = G->adjList[3].first;
    G->adjList[3].first = e;

    // 添加边 F->A->E

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 4; // 邻接顶点序号为E
    e->next = G->adjList[5].first;
    G->adjList[5].first = e;

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 0; // 邻接顶点序号为A
    e->next = G->adjList[5].first;
    G->adjList[5].first = e;

    // 添加边 G->E->F
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 5; // 邻接顶点序号为F
    e->next = G->adjList[6].first;
    G->adjList[6].first = e;

    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 4; // 邻接顶点序号为E
    e->next = G->adjList[6].first;
    G->adjList[6].first = e;

    // 添加边 H->E
    e = (EdgeNode*)malloc(sizeof(EdgeNode));
    e->adjvex = 4; // 邻接顶点序号为E
    e->next = G->adjList[7].first;
    G->adjList[7].first = e;

    // 打印邻接表(字母)和入度
    EdgeNode* p = NULL;
    printf("边结点按邻接顶点字母打印 (入度):\n");
    for (i = 0; i < G->numNodes; i++) {
        printf("%c (入度: %d)", G->adjList[i].data, G->adjList[i].in);
        p = G->adjList[i].first;
        while (p != NULL) {
            printf("->%c", G->adjList[p->adjvex].data); // 打印邻接顶点字母
            p = p->next;
        }
        printf("\n");
    }

    // 打印邻接表(下标)和入度
    printf("\n边结点按邻接下标打印 (入度):\n");
    for (i = 0; i < G->numNodes; i++) {
        printf("%c (入度: %d)", G->adjList[i].data, G->adjList[i].in);
        p = G->adjList[i].first;
        while (p != NULL) {
            printf("->%d", p->adjvex); // 打印邻接顶点下标
            p = p->next;
        }
        printf("\n");
    }
}

int TopologicalSort(GraphAdjList GL) {
    EdgeNode* e;           // 边节点指针,用于遍历邻接表中的边
    int i, k, gettop;      // 迭代变量和临时变量
    int top = 0;           // 栈顶指针,初始值为0
    int count = 0;         // 已输出的节点计数
    int* stack;            // 存储拓扑排序的栈
    stack = (int*)malloc(sizeof(int) * MAXVEX); // 动态分配栈空间

    // 遍历所有节点,将入度为0的节点入栈
    for (i = 0; i < GL.numNodes; i++) {
        if (0 == GL.adjList[i].in) {
            stack[++top] = i; // 入栈,并更新栈顶指针
        }
    }

    printf("\n拓扑排序序列为:\n");

    // 当栈不为空时,进行拓扑排序
    while (top != 0) {
        gettop = stack[top--]; // 出栈操作,获取栈顶元素,并更新栈顶指针
        printf("%c -> ", GL.adjList[gettop].data); // 打印当前节点的值
        count++; // 已处理节点计数器加1

        // 遍历当前节点的所有邻接节点
        for (e = GL.adjList[gettop].first; e; e = e->next) {
            k = e->adjvex; // 获取邻接节点的索引
            if (!(--GL.adjList[k].in)) { // 将邻接节点的入度减1,并检查是否变为0
                stack[++top] = k; // 如果入度为0,将邻接节点入栈
            }
        }
    }

    // 如果已处理的节点数小于图中节点总数,说明存在环
    if (count < GL.numNodes) {
        return FALSE; // 拓扑排序失败
    }
    return TRUE; // 拓扑排序成功
}


int main() {
    GraphAdjList GL;
    GL.numNodes = MAXVEX;        // 设置顶点数
    //情况1有向无环图
    printf("测试有向无环图是否构成拓扑排序\n\n");
    CreateALGraphNotEncircle(&GL);
    if (TopologicalSort(GL)) {
        printf("\n能构成拓扑排序,图中无环\n");
    }
    else {
        printf("\n不能构成拓扑排序,图中有环\n");
    }printf("\n");
    //情况2有向有环图
    printf("测试有向有环图是否构成拓扑排序\n\n");
    CreateALGraphHaveEncircle(&GL);
    if (TopologicalSort(GL)) {
        printf("\n能构成拓扑排序,图中无环\n");
    }
    else {
        printf("\n不能构成拓扑排序,图中有环\n");
    }
    return 0;
}

运行结果:

有向无环图

ee7dd2f22d7c4bb78fb51476cf1f07f9.png

有向有环图(A->B->G->F是环)

c508b76c97c448eea47463546a49fd41.png

b2dd2e7a7b1544c68983f08af08cbfea.png

 


http://www.niftyadmin.cn/n/5667489.html

相关文章

python机器人编程——用手机web远程视频监控并控制小车驾驶(上篇vrep仿真)

目录 一、前言二、技术架构三、设备端实现四、服务控制端实现&#xff08;1&#xff09;摄像头服务模块&#xff08;2&#xff09;web服务器 五、web端实现&#xff08;1&#xff09;视频显示&#xff08;2&#xff09;驾驶盘的实现&#xff08;3&#xff09;心跳 六、总结七、…

青柠视频云——如何开启HTTPS服务?

前言 由于青柠视频云的语音对讲会使用到HTTPS服务&#xff0c;这里我们说一下如何申请证书以及如何在实战中部署并且配置使用。 一、证书申请 1、进入控制台 我们拿阿里云的免费个人证书为例&#xff0c;首先登录阿里云&#xff0c;在控制台找到数字证书管理服务&#xff0c;进…

【Kubernetes】常见面试题汇总(二十六)

目录 75.您认为公司如何处理服务器及其安装&#xff1f; 76.考虑一种情况&#xff0c;公司希望向具有各种环境的客户提供所有必需的分发。您认为他们如何以动态的方式实现这一关键目标&#xff1f; 特别说明&#xff1a;题目 69-113 属于【Kubernetes】的生产应用题。 75.您认…

第二百四十节 JPA教程 - JPA一对一连接列示例

JPA教程 - JPA一对一连接列示例 以下部分显示如何在JPA中为一对一映射设置连接列。 我们使用 JoinColumn 注释设置连接列。 OneToOneJoinColumn(name"DEPT_ID") private Department department;例子 下面的代码来自Department.java。 package cn.w3cschool.common…

条件编译代码记录

#include <iostream>// 基类模板 template<typename T> class Base { public:void func() {std::cout << "Base function" << std::endl;} };// 特化的子类 template<typename T> class Derived : public Base<T> { public:void…

EP21 Promise封装request请求

文件路径&#xff1a; E:/homework/uniappv3tswallpaper/utils/requset.js utils 文件夹中创建一个新的 request 文件。 const BaseUrl "https://tea.qingnian8.com/api/bizhi"export function request(config {}) {return new Promise((resolve, reject) > {…

8.sklearn-模型保存

文章目录 环境配置&#xff08;必看&#xff09;头文件引用1.保存模型代码工程运行结果生成文件 2.加载模型代码工程运行结果 环境配置&#xff08;必看&#xff09; Anaconda-创建虚拟环境的手把手教程相关环境配置看此篇文章&#xff0c;本专栏深度学习相关的版本和配置&…

2024年华为认证热门的5个方向

华为认证是ICT领域内广受认可的专业资格认证体系&#xff0c;它为不同层次的ICT专业人士提供了多样化的认证路径。华为认证体系主要分为三个等级&#xff1a;HCIA&#xff08;华为认证ICT工程师&#xff09;、HCIP&#xff08;华为认证ICT高级工程师&#xff09;、HCIE&#xf…