• 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);
    }
  • 相关阅读:
    java 读取文件内容 方法
    Linux常见问题解答--如何修复“tar:Exiting with failure status due to previous errors”
    FTPbug
    linux shell 字符串操作(长度,查找,替换)详解
    mysqldump参数详细说明
    Win7下的内置FTP组件的设置详解
    FTPAPI
    Linux文件传输FTP详解
    linux 利用shell将当前时间写入文件
    IDEA下创建SpringBoot+MyBatis+MySql项目实现动态登录与注册功能
  • 原文地址:https://www.cnblogs.com/Nastukashii/p/4428690.html
Copyright © 2020-2023  润新知