【无标题】

遍历的定义:

从已给的联通图中某顶点出发,沿着一些边访遍图中的所有顶点,并且每个顶点仅仅被访问一次,叫做图的遍历,是图的基本运算。

图的特点:

图中可能存在回路,且图的任一顶点都有可能与其他顶点联通,在访问完某点之后可能会沿边回到曾经访问过的节点。

避免重复访问的思路:

设置辅助数组visited【n】,用来标记已经访问过的节点

*默认visited状态为0

*顶点被访问后置为1,避免重复访问

深度优先搜索(DFS):

从某个起始节点开始遍历,首先访问该节点,并标记该节点已被访问。接着找到与该节点相邻的未被访问的节点中的一个,继续以该节点为起始节点进行深度优先搜索。

联通图的深度优先遍历类似于树的先根遍历。

设置对应顶点的数组值初始化为0

int visited[顶点个数];

//图G为领接矩阵类型
void DFS(Graph G , int v)
{

visited[v]=true;    
    
    for(int i=0;i<G.vexnum;i++)
    {
        if(G.bian[v][i] != 0 && ( !visited[i]) )
        //检查到相领节点且未访问过就递归执行搜查
        DFS(G,i);
        
    }
    
}

BFS(Breadth-First Search)又称广度优先搜索,是一种基于图的遍历算法,它从指定的起始节点开始遍历图,依次访问其相邻的节点,直到遍历完整个图为止。

使用邻接表表示图的优点包括:

  1. 空间复杂度低:对于稀疏图,邻接表中只存储非零元素,空间复杂度较低;
  2. 可快速获取节点的邻居节点:由于邻居节点存储在同一链表中,因此可以快速获取某个节点的邻居节点;
  3. 遍历效率高:对于从某个节点出发的遍历操作,由于只需要访问该节点的邻居节点,因此遍历的效率较高。

邻接表也有一些缺点,例如:

  1. 无法快速判断两个节点之间是否存在边;
  2. 在查找两个节点之间的边时,需要遍历链表,时间复杂度较高;
  3. 对于稠密图,邻接表的空间复杂度可能不如邻接矩阵。

和树的层次遍历类似。

//树的层次遍历
#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 100           // 队列的最大容量

/* 树结构体定义 */
typedef struct TreeNode 
{
    int data;
    struct TreeNode *left_child;   // 指向左子树根节点的指针
    struct TreeNode *right_child;  // 指向右子树根节点的指针
} TreeNode;

/* 队列结构体定义 */
typedef struct 
{
    TreeNode *data[MAX_SIZE];      // 存储节点指针的数组
    int front;                     // 队首指针
    int rear;                      // 队尾指针
} Queue;

/* 初始化队列 */
void init_queue(Queue *queue) 
{
    queue->front = 0;
    queue->rear = 0;
}

/* 判断队列是否为空 */
int is_empty(Queue *queue) 
{
    return queue->front == queue->rear;
}

/* 入队 */
void enqueue(Queue *queue, TreeNode *node) 
{
    queue->data[queue->rear++] = node;
}

/* 出队 */
TreeNode *dequeue(Queue *queue) 
{
    return queue->data[queue->front++];
}

/* 层次遍历 */
void level_order_traversal(TreeNode *root) 
{
    if (root == NULL) {  // 空树,直接返回
        return;
    }

    Queue queue;
    init_queue(&queue);  // 初始化队列
    enqueue(&queue, root);  // 将根节点入队

    while (!is_empty(&queue)) {
        TreeNode *node = dequeue(&queue);  // 取出队首节点
        printf("%d ", node->data);  // 访问该节点

        if (node->left_child != NULL) {   // 将左子树的根节点入队
            enqueue(&queue, node->left_child);
        }
        if (node->right_child != NULL) {  // 将右子树的根节点入队
            enqueue(&queue, node->right_child);
        }
    }
}

/* 创建新节点 */
TreeNode *new_node(int data) {
    TreeNode *node = (TreeNode *) malloc(sizeof(TreeNode));
    node->data = data;
    node->left_child = NULL;
    node->right_child = NULL;
    return node;
}
//邻接表的层序遍历
#include <stdio.h>
#include <stdlib.h>

/* 边结构体定义 */
typedef struct EdgeNode 
{
    int adjvex;                 // 相邻顶点在数组中的下标
    struct EdgeNode *next_edge; // 指向下一条边的指针
} EdgeNode;

/* 顶点结构体定义 */
typedef struct VertexNode 
{
    int data;                   // 顶点存储的数据
    EdgeNode *first_edge;       // 指向第一条边的指针
} VertexNode;

/* 图结构体定义 */
typedef struct 
{
    VertexNode vertices[100];   // 存储顶点的数组
    int vertex_count;           // 顶点数
    int edge_count;             // 边数
} Graph;

/* 添加边 */
void add_edge(Graph *graph, int from, int to) 
{
    EdgeNode *edge = (EdgeNode *) malloc(sizeof(EdgeNode));
    edge->adjvex = to;
    edge->next_edge = graph->vertices[from].first_edge;
    graph->vertices[from].first_edge = edge;  // 将该边插入到头部
}

/* 创建图 */
Graph *create_graph(int vertex_count, int edge_count) 
{
    Graph *graph = (Graph *) malloc(sizeof(Graph));
    graph->vertex_count = vertex_count;
    graph->edge_count = edge_count;

    for (int i = 0; i < vertex_count; i++) 
    {
        graph->vertices[i].data = i;      // 顶点的数据初始化为下标值
        graph->vertices[i].first_edge = NULL;
    }

    int from, to;
    for (int i = 0; i < edge_count; i++) 
    {
        scanf("%d %d", &from, &to);
        add_edge(graph, from, to);        // 添加边
    }

    return graph;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值