C#构建树形结构数据(全部构建,查找构建)

C#构建树形结构数据(全部构建,查找构建)

前言

树形结构数据在实际开发中非常常见,具有分级、层级、分类等特点,通常应用于目录结构、组织机构、商品分类等场景。本文将介绍如何使用C#构建树形结构数据,包括全部构建和查找构建两种方案。

全部构建

步骤一:定义数据结构

我们假设有一个数据表,包含id、parentId、name三个字段,其中id为自增主键,parentId为父节点id,name为节点名称,例如:

id parentId name
1 0 根节点1
2 1 二级节点1
3 1 二级节点2
4 2 三级节点1
5 2 三级节点2

我们可以定义一个与之对应的数据结构,例如:

public class TreeNode
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<TreeNode> Children { get; set; }
}

其中,Id为节点id,Name为节点名称,Children为子节点集合。

步骤二:加载数据

我们需要将数据表中的数据加载到内存中,使用List存储。

List<TreeNode> nodes = new List<TreeNode>();
// 加载数据
foreach (DataRow row in dataTable.Rows)
{
    var node = new TreeNode
    {
        Id = row.Field<int>("id"),
        Name = row.Field<string>("name")
    };
    nodes.Add(node);
}

步骤三:构建树形结构

接下来的任务就是将这个扁平的节点列表转换成树形结构。我们可以采用递归的方式进行构建:

public static List<TreeNode> BuildTree(List<TreeNode> nodes, int parentId = 0)
{
    var tree = new List<TreeNode>();
    foreach (var node in nodes.Where(n => n.ParentId == parentId))
    {
        node.Children = BuildTree(nodes, node.Id);
        tree.Add(node);
    }
    return tree;
}

当parentId为0时,意味着构建根节点。对于每一个节点,我们在nodes中查找其子节点,并添加到Children中。

步骤四:完整代码

public class TreeNode
{
    public int Id { get; set; }
    public int ParentId { get; set; }
    public string Name { get; set; }
    public List<TreeNode> Children { get; set; }
}

public static class TreeBuilder
{
    public static List<TreeNode> BuildTree(List<TreeNode> nodes, int parentId = 0)
    {
        var tree = new List<TreeNode>();
        foreach (var node in nodes.Where(n => n.ParentId == parentId))
        {
            node.Children = BuildTree(nodes, node.Id);
            tree.Add(node);
        }
        return tree;
    }
}

查找构建

如果数据量较大,全部构建可能会导致性能问题。在这种情况下,我们可以使用查找构建的方式,只构建需要的节点。

步骤一:定义数据结构

与全部构建相同,我们需要定义一个树形结构的节点类:

public class TreeNode
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<TreeNode> Children { get; set; }
}

步骤二:加载数据

同样是将数据表中的数据加载到内存中,使用List存储。

List<TreeNode> nodes = new List<TreeNode>();
// 加载数据
foreach (DataRow row in dataTable.Rows)
{
    var node = new TreeNode
    {
        Id = row.Field<int>("id"),
        Name = row.Field<string>("name")
    };
    nodes.Add(node);
}

步骤三:查找构建

我们通过递归的方式,构建指定节点的树形结构。具体实现如下:

public static List<TreeNode> BuildTree(List<TreeNode> nodes, int id)
{
    var tree = new List<TreeNode>();
    foreach (var node in nodes.Where(n => n.ParentId == id))
    {
        node.Children = BuildTree(nodes, node.Id);
        tree.Add(node);
    }
    return tree;
}

步骤四:完整代码

public class TreeNode
{
    public int Id { get; set; }
    public int ParentId { get; set; }
    public string Name { get; set; }
    public List<TreeNode> Children { get; set; }
}

public static class TreeBuilder
{
    public static List<TreeNode> BuildTree(List<TreeNode> nodes, int parentId = 0)
    {
        var tree = new List<TreeNode>();
        foreach (var node in nodes.Where(n => n.ParentId == parentId))
        {
            node.Children = BuildTree(nodes, node.Id);
            tree.Add(node);
        }
        return tree;
    }

    public static List<TreeNode> BuildSubTree(List<TreeNode> nodes, int id)
    {
        var tree = new List<TreeNode>();
        foreach (var node in nodes.Where(n => n.Id == id))
        {
            node.Children = BuildTree(nodes, node.Id);
            tree.Add(node);
        }
        return tree;
    }
}

示例说明

我们假设有一张商品分类表,其中的数据如下:

id parentId name
1 0 电器类
2 1 彩电类
3 1 冰箱类
4 2 液晶电视
5 2 智能电视
6 3 单门冰箱
7 3 双门冰箱

示例一:全部构建

我们可以使用以下代码构建整个树形结构:

List<TreeNode> nodes = LoadDataFromDb();
List<TreeNode> tree = TreeBuilder.BuildTree(nodes);

构建出的树形结构如下:

电器类
|--彩电类
|  |--液晶电视
|  |--智能电视
|--冰箱类
   |--单门冰箱
   |--双门冰箱

示例二:查找构建

如果我们只需要构建彩电类及其子类别的树形结构,我们可以使用以下代码:

List<TreeNode> nodes = LoadDataFromDb();
List<TreeNode> tree = TreeBuilder.BuildSubTree(nodes, 2);

构建出的树形结构如下:

彩电类
|--液晶电视
|--智能电视

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#构建树形结构数据(全部构建,查找构建) - Python技术站

(0)
上一篇 2023年5月31日
下一篇 2023年5月31日

相关文章

  • C# IsReadOnly:获取一个值,该值指示集合是否为只读

    C#中的IsReadOnly属性用于指示集合或数组是否为只读。如果集合或数组为只读,则不允许用户添加、修改或删除其元素。IsReadOnly是一个bool类型的属性,其值默认为false。当IsReadOnly为true时,集合或数组将变为只读状态,任何修改都会引发NotSupportedException异常。 以下是IsReadOnly属性用法的示例: …

    C# 2023年4月19日
    00
  • 一次.net core异步线程设置超时时间的实战记录

    一次.NET Core异步线程设置超时时间的实战记录需要注意以下几个步骤: 1. 使用 CancellationToken 以便能够取消异步操作 CancellationToken 是一个用于在异步执行期间通知它们应该被取消的对象。在异步操作中可以使用 CancellationToken 实例来获得通知。 在C#中,可以通过以下代码创建一个 Cancella…

    C# 2023年6月3日
    00
  • Asp.net 通用万级数据分页代码[修正下载地址]

    Asp.net 通用万级数据分页代码是一个用于实现数据分页的工具库。下面将给出该工具库的详细攻略: 安装 可以通过Nuget进行安装,输入以下命令即可: Install-Package AspNetPager 安装完成后可以通过以下命名引用Asp.net分页控件: using Wuqi.Webdiyer; 使用方法 在前端页面中添加控件 在前端页面中引用控件…

    C# 2023年5月31日
    00
  • C#、ASP.NET通用扩展工具类之LogicSugar

    首先感谢您对LogicSugar工具类的关注与使用,下面详细讲解一下该工具类的完整攻略。 一、概述 LogicSugar是一款C#、ASP.NET通用扩展工具类库,主要提供了一些常用的快捷方法和扩展类,帮助C#和ASP.NET开发者快速高效地完成开发工作。LogicSugar的特点是简单易用、代码量少、维护性强、可以更加方便地扩展使用。 二、安装和使用 Lo…

    C# 2023年5月15日
    00
  • C#字符串数组转换为整形数组的方法

    以下是详细的讲解“C#字符串数组转换为整形数组的方法”的攻略: 方法一:使用循环遍历 首先,我们可以使用for循环遍历字符串数组,然后逐一转换成整型,保存至目标整型数组中。 string[] strArray = {"10", "20", "30"}; int[] intArray = new in…

    C# 2023年6月7日
    00
  • asp.net获取服务器基本信息的方法代码

    当在开发ASP.NET应用程序时,我们经常需要获取服务器的基本信息,例如操作系统版本、处理器等。下面我将详细讲解如何通过代码获取这些信息。 获取操作系统版本以及平台信息 我们可以通过System.Environment类中的OSVersion和ProcessorCount属性来获取服务器的操作系统版本信息和处理器的数量。具体代码如下: using Syste…

    C# 2023年5月31日
    00
  • c# Linq distinct不会调用Equals方法详解

    下面我将为您详细讲解“c# Linq distinct不会调用Equals方法详解”。 1. 关于Linq的Distinct方法 首先,Linq的Distinct方法用于对元素进行去重,返回一个不包含重复元素的新序列。这个过程中,Distinct方法会调用元素类型的Equals方法进行比较。 2. 关于Equals方法的默认实现 C# 中所有的类都继承自 S…

    C# 2023年6月1日
    00
  • 详解C#中的out和ref

    下面是C#中out和ref的详解攻略。 1. out 和 ref 的作用 out和ref一般用于方法参数中,可以用来传递一个参数的引用地址,而不是传递参数的值。不同的是,ref修饰的参数在方法结束时仍然具有它传入时的值,而out修饰的参数在方法结束时必须返回数据。 2. 示例说明 2.1 使用 ref 关键字 static void Main(string[…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部