C# 获取节点的索引';在平衡树中传递其索引的 例子:
我举了下面的例子来说明锦标赛日程安排:C# 获取节点的索引';在平衡树中传递其索引的 例子:,c#,math,logic,nodes,treenode,C#,Math,Logic,Nodes,Treenode,我举了下面的例子来说明锦标赛日程安排: 1 2 3 4 5 6 7 8 | | | | 9 10 11 12 | | 13 14 | 15 规则: 这些数字表示节点的值(匹配)。该值从上到下开始,因为根是锦标赛的最后一场比赛 树将始终保持平衡,并且可以有N个顶部位置,其中N={2,4,8,16,32,64128256…} 问题: 我需要找到一个数学函数,它将返回节点父节点的
1 2 3 4 5 6 7 8
| | | |
9 10 11 12
| |
13 14
|
15
规则:
这些数字表示节点的值(匹配)。该值从上到下开始,因为根是锦标赛的最后一场比赛
树将始终保持平衡,并且可以有N个顶部位置,其中N={2,4,8,16,32,64128256…}
问题:
我需要找到一个数学函数,它将返回节点父节点的值,并传递其值。这个数学函数必须可以用C#表示
函数应该是怎样的?在我看来,最简单的处理方法是以另一种方式存储树。通常,平衡树可以表示为一个数组,根位于第一个位置,叶位于最后的
n/2
位置,如下所示:
1
|
2 3
| |
4 5 6 7
| | | |
8 9 10 11 12 13 14 15
[TestMethod]
public void TestMethod1()
{
List<int> values = new List<int>{15, 13, 14, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8};
Assert.AreEqual(values.IndexOf(13) + 1, Stuff.GetParent(values.IndexOf(9) + 1));
Assert.AreEqual(values.IndexOf(13) + 1, Stuff.GetParent(values.IndexOf(10) + 1));
Assert.AreEqual(values.IndexOf(10) + 1, Stuff.GetParent(values.IndexOf(4) + 1));
Assert.AreEqual(null, Stuff.GetParent(values.IndexOf(15)));
}
在内存中看起来是这样的:
1|2|3|4|5|6|7|8|9|10|11|12|13|14|15
现在这个结构的一个有趣的特性是,父对象总是位于Math.Floor(index/2)
(因此子对象位于n*2
和n*2+1
)
例如,13
的父项是13/2=6.5=floored=6
。它确实简化了操作
如前所述,所有叶节点都位于最后的n/2位置。这是另一个有趣的命运;如果您正在寻找第一轮比赛,只需切掉您的阵列,然后取出数学上限(n/2)
最后一项:
1 | 2 | 3 | 4 | 5 | 6 | 7 |8 | 9 | 10 | 11 | 12 | 13 | 14 | 15
对于第二轮,移除上一轮,并在数学天花板(n/2)处再次盖章。:
1 | 2 | 3 |4 | 5 | 6 | 7 |
因此,知道了这一点,
GetParent
可以如下所示:
public static int? GetParent(int childIndex)
{
int parentIndex = (int) Math.Floor((double)childIndex/2);
return parentIndex == 0 ? (int?)null : parentIndex;
}
或直接return(int)Math.Floor((双)索引/2)代码>如果不需要空值
这可以通过从示例值位置进行的简单单元测试进行验证:
[TestMethod]
public void TestMethod1()
{
Assert.AreEqual(2, Stuff.GetParent(4));
Assert.AreEqual(2, Stuff.GetParent(5));
Assert.AreEqual(6, Stuff.GetParent(13));
Assert.AreEqual(null, Stuff.GetParent(1));
}
也不要忘记使用索引而不是值,你不能直接应用你的例子中的9和13,现在是4和2,因为这是他们在树中的索引,根在第一个位置,它的结构像。您提供的示例的构造如下:
15|13|14|9|10|11|12|1|2|3|4|5|6|7|8
如果需要按值工作,可以使用IndexOf
。由于您是基于1而不是基于0的,因此还需要向每个索引添加1。看起来是这样的:
1
|
2 3
| |
4 5 6 7
| | | |
8 9 10 11 12 13 14 15
[TestMethod]
public void TestMethod1()
{
List<int> values = new List<int>{15, 13, 14, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8};
Assert.AreEqual(values.IndexOf(13) + 1, Stuff.GetParent(values.IndexOf(9) + 1));
Assert.AreEqual(values.IndexOf(13) + 1, Stuff.GetParent(values.IndexOf(10) + 1));
Assert.AreEqual(values.IndexOf(10) + 1, Stuff.GetParent(values.IndexOf(4) + 1));
Assert.AreEqual(null, Stuff.GetParent(values.IndexOf(15)));
}
[TestMethod]
公共void TestMethod1()
{
列表值=新列表{15,13,14,9,10,11,12,1,2,3,4,5,6,7,8};
AreEqual(values.IndexOf(13)+1,Stuff.GetParent(values.IndexOf(9)+1));
AreEqual(values.IndexOf(13)+1,Stuff.GetParent(values.IndexOf(10)+1));
AreEqual(values.IndexOf(10)+1,Stuff.GetParent(values.IndexOf(4)+1));
AreEqual(null,Stuff.GetParent(values.IndexOf(15));
}
选项1:构建一个与之相反的新树,以便可以使用二叉树
备选案文2:
调用列表\u name.Count()
,我在您的案例中使用了15
GetNodeParent(9,15); // return 13
GetNodeParent(10,15);// return 13
GetNodeParent(4,15); // return 10
这是可行的,但您必须检查最终案例(您的案例中有15个):
事后考虑,在调用方法之前,为null
添加一个if(aNodeValue==list\u name.Count())
,或者将签名更改为int?
,并在方法中进行检查,使其返回null您尝试过这个简单的公式吗
GetNodeParent(k) = (k + 1) div 2 + N
(if >=2N then null)
其中div是整数除法(7 div 2=3)GetNodeParent(Int32 nodeIndex)
方法没有足够的信息来完成任务。除了节点数,它还需要知道节点总数或级别数(实际上是等效的)。您是传递索引还是传递值?因为如果只传递值,那么也需要传递整个数组。如果你正在传递这个值(根据你的例子,我认为你是这样的),那么你在那里做的命名非常糟糕。我需要传递索引。我的索引不是基于0的,根是最后一个索引。哦,我明白了,那是因为你做了自上而下的树。通常从索引0处的根开始,我的不好。使用最小公倍数,您可以找到树中存在多少层!这真的很接近我想要的,但有没有办法得到相同的结果,但树根作为最后一个数字?因为在我的现实世界中,这棵树代表着冠军。根是最后发生的事情,这是最后一场比赛。我现在无法修改其顺序。强烈建议以正确的格式构建树。如果它颠倒了,你以后就无法重新平衡它了。我详细介绍了如何使用以根作为第一个元素构建的树来处理以前的值。我将尝试将根作为1值。我认为我在我的问题上使用的单词索引令人困惑,因为它不是数组、列表或w/e的索引。这只是价值。我没有一个真正的树结构,节点引用它们的父节点。这棵树只是我总冠军赛程的一个例子。嗯,那么最简单的处理方法就是把这场比赛#1作为决赛。但是,由于所有游戏都是不同的,所以您可以使用最后描述的'IndexOf'部分来获取实际的数组索引。。但是每次进行心理转换都会很麻烦。我还提供了一个详细的方法,以获得游戏的层次,如果这能有所帮助…可悲的是,我无法建立一个新的反向树在我的现实世界的情况。