zoukankan      html  css  js  c++  java
  • 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);
    }
  • 相关阅读:
    Qt计算器开发(三):执行效果及项目总结
    [HNOI2019]校园旅行
    How to fix nuget Unrecognized license type MIT when pack
    How to fix nuget Unrecognized license type MIT when pack
    git 通过 SublimeMerge 处理冲突
    git 通过 SublimeMerge 处理冲突
    git 上传当前分支
    git 上传当前分支
    gif 格式
    gif 格式
  • 原文地址:https://www.cnblogs.com/Nastukashii/p/4428690.html
Copyright © 2011-2022 走看看