C# 从深度优先搜索返回路径

C# 从深度优先搜索返回路径,c#,search,depth-first-search,C#,Search,Depth First Search,我试图通过深度优先搜索在图中找到一个特定的节点。我当前的(简单)实现正在工作,但只返回一个bool,即是否已找到节点 我想添加从操作返回路径的功能,例如,如果我在下面的示例中搜索5,我将得到“1-2-3-5”,而不仅仅是true 公共类二进制树节点 { 公共列表子项{get;set;} 公共int数据{get;set;} } 公共类DepthFirstSearch { 私有堆栈_searchStack; 私有二叉树烯_根; public DepthFirstSearch(二进制树节点根节点)

我试图通过深度优先搜索在图中找到一个特定的节点。我当前的(简单)实现正在工作,但只返回一个
bool
,即是否已找到节点

我想添加从操作返回路径的功能,例如,如果我在下面的示例中搜索
5
,我将得到
“1-2-3-5”
,而不仅仅是
true

公共类二进制树节点
{
公共列表子项{get;set;}
公共int数据{get;set;}
}
公共类DepthFirstSearch
{
私有堆栈_searchStack;
私有二叉树烯_根;
public DepthFirstSearch(二进制树节点根节点)
{
_根=根节点;
_searchStack=新堆栈();
}
公共布尔搜索(整数数据)
{
双核三烯醚电流;
_searchStack.Push(_root);
而(_searchStack.Count!=0)
{
_当前=_searchStack.Pop();
如果(_current.Data==数据)
{
返回true;
}
foreach(current.Children.AsEnumerable().Reverse()中的二进制树节点b)
_searchStack.Push(b);
}
返回false;
}
}

非常感谢您的帮助。

最简单的方法是在
BinaryTreeNode
类中存储
BinaryTreeNode父节点{get;set;}
,如果没有父节点,则为
null
。这些将在最初构建树时设置。然后,您可以简单地返回找到的节点(或者如果没有找到任何节点,则返回
null
),然后遍历父节点,用类似于

List<int> path = new List<int>();
BinaryTreeNode found = new DepthFirstSearch(root).Search();
while(found != null)
{
    path.Push(found.Data);
    found = found.Parent;
}
string stringPath = String.Join("-", path);
列表路径=新列表();
BinaryTreeNode found=新的DepthFirstSearch(root.Search();
while(找到!=null)
{
path.Push(find.Data);
found=found.Parent;
}
string stringPath=string.Join(“-”,path);

我不记得推送的确切语义,因此您可能最终不得不反转列表或附加到列表的末尾或类似的内容,而不是使用另一种方式来推送。 这种方法在每个节点上存储父级信息,并
getPath
遍历树并返回值。但是你的树不是二叉树,也许你应该把类名改成TreeNode或者其他什么

static void Main(string[] args)
{
    var root = createNode();
    var search = new DepthFirstSearch(root);
    var result = search.Search(5);
    var arr = result.getPath();
    arr.Reverse();
    Console.Write(String.Join("-",arr));
}
public class DepthFirstSearch
{
    private Stack _searchStack;
    private BinaryTreeNode _root;
    public DepthFirstSearch(BinaryTreeNode rootNode)
    {
        _root = rootNode;
        _searchStack = new Stack();
    }

    public BinaryTreeNode Search(int data)
    {
        BinaryTreeNode _current;
        _searchStack.Push(_root);
        while (_searchStack.Count != 0)
        {
            _current = (BinaryTreeNode)_searchStack.Pop();
            if (_current.Data == data)
            {
                return _current;
            }

            foreach (BinaryTreeNode b in _current.Children.AsEnumerable().Reverse())
                _searchStack.Push(b);
        }
        return null;
    }
}

public class BinaryTreeNode
{
    public BinaryTreeNode parent { get; set; }
    public List<BinaryTreeNode> Children { get; set; }
    public int Data { get; set; }

    public List<int> getPath()
    {
        var list = new List<int>(){Data};

        if (parent != null)
        {
            list.AddRange(parent.getPath());
        }
        return list;
    }
}
static void Main(字符串[]args)
{
var root=createNode();
var search=新的DepthFirstSearch(根);
var result=search.search(5);
var arr=result.getPath();
反向排列();
Console.Write(String.Join(“-”,arr));
}
公共类DepthFirstSearch
{
私有堆栈_searchStack;
私有二叉树烯_根;
public DepthFirstSearch(二进制树节点根节点)
{
_根=根节点;
_searchStack=新堆栈();
}
公共二进制树节点搜索(int数据)
{
双核三烯醚电流;
_searchStack.Push(_root);
而(_searchStack.Count!=0)
{
_当前=(二进制树节点)u searchStack.Pop();
如果(_current.Data==数据)
{
返回电流;
}
foreach(current.Children.AsEnumerable().Reverse()中的二进制树节点b)
_searchStack.Push(b);
}
返回null;
}
}
公共类二元树节点
{
公共二进制树节点父{get;set;}
公共列表子项{get;set;}
公共int数据{get;set;}
公共列表getPath()
{
var list=new list(){Data};
如果(父项!=null)
{
list.AddRange(parent.getPath());
}
退货清单;
}
}

首先,树映像中的示例不是二叉树节点,因为第一个节点(根节点)有3个子节点。二叉树的节点应该只有两个子节点,一个称为“左”,另一个称为“右”,因此“二叉树”中的“bi”

此外,您的BinaryTreeNode实现有两个好主意:

  • 一个名为“Data”的值(节点需要存储此“数据”是正确的)。但我建议不要将变量命名为“数据”,因为C#中还有其他变量和库,其中包含“数据”一词。把它命名为“nodeData”怎么样?描述性和独特性越强越好

  • 您在存储子节点方面的想法是正确的,但是其他二进制树节点的列表是不正确的,因为如果该列表意外地有两个以上的子节点,该怎么办?同样,如果您愿意,也可以这样做,但这将是一个“树”,而不是一个“二叉树”数据结构。不如换成:

    public List<BinaryTreeNode> Children { get; set; }
    
    现在,您的“布尔搜索”功能:

    您正在将节点的所有子节点推入堆栈中。根据定义,这几乎是“广度优先搜索”,而不是“深度优先搜索”。“宽度”,因为首先按“行”(或“宽度”)存储节点。假设第0行是根节点,第1行是根节点的子节点,第2行是根节点的子节点,。。。等等使用堆栈的事实意味着您将搜索弹出到堆栈中的最后一个子节点\u searchStack。正确的宽度优先使用队列而不是堆栈(FIFO与FILO),但这超出了本问题的范围

    深度优先搜索应集中于一次保存一个(且仅一个)节点。对于第一个根节点,选择一个子节点。然后你对那个孩子进行深度优先搜索。那个孩子会从自己的孩子中选择一个,然后打电话给深度优先。等等如果节点没有子节点,则返回/退出该函数。一个节点完成一个子节点后,对另一个子节点调用深度优先搜索。深度优先搜索的一般思想是,在覆盖任何兄弟节点之前,您希望深入到树中

    回答您的问题:

    一旦成功实施DFS,您需要
    public List<BinaryTreeNode> Children { get; set; }
    
    public BinaryTreeNode LeftNode { get; set; }
    public BinaryTreeNode RightNode { get; set; }