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);
    }
  • 相关阅读:
    06 is和==的区别 encode()编码 decode()解码
    05 dic的增删改查 字典的嵌套 考试题dic.get()的相关使用
    03 编码 int ,bool,str的常用操作 主要讲str
    01 基本数据类型 变量 if语句
    04 列表的增删改查 常用方法 元祖 range
    02 while循环 格式化输出 运算符
    多校2 Harmonious Army hdu6598 网络流
    P3159 [CQOI2012]交换棋子 网络流
    P2172 [国家集训队]部落战争 最大流
    P2402 奶牛隐藏 网络流
  • 原文地址:https://www.cnblogs.com/Nastukashii/p/4428690.html
Copyright © 2011-2022 走看看