如何在SMLNJ中创建三元树?

如何在SMLNJ中创建三元树?,sml,smlnj,Sml,Smlnj,现在,我在SMLNJ中建立了一个二叉树模型,但是我想把这个模型改为在树的内部有一个树。(三叉树) 如果从二叉树的根开始 Binode with an (id1*(binode)) ß- a binary tree 然后,如果该“binode”作为元组的一部分定位:2Dbinode 该元组有一个标识符,其中的二元组是二元组树的根 2Dbinode (id2* (binode) *2Dbinode) 每一个都是3Dbinode的一部分,3Dbinode包括: 3Dbin

现在,我在SMLNJ中建立了一个二叉树模型,但是我想把这个模型改为在树的内部有一个树。(三叉树)

如果从二叉树的根开始

    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)
如果用户搜索不存在的节点: (30,(7,(30)))那么显示的路径将是

  • (25)
  • (30)
  • (30,7)
  • (30,7,30)未找到
如果用户希望在任何级别添加节点,应提示用户输入该节点的3位代码;再次显示路径。

  • EX:ADD(30,11,5)则显示为
    • (25)
    • (30)
    • (30、7)
    • (30,11)创建
    • (30,11,5)创建
按(a、B、C)的顺序打印3dbinode树的内容 删除节点 删除节点:EX:DEL(30,7,u) 那么结果就是 -(30、7、22)删除 -(30,7,0)创建

三元树? 编辑2:在您回顾了您的问题之后,似乎仍然不清楚在搜索时您希望如何导航此三元树。二叉搜索树根据元素的大小左右划分元素。您没有描述过类似的标准:您的函数何时应该使用第一、第二和第三分支?

编辑3:我已经提供了在三元树上工作的函数
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