• DFS栈实现 C代码


    这里代码写的比较随意,直接使用数组下标作为索引,而结点就是用0到n-1来表示。

    类似于递归调用的思想(感觉就是把递归调用里面的调用栈用简单的栈数组来替代一下)。这里对于栈顶的元素,如果它为白色,则全局时间变量加一,且把它邻接链表里的白色节点全部入栈;而如果栈顶元素已经是灰色,就把它变成黑色,时间全局变量加一,并且出栈;如果栈顶元素是黑丝,直接出栈。(这里黑色是必须的,因为结点可能重复入栈)

    时间计算:每个循环要么有黑色结点出栈,要么时间变量加一,所以运行时间为Θ(V+E),因为所有入栈的结点数不会超过邻接链表的总大小。

    分析一下两个时间戳和父节点的赋值:

    1) v.d是第一次探索这个节点的时间,即把它从白色变成灰色的时候对v.d进行赋值。

    2) v.f是该结点的所有结点都被探索过后,即把它从灰色变为黑色的时候对v.f进行赋值。

    3) v.pi在入栈的时候赋值。

     PS:网上搜了一下,发现有个方法是一个结点入栈就break,并对这个结点作处理。本质上没有太大区别,我这里使用较大的栈空间,而那种方法期望时间比较长。

    #include <stdio.h>
    #define N 100
    
    
    typedef struct Vertex {
        int color;
        int pi;
        int d;
        int f;
        int index;//下标
    }Vertex;
    
    typedef struct Node{
        int index;//对应的结点的数组下标,相当于存储了该结点的指针
        struct Node *next;
    }Node;
    
    typedef struct List{
        Node *head;
    }List;
    
    int stack[N];
    static int count = 0;
    int time=0;
    void DFS_V(List *Adj, Vertex *V, int n, int u);
    
    void DFS(List *Adj,Vertex *V,int n){
        for (int i = 0; i < n; ++i){
            V[i].color = 0;
            V[i].pi = -1;
        }
        for (int i = 0; i < n; ++i){
            if (V[i].color == 0)
                DFS_V(Adj,V, n, i);
        }
    }
    
    void DFS_V(List *Adj, Vertex *V,int n, int u){
        stack[count++] = u;
        while (count){
            int v = stack[count - 1];
            if (V[v].color == 0){
                V[v].color = 1;
                ++time;
                V[v].d = time;
                Node *tmp = Adj[v].head;
                while (tmp){
                    if (V[tmp->index].color == 0)
                    {
                        stack[count++] = tmp->index;
                        V[tmp->index].pi = v;
                    }
                    tmp = tmp->next;
                }
            }
            else if (V[v].color==1){
                V[v].color = 2;
                ++time;
                V[v].f = time;
                --count;
            }
            else --count;
        }
    }
    
    void print(Vertex *v,int n){
        for (int i = 0; i <n; i++){
            printf("%d %d %d
    ", v[i].d, v[i].f,v[i].pi);
        }
    }
    void print_a(List *adj, int n){
        for (int i = 0; i < n; ++i){
            Node *tmp = adj[i].head;
            while (tmp){
                printf("%d", tmp->index);
                tmp = tmp->next;
            }
            printf("
    ");
        }
    }
    
    
    int main(){
        Vertex V[6];
        for (int i = 0; i < 6; ++i)
            V[i].index = i;
        List Adj[6] = { 0, 0, 0, 0, 0, 0 };
        
        /*while (1){
            int u, v;
            cin >> u >> v;
            if (u < 0)
                break;
            Node tmp = { v, Adj[u].head };
            Adj[u].head = &tmp;
        }
        */
    
        Node n1 = { 2, 0 }, n2 = { 1, &n1 }, n11 = {4,&n2};
        Adj[0].head = &n11;
        Node n3 = { 0, 0 }, n4 = { 4, &n3 }, n5 = { 3, &n4 };
        Adj[1].head = &n5;
        Node n6 = { 0, 0 }, n7 = { 5, &n6 };
        Adj[2].head = &n7;
        Node n8 = { 1, 0 };
        Adj[3].head = &n8;
        Node n9 = { 1, 0 };
        Adj[4].head = &n9;
        Node n10 = { 2, 0 };
        Adj[5].head = &n10;
        print_a(Adj, 6);
    
        DFS(Adj, V, 6);
        print(V, 6);
    }
  • 相关阅读:
    转载: JS 中 new 操作符
    转载: js的值,对象,原型
    php setcookie(name, value, expires, path, domain, secure) 参数详解
    转载:js数组对象操作
    转载: js数组与 json 的区别
    转载: js的Prototype属性 解释及常用方法
    行人检测程序对接景区测试人数比对数据库切换时间不准确排查
    TSINGSEE青犀视频行人检测集成票务系统读取票务系统数据库为空的问题
    EasyWasmPlayer播放视频报错Uncaught (in promise)DOMException
    名胜景区部署TSINGSEE青犀视频监控具备哪些现实意义?
  • 原文地址:https://www.cnblogs.com/Nastukashii/p/4428690.html
Copyright © 2020-2023  润新知