图的遍历之深度优先遍历与广度优先遍历

算法详解——图的深度优先遍历和广度优先遍历 图数据中的深度优先遍历算法和广度优先遍历算法 阅读详情

一、简介

1、对于树而言,因为根结点只有一个,并且所有的结点都只有一个双亲,所以对于树的遍历相对容易一点。但是对于图的遍历,就不那么容易了,因为它的任一顶点都可以和其余的所有顶点相邻接,因此极有可能存在重复走过某个顶点或漏了某个顶点的遍历过程。对于图的遍历,通常有两种遍历次序方案,分别是深度优先遍历和广度优先遍历。

二、深度优先遍历

1、深度优先遍历(DepthFirstSearch),也称为深度优先搜索,简称为DFS。它的思想简单来说就是按照一定的顺序挨个查找,找完一个,继续找下一个。

2、如下图所示,假如从顶点A开始,该如何遍历各个顶点?可以根绝右手原则:在没有碰到重复顶点的情况下,分叉路口始终是向右手边走,每路过一个顶点就做一个记号。


  那么现在从顶点A开始,依据右手原则,那么开始遍历顶点B,依据右手原则遍历顶点C,依据右手原则遍历顶点D,依据右手原则遍历顶点E,依据右手原则遍历顶点F,然后发现顶点A已经被标记过了,依据右手原则已行不通,那么只能遍历顶点G,然后发现顶点B也已经被标记过了,且顶点D也被标记过了,那么只能遍历顶点H,然后发现顶点D和E也都被标记过了,前方已经没有顶点可被遍历了,那么回退到顶点G,也是已经没有可遍历的顶点了,继续回退到顶点F,继续回退到顶点E,顶点D,然后发现顶点I没遍历,那么遍历顶点I,然后没有可遍历的顶点了,回退到顶点D,继续回退到顶点C、B,最后回退到顶点A,那么遍历完毕。

3、从上面的遍历过程来看,深度优先遍历其实就是一个递归的过程。而且整个遍历过程就像是一棵树的前序遍历。如下图,蓝色的路线就是上面遍历的一个顺序,红色顶点就是在各个分叉路径的选择项,但是根据右手原则,是不会选择遍历它们的;那么对于蓝色线路这棵树来说就是对该树的前序遍历。


4、对于无向图采用邻接矩阵存储方式的深度优先遍历完整代码如下:

/***************************************************************************/
/**               图的遍历之深度优先遍历(邻接矩阵存储)                         **/
/***************************************************************************/

#include <stdio.h>

#define GRAPH_MAX_VERTEX_SIZE 100           // 最大顶点数
#define TRUE 1
#define FALSE 0

typedef char VertexType;     // 顶点类型
typedef int EdgeType;        // 代表是否有边的类型值
typedef int Boolean;

Boolean visited[GRAPH_MAX_VERTEX_SIZE];    // 遍历标志数组

typedef struct Graph
{
	VertexType vexs[GRAPH_MAX_VERTEX_SIZE];           // 顶点表
	EdgeType arc[GRAPH_MAX_VERTEX_SIZE][GRAPH_MAX_VERTEX_SIZE];      // 邻接矩阵
	int numVertexs, numEdges;            // 图中当前的顶点数和边数
}Graph;

/**
 * 建立无向图的邻接矩阵表示
 * @param graph:指向图结构的指针
 */
void CreateGraph(Graph *graph)
{
	int i, j, k;

	printf("输入顶点数和边数,分别用空格分隔:");
	scanf("%d %d", &(graph->numVertexs), &(graph->numEdges));          // 接收输入的顶点数和边数

	for(i = 0; i < graph->numVertexs; i++)                             // 读入顶点信息,建立顶点表
	{
	    printf("输入第%d个顶点信息:", i + 1);
        fflush(stdin);                                                 // 清空键盘输入缓冲区
		scanf("%c", &(graph->vexs[i]));
	}

	for(i = 0; i < graph->numVertexs; i++)
	{
		for(j = 0; j < graph->numVertexs; j++)
		{
			graph->arc[i][j] = 0;	                           // 邻接矩阵初始化
		}
	}

	for(k = 0; k < graph->numEdges; k++)                               // 读入numEdges条边,建立邻接矩阵
	{
		printf("输入边(vi,vj)上的下标i,下标j,分别用空格分隔:");
		fflush(stdin);                                                 // 清空键盘输入缓冲区
		scanf("%d %d", &i, &j);
		graph->arc[i][j] = 1;
		graph->arc[j][i] = graph->arc[i][j];                           // 因为是无向图,矩阵对称
	}
}
/**
 * 邻接矩阵的深度优先遍历递归算法
 * @param graph:图结构
 * @param i:遍历到第i个顶点
 */
void DFS(Graph graph, int i)
{
    int j;
    visited[i] = TRUE;                   // 标志已经被遍历过了
    printf("%c ", graph.vexs[i]);

    for(j = 0; j < graph.numVertexs; j++)
    {
        // 如果与第i个顶点相邻接且该顶点还没有被遍历过,则对邻接顶点递归调用
        if(graph.arc[i][j] == 1 && !visited[j])
        {
            DFS(graph, j);
        }
    }
}

/**
 * 邻接矩阵的深度优先遍历操作
 * @param graph:图结构
 */
void DFSTraverse(Graph graph)
{
    int i;
    for(i = 0; i < graph.numVertexs; i++)
    {
        // 初始所有顶点都是未被遍历过的状态
        visited[i] = FALSE;
    }
    for(i = 0; i < graph.numVertexs; i++)
    {
        // 对未访问过的顶点调用DFS,若是连通图,只会执行一次
        if(!visited[i])
        {
            DFS(graph, i);
        }
    }
}

int main()
{
    Graph graph;

    CreateGraph(&graph);
    DFSTraverse(graph);
    return 0;
}
5、对于无向图采用邻接表的存储方式的深度优先遍历完整代码如下:

/***************************************************************************/
/**                 图的遍历之深度优先遍历(邻接表存储)                         **/
/***************************************************************************/

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

#define GRAPH_MAX_VERTEX_SIZE 100                    // 最大顶点数
#define TRUE 1
#define FALSE 0

typedef char VertexType;                             // 顶点类型
typedef int Boolean;

Boolean visited[GRAPH_MAX_VERTEX_SIZE];              // 顶点访问标志数组

// 边表结点结构定义
typedef struct EdgeNode
{
	int adjvex;                                      // 邻接点域,存储该顶点在顶点表中对应的下标
	struct EdgeNode *next;                           // 链表指针域,指向下一个邻接点
}EdgeNode;

// 顶点表结点结构定义
typedef struct VertexNode
{
	VertexType data;                                 // 顶点域,存储顶点信息
	EdgeNode *firstEdge;                             // 边表头指针
}VertexNode;

// 图结构定义
typedef struct Graph
{
	VertexNode adjList[GRAPH_MAX_VERTEX_SIZE];
	int numVertexs, numEdges;                        // 图中当前顶点数和边数
}Graph;

/**
 * 建立无向图的邻接表表示
 * @param graph:指向图结构的指针
 */
void CreateGraph(Graph *graph)
{
    int i, j, k;
    EdgeNode *e;

    printf("输入无向图的顶点数和边数,分别用空格分隔:");
    scanf("%d %d", &(graph->numVertexs), &(graph->numEdges));  // 接收输入的顶点数和边数,并赋值

    // 读入顶点信息,建立顶点表
    for(i = 0; i < graph->numVertexs; i++)
    {
        printf("输入第%d个顶点信息:", i + 1);
        fflush(stdin);             // 清空键盘输入缓冲区
        scanf("%c", &(graph->adjList[i].data));
        graph->adjList[i].firstEdge = NULL;     // 将该顶点指向第一个边表结点的指针置为空
    }

    // 建立边表
    for(k = 0; k < graph->numEdges; k++)
    {
        printf("输入边(vi, vj)的两个顶点在顶点数组中的下标i、下标j,分别用空格分隔:");
        fflush(stdin);           // 清空键盘输入缓冲区
        scanf("%d %d", &i, &j);
        e = (EdgeNode *)malloc(sizeof(EdgeNode));  // 生成边表结点
        if(!e)
        {
            exit(1);
        }
        e->adjvex = j;     // 邻接序号为j
        e->next = graph->adjList[i].firstEdge;   // 将边表结点e的next指针指向当前顶点上firstEdge指针指向的边表结点
        graph->adjList[i].firstEdge = e;         // 将当前顶点的firstEdge指针指向边表结点e,头插法

        // 因为是无向图,所以需要将(vi, vj)表示的边反过来再执行一遍,设置下标为j的顶点的边表
        e = (EdgeNode *)malloc(sizeof(EdgeNode));
        if(!e)
        {
            exit(1);
        }
        e->adjvex = i;
        e->next = graph->adjList[j].firstEdge;
        graph->adjList[j].firstEdge = e;
    }
}

/**
 * 邻接表的深度优先遍历递归算法
 * @param graph:图结构
 * @param i:遍历到第i个顶点
 */
void DFS(Graph graph, int i)
{
    EdgeNode *e;
    visited[i] = TRUE;                    // 标志该顶点已经被访问过了
    printf("%c ", graph.adjList[i].data);

    e = graph.adjList[i].firstEdge;
    while(e)
    {
        if(!visited[e->adjvex])
        {
            DFS(graph, e->adjvex);    // 对访问的邻接顶点进行递归调用
        }
        e = e->next;
    }
}

/**
 * 邻接表的深度优先遍历操作
 * @param graph:图结构
 */
void DFSTraverse(Graph graph)
{
    int i;

    // 初始化顶点访问标志数组,所有顶点都还没有被访问过
    for(i = 0; i < graph.numVertexs; i++)
    {
        visited[i] = FALSE;
    }
    for(i = 0; i < graph.numVertexs; i++)
    {
        // 对未访问过的顶点调用DFS,若是连通图,只会执行一次
        if(!visited[i])
        {
            DFS(graph, i);
        }
    }
}
int main()
{
    Graph graph;

    CreateGraph(&graph);
    DFSTraverse(graph);
    return 0;
}

三、广度优先遍历

1、广度优先遍历(BreadthFirstSearch),又称为广度优先搜索,简称BFS。

2、如果以找钥匙的例子来讲,运用深度优先遍历意味着要先彻底查找完一个房间再开始另一个房间的搜索。但可能钥匙放在沙发地下等犄角旮旯的可能性极低,因此运用新的方案:先看看钥匙是否放在各个房间的显眼位置,如果没有,再看看各个房间的抽屉有没有。这样逐步扩大查找的范围的方式称为广度优先遍历。如下图:广度优先遍历类似于树的层序遍历。


3、要实现对图的广度遍历,可以利用队列来实现。如下图,出队列的顺序就是广度优先遍历的顺序。


4、对于无向图采用邻接矩阵存储方式的广度优先遍历完整代码如下:

/***************************************************************************/
/**               图的遍历之广度优先遍历(邻接矩阵存储)                        **/
/***************************************************************************/

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

#define GRAPH_MAX_VERTEX_SIZE 100           // 图的最大顶点数
#define TRUE 1
#define FALSE 0

typedef char VertexType;     // 图的顶点类型
typedef int QueueElemType;   // 队列元素数据类型
typedef int EdgeType;        // 代表是否有边的类型值
typedef int Boolean;

Boolean visited[GRAPH_MAX_VERTEX_SIZE];    // 遍历标志数组

// 定义图结构
typedef struct Graph
{
	VertexType vexs[GRAPH_MAX_VERTEX_SIZE];           // 顶点表
	EdgeType arc[GRAPH_MAX_VERTEX_SIZE][GRAPH_MAX_VERTEX_SIZE];      // 邻接矩阵
	int numVertexs, numEdges;            // 图中当前的顶点数和边数
}Graph;

// 定义队列元素结构
typedef struct QueueNode
{
    QueueElemType data;
    struct QueueNode *next;
}QueueNode;

// 定义队列结构
typedef struct
{
    QueueNode *front;  // 对头指针
    QueueNode *rear;   // 对尾指针
}LinkQueue;

/**
 * 初始化一个空队列,初始化成功返回TRUE,否则返回FALSE
 * @param queue:指向队列结构的指针
 */
Boolean initLinkQueue(LinkQueue *queue)
{
    QueueNode *head;

    // 生成头结点
    head = (QueueNode *)malloc(sizeof(QueueNode));

    if(!head)
    {
        return FALSE;
    }

    head->next = NULL;
    queue->front = queue->rear = head;
    return TRUE;
}

/**
 * 入队列,入队列成功返回TRUE,否则返回FALSE
 * @param queue:指向队列结构的指针
 * @param data:入队列元素
 */
Boolean insertLinkQueue(LinkQueue *queue, QueueElemType data)
{
    QueueNode *p;

    p = (QueueNode *)malloc(sizeof(QueueNode));
    if(!p)
    {
        return FALSE;
    }
    p->data = data;
    p->next = NULL;

    queue->rear->next = p;
    queue->rear = p;

    return TRUE;
}

/**
 * 出队列,空队列的情况下出队列返回FALSE,否则返回TRUE
 * @param queue:指向队列结构的指针
 * @param data:保存成功出队列的元素
 */
Boolean deleteLinkQueue(LinkQueue *queue, QueueElemType *data)
{
    QueueNode *p;

    if(queue->front == queue->rear)
    {
        return FALSE;
    }

    p = queue->front->next;
    *data = p->data;

    queue->front->next = p->next;
    if(p == queue->rear)
    {
        queue->rear = queue->front;
    }
    free(p);
    return TRUE;
}

/**
 * 建立无向图的邻接矩阵表示
 * @param graph:指向图结构的指针
 */
void CreateGraph(Graph *graph)
{
	int i, j, k;

	printf("输入顶点数和边数,分别用空格分隔:");
	scanf("%d %d", &(graph->numVertexs), &(graph->numEdges));          // 接收输入的顶点数和边数

	for(i = 0; i < graph->numVertexs; i++)                             // 读入顶点信息,建立顶点表
	{
	    printf("输入第%d个顶点信息:", i + 1);
        fflush(stdin);                                                 // 清空键盘输入缓冲区
		scanf("%c", &(graph->vexs[i]));
	}

	for(i = 0; i < graph->numVertexs; i++)
	{
		for(j = 0; j < graph->numVertexs; j++)
		{
			graph->arc[i][j] = 0;	                           // 邻接矩阵初始化
		}
	}

	for(k = 0; k < graph->numEdges; k++)                               // 读入numEdges条边,建立邻接矩阵
	{
		printf("输入边(vi,vj)上的下标i,下标j,分别用空格分隔:");
		fflush(stdin);                                                 // 清空键盘输入缓冲区
		scanf("%d %d", &i, &j);
		graph->arc[i][j] = 1;
		graph->arc[j][i] = graph->arc[i][j];                           // 因为是无向图,矩阵对称
	}
}

/**
 * 邻接矩阵的广度优先遍历操作
 * @param graph:图结构
 */
void BFSTraverse(Graph graph)
{
    int i, j;
    QueueElemType q;
    Boolean bole;
    LinkQueue queue;

    for(i = 0; i < graph.numVertexs; i++)
    {
        visited[i] = FALSE;   // 初始化遍历标志数组
    }
    bole = initLinkQueue(&queue);   // 初始化队列
    if(!bole) {
        exit(1);   // 队列初始化失败
    }
    // 循环每一个顶点
    for(i = 0; i < graph.numVertexs; i++)
    {
        // 第i个顶点还未被访问过
        if(!visited[i])
        {
            visited[i] = TRUE;   //标志该顶点已经被访问过了
            printf("%c ", graph.vexs[i]);
            bole = insertLinkQueue(&queue, i);   // 入队列
            if(!bole)
            {
                exit(1);    // 入队列失败
            }
            // 队列不为空,成功出队列
            while(deleteLinkQueue(&queue, &q))
            {
                for(j = 0; j < graph.numVertexs; j++)
                {
                    // 其他顶点与该顶点存在边且还没被访问过
                    if(graph.arc[q][j] == 1 && !visited[j])
                    {
                        visited[j] = TRUE;        // 标记该顶点已经被访问过了
                        printf("%c ", graph.vexs[j]);
                        bole = insertLinkQueue(&queue, j);
                        if(!bole)
                        {
                            exit(1);    // 入队列失败
                        }
                    }
                }
            }
        }
    }
}

int main()
{
    Graph graph;

    CreateGraph(&graph);
    BFSTraverse(graph);
    return 0;
}
五、对于无向图采用邻接表存储方式的广度优先遍历完整代码如下:
/***************************************************************************/
/**                 图的遍历之广度优先遍历(邻接表存储)                        **/
/***************************************************************************/

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

#define GRAPH_MAX_VERTEX_SIZE 100                    // 最大顶点数
#define TRUE 1
#define FALSE 0

typedef char VertexType;                             // 顶点类型
typedef int QueueElemType;   // 队列元素数据类型
typedef int Boolean;

Boolean visited[GRAPH_MAX_VERTEX_SIZE];    // 遍历标志数组

// 边表结点结构定义
typedef struct EdgeNode
{
	int adjvex;                                      // 邻接点域,存储该顶点在顶点表中对应的下标
	struct EdgeNode *next;                           // 链表指针域,指向下一个邻接点
}EdgeNode;

// 顶点表结点结构定义
typedef struct VertexNode
{
	VertexType data;                                 // 顶点域,存储顶点信息
	EdgeNode *firstEdge;                             // 边表头指针
}VertexNode;

// 图结构定义
typedef struct Graph
{
	VertexNode adjList[GRAPH_MAX_VERTEX_SIZE];
	int numVertexs, numEdges;                        // 图中当前顶点数和边数
}Graph;

// 定义队列元素结构
typedef struct QueueNode
{
    QueueElemType data;
    struct QueueNode *next;
}QueueNode;

// 定义队列结构
typedef struct
{
    QueueNode *front;  // 对头指针
    QueueNode *rear;   // 对尾指针
}LinkQueue;

/**
 * 建立无向图的邻接表表示
 * @param graph:指向图结构的指针
 */
void CreateGraph(Graph *graph)
{
    int i, j, k;
    EdgeNode *e;

    printf("输入无向图的顶点数和边数,分别用空格分隔:");
    scanf("%d %d", &(graph->numVertexs), &(graph->numEdges));  // 接收输入的顶点数和边数,并赋值

    // 读入顶点信息,建立顶点表
    for(i = 0; i < graph->numVertexs; i++)
    {
        printf("输入第%d个顶点信息:", i + 1);
        fflush(stdin);             // 清空键盘输入缓冲区
        scanf("%c", &(graph->adjList[i].data));
        graph->adjList[i].firstEdge = NULL;     // 将该顶点指向第一个边表结点的指针置为空
    }

    // 建立边表
    for(k = 0; k < graph->numEdges; k++)
    {
        printf("输入边(vi, vj)的两个顶点在顶点数组中的下标i、下标j,分别用空格分隔:");
        fflush(stdin);           // 清空键盘输入缓冲区
        scanf("%d %d", &i, &j);
        e = (EdgeNode *)malloc(sizeof(EdgeNode));  // 生成边表结点
        if(!e)
        {
            exit(1);
        }
        e->adjvex = j;     // 邻接序号为j
        e->next = graph->adjList[i].firstEdge;   // 将边表结点e的next指针指向当前顶点上firstEdge指针指向的边表结点
        graph->adjList[i].firstEdge = e;         // 将当前顶点的firstEdge指针指向边表结点e,头插法

        // 因为是无向图,所以需要将(vi, vj)表示的边反过来再执行一遍,设置下标为j的顶点的边表
        e = (EdgeNode *)malloc(sizeof(EdgeNode));
        if(!e)
        {
            exit(1);
        }
        e->adjvex = i;
        e->next = graph->adjList[j].firstEdge;
        graph->adjList[j].firstEdge = e;
    }
}

/**
 * 初始化一个空队列,初始化成功返回TRUE,否则返回FALSE
 * @param queue:指向队列结构的指针
 */
Boolean initLinkQueue(LinkQueue *queue)
{
    QueueNode *head;

    // 生成头结点
    head = (QueueNode *)malloc(sizeof(QueueNode));

    if(!head)
    {
        return FALSE;
    }

    head->next = NULL;
    queue->front = queue->rear = head;
    return TRUE;
}

/**
 * 入队列,入队列成功返回TRUE,否则返回FALSE
 * @param queue:指向队列结构的指针
 * @param data:入队列元素
 */
Boolean insertLinkQueue(LinkQueue *queue, QueueElemType data)
{
    QueueNode *p;

    p = (QueueNode *)malloc(sizeof(QueueNode));
    if(!p)
    {
        return FALSE;
    }
    p->data = data;
    p->next = NULL;

    queue->rear->next = p;
    queue->rear = p;

    return TRUE;
}

/**
 * 出队列,空队列的情况下出队列返回FALSE,否则返回TRUE
 * @param queue:指向队列结构的指针
 * @param data:保存成功出队列的元素
 */
Boolean deleteLinkQueue(LinkQueue *queue, QueueElemType *data)
{
    QueueNode *p;

    if(queue->front == queue->rear)
    {
        return FALSE;
    }

    p = queue->front->next;
    *data = p->data;

    queue->front->next = p->next;
    if(p == queue->rear)
    {
        queue->rear = queue->front;
    }
    free(p);
    return TRUE;
}

/**
 * 邻接表的广度优先遍历操作
 * @param graph:图结构
 */
void BFSTraverse(Graph graph)
{
    int i, j;
    QueueElemType q;
    Boolean bole;
    EdgeNode *e;
    LinkQueue queue;

    for(i = 0; i < graph.numVertexs; i++)
    {
        // 初始化遍历标志数组
        visited[i] = FALSE;
    }
    bole = initLinkQueue(&queue);   // 初始化队列
    if(!bole)
    {
        exit(1); // 初始化队列失败
    }
    for(i = 0; i < graph.numVertexs; i++)
    {
        if(!visited[i])
        {
            visited[i] = TRUE;
            printf("%c ", graph.adjList[i].data);
            bole = insertLinkQueue(&queue, i);    // 入队列
            if(!bole)
            {
                exit(1); // 入队列失败
            }
            // 队列不为空,成功出队列
            while(deleteLinkQueue(&queue, &q))
            {
                e = graph.adjList[q].firstEdge;  // 当前结点指向边表结果的头指针
                while(e)
                {
                    j = e->adjvex;
                    // 未被访问过
                    if(!visited[j])
                    {
                        visited[j] = TRUE;
                        printf("%c ", graph.adjList[j].data);
                        bole = insertLinkQueue(&queue, j);    // 入队列
                        if(!bole)
                        {
                            exit(1); // 入队列失败
                        }
                    }
                    // 指向下一个邻接点
                    e = e->next;
                }
            }
        }
    }
}

int main()
{
    Graph graph;

    CreateGraph(&graph);
    BFSTraverse(graph);
    return 0;
}


大话数据结构-图的深度优先遍历和广度优先遍历 数据结构中图的深度优先遍历、广度优先遍历定义,邻接矩阵、邻接表、逆邻接表、十字链表、邻接多重表和边集数组的深度优先遍历实现和广度优先遍历实现。 阅读详情

相关推荐

【数据结构】图的遍历方法 深度优先遍历和广度优先遍历

图的遍历方法 深度优先遍历和广度优先遍历 接着上次的文章“图的构建(邻接链表法)”,邻接链表法构建图相对来说比较简单,并且遍历起来也相对简单,但是要是动态添加图的节点和图的边,则是实在不方便,不过现在不管那么多,今天的主题是遍历。  - 有另外一种图的构建方法,叫做十字链表法,插入删除比较方便,但是相对来说比较复杂,改天闲着木事的再搞。(其实主要原因是因为三四年前写的代码,现在翻出来了,现成的

sundong_d的专栏 2万+

数据结构实验报告三

1.输入指定的边数和顶点数建立图,并输出深度优先遍历和广度优先遍历的结果。 1)问题描述:在主程序中设计一个简单的菜单,分别调用相应的函数功能: 1…图的建立 2…深度优先遍历图 3…广度优先遍历图 0…结束 2)实验要求:在程序中定义下述函数,并实现要求的函数功能: CreateGraph(): 按从键盘的数据建立图 DFSGrahp():深度优先遍历图 ...

小wal的博客 7292

别再只会用QTcpSocket了!手把手教你用QSslSocket为你的Qt网络应用加上SSL/TLS加密(附完整代码示例)

本文详细介绍了如何将Qt网络应用从QTcpSocket迁移到QSslSocket,实现SSL/TLS加密传输。通过对比API差异、解析核心机制和提供完整代码示例,帮助开发者快速掌握安全网络编程技巧,有效防范数据窃听和中间人攻击等安全风险。

weixin_30654583的博客 400

7.3图的遍历(深度优先)-理论

7.3图的遍历(深度优先)-理论

IT1995的博客 5891

接口调试必看:status显示canceled的3种常见原因及修复方法

本文深度解析了接口调试中status显示canceled的三种核心原因:网络层中断(如请求超时)、应用层逻辑主动取消(如请求竞态、组件卸载)以及用户交互与浏览器行为。文章提供了从诊断到修复的系统性方案,包括分析Network Timing、使用Axios CancelToken、优化请求策略与性能,帮助开发者从根本上解决这一常见问题。

bb456的博客 937

STM32L051低功耗模式下LPUART的使用

STM32L0系列低功耗UART配置代码清单及注释,大家可参考学习使用。

嵌入式工程师 2104

图(二)——图的遍历

邻接矩阵的深度优先搜索递归遍历,非递归,广度优先搜索遍历

在校生 2998

2025反爬虫革命:京东商品接口的动态指纹认证与量子加密传输方案

在2025年,全球电商API接口面临的安全威胁呈现指数级增长:京东构建了基于硬件、软件、行为三重维度的设备指纹模型:京东构建了基于BB84+E91混合协议的量子密钥中继网络:

FB13713612741的博客 1649

关于搜索(DFS 、BFS)

深度优先搜索(DFS):     思想:             首先以一个未被访问过的顶点作为开始顶点,沿当前顶点的边走到未访问过的顶点;当没有未访问过的顶点时,则回溯到上一个顶点,继续试探访问别的顶点,直到所有的顶点都被访问过。 完整代码: #include&lt;stdio.h&gt; int a[10],book[10],n; void dfs(int step) { int ...

仙女的博客 291

Stable-Baselines3性能优化:多环境训练对比指南(DummyVecEnv vs SubprocVecEnv)

本文深入对比了Stable-Baselines3中DummyVecEnv与SubprocVecEnv两种向量化环境的性能差异与应用场景。DummyVecEnv适用于轻量级、步进快的环境,调试友好且开销低;而SubprocVecEnv则通过真正的多进程并行,能显著加速计算密集型环境的训练。文章通过基准测试与决策树,指导开发者根据环境计算成本、CPU核心数等关键因素做出最优选择,以实现训练效率最大化。

weixin_29063979的博客 147

Calibre 3Dstack --每日一个命令day27【overlap】(3-27)

本文介绍了Calibre3Dstack中overlap命令的使用方法。该命令用于检查两个已放置层之间的重叠量是否符合要求,支持设置检查名称、层类型、堆叠范围、检查方向等参数。关键参数包括:-constraint指定重叠约束条件,-exact控制百分比精度,-by_area切换为面积检查模式,-intersection报告相交区域。检查结果可通过RVE选项定制显示方式,适用于3D堆叠设计中的层间重叠验证场景。

u013620135的博客 112

数据结构-图

1.实现图的邻接矩阵和邻接表的存储 图.h的头文件 #ifndef Map #define Map #include<iostream> #include<malloc.h> #include<cstring> using namespace std; #define MAXV 100 //定义最大顶点数 #define INF 65535 //用65535来表示无穷大 typedef char InfoTpye; //以下定义邻接矩阵类型..

白泓的博客 734

YOLO车辆测距、车辆识别与单目测距

YOLO(You Only Look Once)是一种实时物体检测系统,能够识别视频或图像中的多个对象,并确定其位置。结合车辆识别与单目测距技术,YOLO可以用于交通监控、自动驾驶等应用场景,通过单个摄像头实现车辆的识别与距离测量。YOLO结合单目测距技术,在多个应用领域展现出巨大的潜力与灵活性。其实时性和准确性为智能交通、自动驾驶等领域提供了强有力的技术支持。

走向CTO的路上... 1698

C++实现图的深度优先遍历和广度优先遍历

图的深度优先遍历 图的深度优先遍历参考 图的深度优先遍历 参考 1、https://blog.youkuaiyun.com/todd911/article/details/9191481 2、https://blog.youkuaiyun.com/weixin_42109012/article/details/94199335

JMW1407的博客 1万+

华为OD机试真题 Java&Go 实现【优雅子数组】【100%通过率】【2022.11 Q4 新题】

如果一个数组中出现次数最多的元素出现大于等于K次,被称为K -优雅数组,k也可以被称为优雅阈值。例如,数组1,2,3,1、2,3,1,它是一个3-优雅数组,因为元素1出现次数大于等于3次,数组1,2,3,1,2就不是一个3-优雅数组,因为其中出现次数最多的元素是1和2,只出现了2次。给定一个数组A和k,请求出A有多少子数组是k-优雅子数组。

MISAYAONE的博客 1万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

图的遍历 (深度优先遍历和广度优先遍历)

一. 什么是深度优先遍历 深度优先遍历可定义如下:首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点均已被访问为止。若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点为新的源点重复上述过程,直至图中所有的顶点均已被访问为止。 深度优先遍历结果是: A B E F C D G H 深度优先遍历尽可能优先往深层次进行搜索 二.广度优先遍历 广度优先遍历可定...

qq_52252193的博客 2万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

C语言实现图的深度优先遍历和广度优先遍历

图的深度优先遍历和广度优先遍历图的遍历深度优先遍历广度优先遍历 图的遍历 从给定图中任意指定的顶点(称为初始点)出发,按照某种搜索方法沿着图的边访问图中所有顶点,使每个顶点仅被访问一次,这个过程称为图的遍历 图的遍历方法有两种,一种叫深度优先遍历(DFS),另一种叫广度优先遍历(BFS)。 深度优先遍历 深度优先遍历的过程是从图中的某个初始点v出发,首先访问初始点v,然后选择一个与顶点v相邻且没被...

BEICHENx1的博客 1万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

图(深度优先遍历、广度优先遍历)

文章目录一、图的概述1.1 什么是图1.2 图对比线性表和树1.3 图的常见概念二、图的存储方式2.1 邻接矩阵2.2 邻接表三、图的遍历3.1 图的深度优先遍历3.1.1 什么是深度优先遍历3.1.2 深度优先遍历的步骤3.1.3 深度优先遍历代码实现3.2 图的广度优先遍历3.2.1 什么是广度优先遍历3.2.2 广度优先遍历的步骤3.2.3 广度优先遍历代码实现 一、图的概述 1.1 什么是图 图(graph)是一种数据结构,它是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E)。

Ronz 的博客 6469

图的遍历(广度优先遍历BFS,深度优先遍历DFS)

详细介绍了图的广度优先遍历(BFS)和深度优先遍历(DFS),涉及代码均有用图进行描述,非常详细!!!

2301_80035594的博客 2441

数据结构——详解图的深度优先遍历和广度优先遍历及代码实现

图的深度优先遍历和广度优先遍历: 从本质上来说都是用来访问图中的所有结点的,只是两种访问的方式不同,深度优先遍历用的是堆栈,先进的后出,而广度优先遍历用的是队列的思想。 1.图的深度优先遍历 1.1基本思想: ⑴ 访问顶点v; ⑵ 从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历; ⑶ 重复上述两步,直至图中所有和v有路径相通的顶点都被访问到。 例如我们需要用深度优先遍历下面这个图...

诶你爱我吗的博客 1万+

图的邻接矩阵实现与深度优先遍历、广度优先

重点: 1、深度优先遍历——递归 2、广度优先遍历——队列 #include<bits/stdc++.h> using namespace std; const int MaxSize=10;//图中最多顶点的个数 int visited[MaxSize]; template<class DataType> class Queue { public: D...

pxl20171799的博客 8692

图的遍历(深度优先遍历DFS,广度优先遍历BFS)以及C语言的实现

遍历的定义: 从已给的连通图中某一顶点出发,沿着一些边访遍图中所有的顶点,且使每个顶点仅被访问一次,就叫做图的遍历,它是图的基本运算. 一:深度优先遍历(DFS) 1,在访问图中某一起始顶点V后,由V出发,访问它的任一邻接顶点W1 2,再从W1出发,访问与W1邻接但还未被访问过的顶点W2; 3,然后再从W2出发,进行类似的访问...... 4,如此进行下去,直至到达所有的邻接顶点都被访问过的顶点U为止. 5,接着,退回一步,退到前一次刚访问过的顶点,看是否还有其它没有被访问过的邻接点 6,如

any_ways的博客 3万+

数据结构——图的两种遍历【深度优先遍历-广度优先遍历】的区别用法

目录: 一:深度优先遍历 1.定义 2.图表达流程 举例: 代码实现: 3.对于连通图 4.对于非连通图 5.深度优先搜索 6.对无向图的深度优先遍历图解 7.对有向图的深度优先遍历 二:广度优先遍历 1.定义 2.搜索步骤 3.图表达流程 举例: 代码实现: 4.对无向图的广度优先遍历图解 5.对有向图的广度优先遍历图解 三:异同 1.同 2.异 ...

刘鑫磊 3万+

图的深度优先遍历与广度优先遍历

1. 深度优先遍历   深度优先遍历(Depth First Search)的主要思想是:     1、首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点;     2、当没有未访问过的顶点时,则回到上一个顶点,继续试探别的顶点,直至所有的顶点都被访问过。 用一句话来形容 “不到南墙不回头”。   1.1 无向图的深度优先遍历图解 以下"无向图"为例:  对上无向图进行深度优先遍历,从A开始: 第1步:访问A。 第2步...

qq_44421399的博客 3457

图的遍历-深度优先遍历与广度优先遍历(C语言)

目录 邻接矩阵及邻接表的创建 深度优先遍历(DFS) 邻接矩阵的深度优先遍历 结构定义 邻接矩阵的深度优先遍历操作 邻接矩阵的深度优先递归算法 邻接表的深度优先遍历 结构定义 邻接表的深度优先遍历操作 邻接表的深度优先递归算法 广度优先遍历(BFS) 邻接矩阵的广度遍历 结构定义 邻接矩阵的广度遍历算法 邻接表的广度优先遍历 结构定义 邻接表的遍历算法 广度优先遍历所需队列代码

偶然路过的帅小伙z的博客 5933

利用堆栈和队列实现图的深度优先遍历和广度优先遍历

//图的存储结构为邻接表 #include #include #define MaxVex 100 int visited[MaxVex]; //全局数组,用于记录图中节点访问状态 typedef struct EdgeNode { //邻接表节点 int adjvex; //该邻接点在顶点数组中的下标 struct EdgeNode *next; //指向下一个

zsw_404的博客 1万+
上一篇: 设计模式之单例模式
下一篇: 马踏棋盘算法(骑士周游问题)
漂流在深圳
博客等级 码龄15年 30粉丝 60原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值