如何在SMLNJ中创建三元树?
现在,我在SMLNJ中建立了一个二叉树模型,但是我想把这个模型改为在树的内部有一个树。(三叉树) 如果从二叉树的根开始如何在SMLNJ中创建三元树?,sml,smlnj,Sml,Smlnj,现在,我在SMLNJ中建立了一个二叉树模型,但是我想把这个模型改为在树的内部有一个树。(三叉树) 如果从二叉树的根开始 Binode with an (id1*(binode)) ß- a binary tree 然后,如果该“binode”作为元组的一部分定位:2Dbinode 该元组有一个标识符,其中的二元组是二元组树的根 2Dbinode (id2* (binode) *2Dbinode) 每一个都是3Dbinode的一部分,3Dbinode包括: 3Dbin
Binode with an (id1*(binode)) ß- a binary tree
然后,如果该“binode”作为元组的一部分定位:2Dbinode
该元组有一个标识符,其中的二元组是二元组树的根
2Dbinode (id2* (binode) *2Dbinode)
每一个都是3Dbinode的一部分,3Dbinode包括:
3Dbinode(id3 * (2Dbinode) * 3Dbinode)
对于例如3Dbinode(id3*(2DBNODE)*3Dbinode),根3Dbinode可能包含以下数据:
(25, (7, (11)))
And by adding the nodes (25, (7, (22)))
(25, (10, (4))), (30, (7, (22)))
这是我正在修改的2D二叉树的SMLNJ代码
datatype btree = Empty | Node of int * btree * btree;
fun AddNode (i:int, Empty) = Node(i, Empty, Empty) |
AddNode(i:int, Node(j, left, right)) =
if i = j then Node(i, left, right)
else if i < j then Node(j, AddNode(i, left), right)
else Node(j, left, AddNode(i, right));
fun printInorder Empty = () |
printInorder (Node(i,left,right)) =
(printInorder left; print(Int.toString i ^ " "); printInorder right);
val x : btree = AddNode(50, Empty);
val x : btree = AddNode(75, x);
val x : btree = AddNode(25, x);
val x : btree = AddNode(72, x);
val x : btree = AddNode(20, x);
val x : btree = AddNode(100, x);
val x : btree = AddNode(3, x);
val x : btree = AddNode(36, x);
val x : btree = AddNode(17, x);
val x : btree = AddNode(87, x);
printInorder(x);
datatype btree=Empty | int*btree*btree的节点;
fun AddNode(i:int,Empty)=节点(i,Empty,Empty)|
AddNode(i:int,节点(j,左,右))=
如果i=j,则节点(i,左,右)
如果i
我需要用N个随机(3Dnodes)填充数据结构:
如何实现这些功能?
搜索显示节点路径的特定节点ex:(25,10,4)显示将为
- (25)
- (25,7)
- (25、10)
- (25,10,4)
- (25)
- (30)
- (30,7)
- (30,7,30)未找到
- EX:ADD(30,11,5)则显示为
- (25)
- (30)
- (30、7)
- (30,11)创建
- (30,11,5)创建
pathExists
,但是仍然缺少AddNode
,因为您没有提供关于我用粗体突出显示的问题的任何见解。如果你的树真的能在三维空间中包含点,那听起来你确实想要一棵k-d树,就像我曾经建议的那样。我还提供了部分函数make3DTree
,假设您正在寻找的是k-d树
直到我看到你画的a(或通常是a)的画,我才理解你的问题。三元树只是在每一级有(最多)三个子节点,而不是二元树的两个子节点 “树中树中树中树”一词的意思与(2,3,n)不同。你到底是如何把三元组
(25,7,11)
,(25,7,22)
,(25,10,4)
,和(30,7,22)
转化成的,我还是有点困惑。底部节点似乎只有两个空叶子。我将把它解释为中间有第三个空箭头。< /P>
您的AddNode
函数构造较小的元素位于左侧,较大的元素位于右侧那么,您希望如何使用第三个分支?
比较以下通用/特定于整数的二叉树数据类型定义
datatype 'a btree = BTreeEmpty | BTreeNode of 'a * 'a btree * 'a btree
datatype int_btree = BTreeEmpty | BtreeNode of 'a * int_btree * int_btree
对于三元树
datatype 'a ttree = TTreeEmpty | TTreeNode of 'a * 'a ttree * 'a ttree * 'a ttree
datatype int_ttree = TTreeEmpty | TtreeNode of 'a * int_ttree * int_ttree * int_ttree
甚至是在每个节点中支持变量分支的节点
datatype 'a tree = TreeEmpty | TreeNode of 'a * 'a tree list
datatype int_tree = TreeEmpty | TreeNode of int * int_tree list
创建您描述的三元树
val treeModel =
let val t = TTreeNode
val e = TTreeEmpty
in
t (25,
e,
t (7,
e,
t (11, e, e, e),
t (10,
e,
t (4, e, e, e),
e
)
),
t (30,
e,
t (7,
e,
t (22, e, e, e),
e
),
e)
)
end
虽然使用像AddNode
这样的函数可能会更方便,但您只需要为要添加到此类树中的元素指定一致的方式二元搜索树逻辑如何转换为三元树?
确定三元树中是否存在路径 您可以确定节点的路径是否存在。因为树可以有任何深度,所以路径可以有任何长度,并且应该用列表表示。例如,路径
[25,7,10,4]
存在于中
fun pathExists [] _ = true (* the empty path is trivially found *)
| pathExists _ TTreeEmpty = false (* no non-empty path goes through an empty tree *)
| pathExists (x::xs) (TTreeNode (y, subtree1, subtree2, subtree3)) =
x = y andalso
(pathExists xs subtree1 orelse
pathExists xs subtree2 orelse
pathExists xs subtree3)
使用上面的treeModel
测试此功能:
- pathExists [25, 7, 10, 4] treeModel;
> val it = true : bool
- pathExists [25, 30, 7, 22] treeModel;
> val it = true : bool
- pathExists [25, 7, 11, 9] treeModel;
> val it = false : bool
- pathExists [25, 7, 9] treeModel;
> val it = false : bool
在三元树中插入点[??]
此函数的模板可以是
fun AddNode (x, TTreeEmpty) = TTreeNode (x, TTreeEmpty, TTreeEmpty, TTreeEmpty)
| AddNode (x, TTreeNode (y, subtree1, subtree2, subtree3))) = ???
但是如果xy
,它应该尝试将x
添加到三个子树中的哪一个子树
K-d树? 编辑1:回答完之后,我意识到也许你在找一份工作?k-d树可以存储k维向量,仅使用二叉树,以允许高效的、特定于位置的查找 这里最大的技巧是,树的第一层在X轴上将空间分成两半,树的第二层在Y轴上将左/右两半分成两半,树的第三层在Z轴上将左/右两半分成两半,
(* 'byDimension dim (p1, p2)' determines if p1 is greater than p2 in dimension dim. *)
fun byDimension 0 ((x1,_,_), (x2,_,_)) = x1 > x2
| byDimension 1 ((_,y1,_), (_,y2,_)) = y1 > y2
| byDimension 2 ((_,_,z1), (_,_,z2)) = z1 > z2
| byDimension d _ _ = raise Fail ("Invalid dimension " ^ Int.toString d)
(* split points into two halves and isolate the middle element *)
fun splitAt dim points = ...
(* The number of dimensions, matching the arity of the point tuples below *)
val k = 3
fun make3DTree ([], _) = BTreeEmpty
| make3DTree (points, depth) =
let val axis = depth mod k
val len = List.length points
val points_sorted = ListMergeSort.sort (byDimension axis) points
val (points_left, median, points_right) = splitAt len points_sorted
in BTreeNode (median,
make3DTree (points_left, depth+1),
make3DTree (points_right, depth+1))
end
(* get the (n mod 3)-th value of a 3-tuple. *)
fun getDimValue (n, (x,y,z)) =
let val m = n mod k
in if m = 0 then x else
if m = 1 then y else
if m = 2 then z else
raise Fail ("Invalid dimension " ^ Int.toString n)
end
(* the smallest tree that contains a k-dimensional point
* has depth k-1 (because of 0-indexing). *)
fun deepEnough depth = depth >= k-1
fun insertNode (point, BTreeEmpty, depth) =
let val v1 = getDimValue (depth, point)
val v2 = getDimValue (depth+1, point)
val (left, right) =
if deepEnough depth
then (BTreeEmpty, BTreeEmpty)
else if v1 > v2
then (insertNode (point, BTreeEmpty, depth+1), BTreeEmpty)
else (BTreeEmpty, insertNode (point, BTreeEmpty, depth+1))
in BTreeNode (v1, left, right)
end
| insertNode (point, BTreeNode (v1, left, right), depth) =
let val v2 = getDimValue (depth, point)
in if v1 > v2
then BTreeNode (v1, insertNode (point, left, depth+1), right)
else BTreeNode (v1, left, insertNode (point, right, depth+1))
end