【问题标题】:Calculate Preorder Tree Traversal From DataTable structure从 DataTable 结构计算前序树遍历
【发布时间】:2013-08-02 21:01:49
【问题描述】:

我有一个具有以下结构的 DataTable:

Root | Level 1 | Level 2 | Level 3 | Tree L | Tree R
Food                                 1        18
       Fruit                         2        11
                 Red                 3        6
                           Cherry    4        5
                 Yellow              7        10
                           Banana    8        9
       Meat                          12       17
                 Beef                13       14
                 Pork                15       16

使用 C#,我需要遍历这个结构并为每个节点计算正确的 Tree L 和 Tree R 值。这只是一个例子,真正的结构有数百个节点,至少达到 7 级,但可能更多。

谁能建议我如何处理计算左右值的代码?

【问题讨论】:

  • 你期望这个例子的结果是什么?
  • @Vasiliy - 我更新了我的示例以显示预期值。
  • 如果你表明你已经尝试了一些东西,这个问题会更好。我怀疑这就是它收集反对票的原因。要么就是这样,要么看起来你正在发布家庭作业。
  • 见下文,我已经用我想出的解决方案添加了答案。
  • 为什么不能在数据库中执行此操作?我的层次结构数据 L/R 是通过插入触发器计算的。

标签: c# modified-preorder-tree-t


【解决方案1】:

因此,您想要跟踪树的访问顺序,但您将顺序拆分为 LR。这些对应于Node 结构的Visit 函数的“入口”和“出口”。假设 Node 类具有 Node.Visit() 方法,您可以:

private static List<Tuple<char,Node>> VisitOrder = new List<Tuple<char,Node>>();

public void Visit()
{
    VisitOrder.Add(Tuple.Create('L', this));
    // whatever visit logic you use here
    VisitOrder.Add(Tuple.Create('R', this));
}

完成后,您所要做的就是查看VisitOrder 值。它们以升序存储在List 中,其中索引对应于它在访问序列中的位置。那么List 中的每个项目都是一个Tuple,描述它对应于哪个值以及它访问了哪个Node

编辑:

要获得最终的输出格式,您可以执行以下操作:

var LTree = VisitOrder
    .Where(t => t.First == 'L')
    .Select((t, i) => String.Format("{0}) {1}", i + 1, t.Second.Name));
var RTree = VisitOrder
    .Where(t => t.First == 'R')
    .Select((t, i) => String.Format("{0}) {1}", i + 1, t.Second.Name));

【讨论】:

    【解决方案2】:

    我是这样理解的:

    private class FolderRow
        {
            public int Indent
            {
                get { return this.Row.GetValue("Indent", 0); }
                set { this.Row["Indent"] = value; }
            }
            public int Left
            {
                get { return this.Row.GetValue("Tree L", 0); }
                set { this.Row["Tree L"] = value; }
            }
            public int Right
            {
                get { return this.Row.GetValue("Tree R", 0); }
                set { this.Row["Tree R"] = value; }
            }
            public Guid Id
            {
                get { return this.Row.GetValue("FolderID", Guid.Empty); }
    
            }
            public DataRow Row { get; private set; }
    
            public int RowNum { get; set; }
    
            public bool RowComplete { get { return this.Left > 0 && this.Right > 0; } }
    
            public FolderRow(DataRow row, int rowNum)
            {
                this.Row = row;
                this.RowNum = rowNum;
            }
        }    
    
    [TestMethod]
    public void ImportFolderStructure()
    {
        var inputTable = FileUtil.GetDataSetFromExcelFile(new FileInfo(@"c:\SampleTree.xlsx")).Tables[0];
    
        var currentLevel = 0;
        var nodeCount = 1;
        var currentRow = 0;
    
        inputTable.Columns.Add("Indent", typeof (int));
        inputTable.Columns.Add("Path", typeof (string));
    
        var rightStack = new List<FolderRow>();
    
        foreach (DataRow row in inputTable.Rows)
            row["Indent"] = GetLevelPopulated(row);
    
        foreach (DataRow row in inputTable.Rows)
        {
            if (row.GetValue("Indent", 0) == 0)
                row["Tree L"] = 1;                
    
        }
    
        while (true)
        {
            var row = GetRow(inputTable, currentRow);
            if (row.Indent == 0)
            {
                currentRow++;
                rightStack.Add(row);
                continue; 
            }
    
            // if the indent of this row is greater than the previous row ...
            if (row.Indent > currentLevel)
            {
                currentLevel++;
                nodeCount++;
                row.Left = nodeCount;
                // ... check the next row to see if it is further indented
                currentRow = HandleNextRow(row, currentRow, rightStack, inputTable, ref currentLevel, ref nodeCount);
            } else if (row.Indent == currentLevel)
            {
                nodeCount++;
                row.Left = nodeCount;
                currentRow = HandleNextRow(row, currentRow, rightStack, inputTable, ref currentLevel, ref nodeCount);
            } else if (row.Indent < currentLevel)
            {
                currentLevel--;
                nodeCount++;
                row.Left = nodeCount;
                currentRow = HandleNextRow(row, currentRow, rightStack, inputTable, ref currentLevel, ref nodeCount);
            }
    
            if (inputTable.Rows.Cast<DataRow>().Select(r => new FolderRow(r, -1)).All(r => r.RowComplete))
                break;
    
        }
    
    }
    
    private int HandleNextRow(FolderRow row, int currentRow, List<FolderRow> rightStack, DataTable inputTable, ref int currentLevel,
                              ref int nodeCount)
    {
        var nextRow = GetRow(inputTable, currentRow + 1);
        if (nextRow != null)
        {
            if (nextRow.Indent > row.Indent)
            {
                // ok the current row has a child so we will need to set the tree right of that, add to stack
                rightStack.Add(row);
            }
            else if (nextRow.Indent == row.Indent)
            {
                nodeCount++;
                row.Right = nodeCount;
            }
            else if (nextRow.Indent < row.Indent)
            {
                nodeCount++;
                row.Right = nodeCount;
                nodeCount++;
                // here we need to get the most recently added row to rightStack, set the Right to the current nodeCount
                var stackLast = rightStack.LastOrDefault();
                if (stackLast != null)
                {
                    stackLast.Right = nodeCount;
                    rightStack.Remove(stackLast);
                }
    
                currentLevel--;
            }
    
            currentRow++;
    
            if (rightStack.Count > 1)
            {
                // before we move on to the next row, we need to check if there is more than one row still in right stack and 
                // the new current row's ident is less than the current branch (not current leaf)
                var newCurrentRow = GetRow(inputTable, currentRow);
                var stackLast = rightStack.LastOrDefault();
                if (newCurrentRow.Indent == stackLast.Indent)
                {
                    nodeCount++;
                    stackLast.Right = nodeCount;
                    rightStack.Remove(stackLast);
    
                }
            }
    
    
        }
        else
        {
            // reached the bottom
            nodeCount++;
            row.Right = nodeCount;
    
            // loop through the remaining items in rightStack and set their right values
            var stackLast = rightStack.LastOrDefault();
            while (stackLast != null)
            {
                nodeCount++;
                stackLast.Right = nodeCount;
                rightStack.Remove(stackLast);
                stackLast = rightStack.LastOrDefault();
            }
        }
        return currentRow;
    }
    
    private FolderRow GetRow(DataTable inputTable, int rowCount)
    {
        if (rowCount >= inputTable.Rows.Count)
            return null;
    
        return rowCount < 0 ? null : new FolderRow(inputTable.Rows[rowCount],rowCount);
    }
    
    private int GetLevelPopulated(DataRow row)
    {
        var level = 0;
    
        while (level < 14)
        {
            if (level == 0 && row["Root"] != DBNull.Value)
                return level;
    
            level++;
    
            if (row["Level " + level] != DBNull.Value)
                return level;
        }
    
        return -1;
    }
    

    【讨论】:

      猜你喜欢
      • 2013-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-09
      • 2021-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多