郭其先生利用DeepSeek实现的PostgreSQL递归CTE实现DFS写法

测试用表

sql 复制代码
CREATE TABLE tree_nodes (
    id INT PRIMARY KEY,
    parent_id INT REFERENCES tree_nodes(id),
    name VARCHAR(50)
);

INSERT INTO tree_nodes VALUES 
(1, NULL, '根节点'),
(2, 1, '子节点1'),
(3, 1, '子节点2'),
(4, 2, '孙子节点1'),
(5, 2, '孙子节点2'),
(6, 3, '孙子节点3');

使用递归 CTE 实现 DFS:

sql 复制代码
WITH RECURSIVE dfs AS (
    -- 锚点:从根节点开始
    SELECT 
        id,
        parent_id,
        name,
        1 AS depth,
        ARRAY[id] AS path,
        ARRAY[name]::text[] AS path_names,
        FALSE AS is_cycle
    FROM tree_nodes
    WHERE parent_id IS NULL
    
    UNION ALL
    
    -- 递归部分:深度优先遍历
    SELECT 
        tn.id,
        tn.parent_id,
        tn.name,
        d.depth + 1,
        d.path || tn.id,
        d.path_names || tn.name,
        tn.id = ANY(d.path) AS is_cycle
    FROM tree_nodes tn
    JOIN dfs d ON tn.parent_id = d.id
    WHERE NOT d.is_cycle  -- 防止循环
)
-- 按深度优先顺序输出
SELECT 
    id,
    parent_id,
    name,
    depth,
    path,
    path_names
FROM dfs
ORDER BY path;

使用栈模拟 DFS

sql 复制代码
WITH RECURSIVE dfs_stack AS (
    -- 初始栈:包含根节点
    SELECT 
        1 AS step,
        id AS current_node,
        name,
        ARRAY[id] AS stack,
        ARRAY[]::INT[] AS visited,
        'visit' AS action
    FROM tree_nodes
    WHERE parent_id IS NULL
    
    UNION ALL
    
    -- 模拟栈操作:弹出、压入
    SELECT 
        d.step + 1,
        CASE 
            -- 如果有未访问的子节点,访问第一个
            WHEN EXISTS (
                SELECT 1 FROM tree_nodes tn 
                WHERE tn.parent_id = d.current_node 
                AND tn.id != ALL(d.visited)
            ) THEN (
                SELECT tn.id 
                FROM tree_nodes tn 
                WHERE tn.parent_id = d.current_node 
                AND tn.id != ALL(d.visited)
                ORDER BY tn.id
                LIMIT 1
            )
            -- 否则回溯
            ELSE d.stack[array_length(d.stack, 1) - 1]
        END,
        tn.name,
        CASE 
            -- 访问新节点:压栈
            WHEN EXISTS (
                SELECT 1 FROM tree_nodes tn 
                WHERE tn.parent_id = d.current_node 
                AND tn.id != ALL(d.visited)
            ) THEN d.stack || (
                SELECT tn.id 
                FROM tree_nodes tn 
                WHERE tn.parent_id = d.current_node 
                AND tn.id != ALL(d.visited)
                ORDER BY tn.id
                LIMIT 1
            )
            -- 回溯:出栈
            ELSE d.stack[1:array_length(d.stack, 1) - 1]
        END,
        d.visited || d.current_node,
        CASE 
            WHEN EXISTS (
                SELECT 1 FROM tree_nodes tn 
                WHERE tn.parent_id = d.current_node 
                AND tn.id != ALL(d.visited)
            ) THEN 'push'
            ELSE 'pop'
        END
    FROM dfs_stack d
    LEFT JOIN tree_nodes tn ON tn.id = d.current_node
    WHERE array_length(d.stack, 1) > 0  -- 栈不为空时继续
)
SELECT 
    step,
    current_node,
    name,
    stack,
    action,
    visited
FROM dfs_stack
ORDER BY step;
相关推荐
池塘的蜗牛8 小时前
AFDM波形基于DFT的通感一体化
算法
阿坤带你走近大数据8 小时前
Oracle新老SQL写法对比
数据库·sql·oracle
147API8 小时前
Claude global workspace 研究给智能体测试提了一个醒
人工智能·算法·机器学习
葫三生8 小时前
《论三生原理》与模糊数学的关联、异同、互补关系?
人工智能·科技·算法·机器学习·开源
我命由我123458 小时前
方差(实例实操、与标准差的区别)
java·数据结构·算法·数据分析·java-ee·intellij-idea·idea
闲研随记8 小时前
【文献阅读 ICML 2026】RL算法:Critique-GRPO
论文阅读·算法·llm·强化学习·rl·icml·grpo
民乐团扒谱机9 小时前
【微实验】从迷雾中看清世界:卡尔曼滤波的数学诗意与MATLAB实践
人工智能·算法·matlab·卡尔曼滤波·kalman
什巳9 小时前
JAVA练习275-乘积最大子数组
java·开发语言·数据结构·算法
@踏雪寻梅9 小时前
27. 移除元素
算法