POV-Ray : Newsgroups : povray.text.scene-files : "bst.inc" A Binary Search Tree : "bst.inc" A Binary Search Tree Server Time
27 Jul 2024 12:08:54 EDT (-0400)
  "bst.inc" A Binary Search Tree  
From: ingo
Date: 6 Jun 2024 13:00:00
Message: <web.6661ea63cce2064317bac71e8ffb8ce3@news.povray.org>
Run the file as is for some demo output.

ingo

---%<------%<------%<---
/*
POV-Ray include file: bst.inc

Author : Ingo Janssen
Date   : 2024-03-16
Version: 0.5

A POV-Ray include file for a Binary Seach Tree (BST)
*/

#version 3.7;

#declare _Sentinel = -999999;

// Enums for BST struct
#declare _bstNodeVal = 0;
#declare _bstLeft    = 1;
#declare _bstRight   = 2;
#declare _bstSize    = 3;

#macro BSTDebug(BST)
  #for(I, 0, dimension_size(BST[_bstNodeVal], 1) - 1)
    #debug concat("Value : ",str(BSTree[_bstNodeVal][I], 14, -1), ",  ")
    #debug concat("Left  : ",str(BSTree[_bstLeft][I], 7, 0), ",  ")
    #debug concat("Right : ",str(BSTree[_bstRight][I], 7, 0), "\n")
  #end
  #debug"\n"
#end

#macro BSTInit(MaxNodes)
  /*InitBST(MaxNodes)
  Creates a "struct" for a Binar Search Tree.

  Parameters:
    MaxNodes (int): maximum nuber of nodes the tree can contain.

  Result:
    Returns an array of arrays
    array{
      array[MaxNodes]; // Value array
      array[MaxNodes]; // Left pointer array
      array[MaxNodes]; // Right pointer arra
      array[1];        // BST size, is updated during inserts
    };

  */
  #local BST = array[4];
  #local BST[_bstNodeVal] = array[MaxNodes]; // Value array
  #local BST[_bstLeft]    = array[MaxNodes]; // Left pointer array
  #local BST[_bstRight]   = array[MaxNodes]; // Right pointer array
  #local BST[_bstSize]    = array[1];

  #local BST[_bstSize][0] = 0;
  #for(I, 0, MaxNodes-1)
    #local BST[_bstNodeVal][I] = _Sentinel;
    #local BST[_bstLeft][I]    = _Sentinel;
    #local BST[_bstRight][I]   = _Sentinel;
  #end
  BST
#end


#macro BSTInsert(BST, Value)
  /*: BSTInsert(BST, Value)
  Insert data in the BST.
  */
  //#debug concat("\nBSTsize: ",str(BST[_bstSize][0],0,0), "\n\n")
  #if(BST[_bstSize][0] < dimension_size(BST[_bstNodeVal], 1))
    #local Node = 0;
    #local NodeAdded = false;
    #while(NodeAdded = false)
      #if(BST[_bstNodeVal][Node] = _Sentinel)

        // Found an empty node, insert the value here
        #local BST[_bstNodeVal][Node] = Value;
        #local BST[_bstSize][0] = BST[_bstSize][0] + 1;
        #local NodeAdded = true;

      #else

        #if(Value < BST[_bstNodeVal][Node])
          #if(BST[_bstLeft][Node] = _Sentinel)
            // Found an empty left child, insert the value here
            #local BST[_bstLeft][Node] = BST[_bstSize][0];
            #local BST[_bstNodeVal][BST[_bstSize][0]] = Value;
            #local BST[_bstSize][0] = BST[_bstSize][0] + 1;
            #local NodeAdded = true;
          #else
            // Traverse the left subtree
            #local Node = BST[_bstLeft][Node];
          #end

        #else

           #if(Value > BST[_bstNodeVal][Node])
            #if(BST[_bstRight][Node] = _Sentinel)
              // Found an empty right child, insert the value here
              #local BST[_bstRight][Node] = BST[_bstSize][0];
              #local BST[_bstNodeVal][BST[_bstSize][0]] = Value;
              #local BST[_bstSize][0] = BST[_bstSize][0] + 1;
              #local NodeAdded = true;
            #else
              // Traverse the right subtree
              #local Node = BST[_bstRight][Node];
            #end
          #else
            // Value already exists in the tree, do nothing
            #local NodeAdded = true;
          #end
        #end

      #end
    #end
  #else
    #error "Binary search tree is full"
  #end
#end


#macro BSTSearch(BST, Value)
  /*: BSTSearch(BST, Value)
  Finds the index the given value is at.
  Returns -1 if the value is not found in the BST.
  */
  #local Node = 0;
  #while(Node != _Sentinel)
    #if(Value < BST[_bstNodeVal][Node])
      #local Node = BST[_bstLeft][Node];
    #else
      #if(Value > BST[_bstNodeVal][Node])
        #local Node = BST[_bstRight][Node];
      #else
        // Value found in the tree
        #break
      #end
    #end
  #end
  Node
#end


#macro BSTMinVal(BST, Node)
  /*: BSTMinVal(BST, Node)

  Returns the minimum value in the tree, starting from Node.
  */
  #while(BST[_bstLeft][Node] != _Sentinel)
    #local Node = BST[_bstLeft][Node];
  #end
  BST[_bstNodeVal][Node]
#end

#macro BSTMinIdx(BST, Node)
  /*: BSTMinIdx(BST, Node)

  Returns the index of the minimum value in the tree, starting from Node.
  */
  #while(BST[_bstLeft][Node] != _Sentinel)
    #local Node = BST[_bstLeft][Node];
  #end
  Node
#end


#macro BSTiot(BST, Node)
  /*: BSTiot(BST, Node)

  BST In Order Traversal : Left - Root - Right pattern traversal of the tree,
  starting from Node

  Returns an array with values.
  */
  #macro _BSTIOTraverse(BST, Node, Traversed, I)
    #if(Node != _Sentinel)
      // Visit the left subtree
      _BSTIOTraverse(BST, BST[_bstLeft][Node], Traversed, I)
      // Visit the current node
      //#debug concat("Node : ", str(Node,0,0)," Value :
",str(BST[_bstNodeVal][Node], 0, 0), "\n")
      #local Traversed[I] = BST[_bstNodeVal][Node];
      #local I = I + 1;
      // Visit the right subtree
      _BSTIOTraverse(BST, BST[_bstRight][Node], Traversed, I)
    #end
  #end
  #local I = 0;
  #local Traversed = array[dimension_size(BST[_bstNodeVal],1)];
  _BSTIOTraverse(BST, Node, Traversed, I)
  Traversed
#end


#macro BSTpre(BST, Node)
  /*: BSTpre(BST, Node)
  BST Pre Order Traversal: Root - Left - Right pattern traversal of the tree,
  starting from Node

  Returns an array with values.
  */
  #macro _BSTpreTraverse(BST, Node, Traversed, I)
    #if(Node != _Sentinel)
      //#debug concat("Node : ", str(Node,0,0)," Value :
",str(BST[_bstNodeVal][Node], 0, 0), "\n")
      #local Traversed[I] = BST[_bstNodeVal][Node];
      #local I = I + 1;
      _BSTpreTraverse(BST, BST[_bstLeft][Node] , Traversed, I)
      _BSTpreTraverse(BST, BST[_bstRight][Node], Traversed, I)
    #end
  #end
  #local I = 0;
  #local Traversed = array[dimension_size(BST[_bstNodeVal],1)];
  _BSTpreTraverse(BST, Node, Traversed, I)
  Traversed
#end


#macro BSTpro(BST, Node)
  /*: BSTpost(BST, Node)
  BST Post Order Traversal: Left - Right - Root patern traversal of the tree,
  starting from Node.

  Returns an array with values.
  */
  #macro _BSTpostTraverse(BST, Node, Traversed, I)
    #if(Node != _Sentinel)
      _BSTpostTraverse(BST, BST[_bstLeft][Node] , Traversed, I)
      _BSTpostTraverse(BST, BST[_bstRight][Node], Traversed, I)
      //#debug concat("Node : ", str(Node,0,0)," Value :
",str(BST[_bstNodeVal][Node], 0, 0), "\n")
    #end
  #end
  #local I = 0;
  #local Traversed = array[dimension_size(BST[_bstNodeVal],1)];
  _BSTpostTraverse(BST, Node, Traversed, I)
  Traversed
#end


#macro BSTDelete(BST, Value)
  /*: BSTDelete(BST, Value)

  Deletes the given value from the BST.
  */

  #local Root = 0;
  #local NodeToDelete = BSTSearch(BST, Value);

  #if (NodeToDelete != _Sentinel)
    // Node found, proceed with deletion
    #local ParentOfNodeToDelete = _Sentinel;

    // Find the parent of the node to be deleted
    #while (Root != NodeToDelete)
      #if (Value < BST[_bstNodeVal][Root])
        #local ParentOfNodeToDelete = Root;
        #local Root = BST[_bstLeft][Root];
      #else
        #local ParentOfNodeToDelete = Root;
        #local Root = BST[_bstRight][Root];
      #end
    #end

    // Handle the case of a leaf node
    #if (BST[_bstLeft][NodeToDelete] = _Sentinel & BST[_bstRight][NodeToDelete]
= _Sentinel)
      #if (ParentOfNodeToDelete = _Sentinel)
        // Node to be deleted is the root node
        #local BST[_bstNodeVal][0] = _Sentinel;
        #local BST[_bstLeft][0] = _Sentinel;
        #local BST[_bstRight][0] = _Sentinel;
      #else
        #if (BST[_bstNodeVal][ParentOfNodeToDelete] > Value)
          #local BST[_bstLeft][ParentOfNodeToDelete] = _Sentinel;
        #else
          #local BST[_bstRight][ParentOfNodeToDelete] = _Sentinel;
        #end
      #end
    #end

    // Handle the case of a node with one child
    #if (BST[_bstLeft][NodeToDelete] != _Sentinel & BST[_bstRight][NodeToDelete]
= _Sentinel)
      #if (ParentOfNodeToDelete = _Sentinel)
        // Node to be deleted is the root node
        #local BST[_bstNodeVal][0] =
BST[_bstNodeVal][BST[_bstLeft][NodeToDelete]];
        #local BST[_bstLeft][0] = BST[_bstLeft][BST[_bstLeft][NodeToDelete]];
        #local BST[_bstRight][0] = BST[_bstRight][BST[_bstLeft][NodeToDelete]];
      #else
        #if (BST[_bstNodeVal][ParentOfNodeToDelete] > Value)
          #local BST[_bstLeft][ParentOfNodeToDelete] =
BST[_bstLeft][NodeToDelete];
        #else
          #local BST[_bstRight][ParentOfNodeToDelete] =
BST[_bstLeft][NodeToDelete];
        #end
      #end
    #elseif (BST[_bstLeft][NodeToDelete] = _Sentinel &
BST[_bstRight][NodeToDelete] != _Sentinel)
      #if (ParentOfNodeToDelete = _Sentinel)
        // Node to be deleted is the root node
        #local BST[_bstNodeVal][0] =
BST[_bstNodeVal][BST[_bstRight][NodeToDelete]];
        #local BST[_bstLeft][0] = BST[_bstLeft][BST[_bstRight][NodeToDelete]];
        #local BST[_bstRight][0] = BST[_bstRight][BST[_bstRight][NodeToDelete]];
      #else
        #if (BST[_bstNodeVal][ParentOfNodeToDelete] > Value)
          #local BST[_bstLeft][ParentOfNodeToDelete] =
BST[_bstRight][NodeToDelete];
        #else
          #local BST[_bstRight][ParentOfNodeToDelete] =
BST[_bstRight][NodeToDelete];
        #end
      #end
    #end

    // Handle the case of a node with two children
    #if (BST[_bstLeft][NodeToDelete] != _Sentinel & BST[_bstRight][NodeToDelete]
!= _Sentinel)
      // Find the in-order successor (smallest value in the right subtree)
      #local InOrderSuccessor = BSTMinIdx(BST, BST[_bstRight][NodeToDelete]);

      // Copy the value of the in-order successor to the node to be deleted
      #local BST[_bstNodeVal][NodeToDelete] =
BST[_bstNodeVal][InOrderSuccessor];

      // Delete the in-order successor node
      BSTDelete(BST, BST[_bstNodeVal][InOrderSuccessor]);
    #end

    // Decrement the size of the BST
    #local BST[_bstSize][0] = BST[_bstSize][0] - 1;

  #else
    // Node not found, do nothing
  #end
#end



//=====

#if(input_file_name="bst.inc")

#declare MAX_NODES = 15; // Maximum number of nodes in the tree
                         // for demo sake a bigger array then used is defined
#declare BSTree = BSTInit(MAX_NODES);

#declare ValArr = array[13]{3.33,432,90,pi,6,8,-1,34,9,0,13,12,23};
#for(I, 0, dimension_size(ValArr,1) - 1)
  BSTInsert(BSTree, ValArr[I])
  #debug concat("I : ", str(I, 1, 1), "\n")
  BSTDebug(BSTree)
#end
#debug "\n"


#declare SearchVal = 90;
#declare IsNode = BSTSearch(BSTree, SearchVal);
#debug concat("Searched value ",str(SearchVal,7,-1) ," is at index ",
str(IsNode, 0, 0),"\n\n")


#debug concat("The MinVal is ", str(BSTMinVal(BSTree, 5),7,-1)," and is at index
", str(BSTMinIdx(BSTree, 5),0,0),"\n\n")


#declare InOrderVals = BSTiot(BSTree, 0);
#debug "BSTiot : "
#for(I, 0, dimension_size(InOrderVals,1) - 1)
  #if(defined(InOrderVals[I]))  // because one can define a bigger array than is
actually used.
    #debug concat(str(InOrderVals[I],7,-1), ", ")
  #end
#end
#debug "\n\n"


#declare PreOrderVals = BSTpre(BSTree, 0);
#debug "BSTpre : "
#for(I, 0, dimension_size(PreOrderVals,1) - 1)
  #if(defined(PreOrderVals[I]))
    #debug concat(str(PreOrderVals[I],7,-1), ", ")
  #end
#end
#debug "\n\n"


#declare PostOrderVals = BSTpre(BSTree, 0);
#debug "BSTpost: "
#for(I, 0, dimension_size(PostOrderVals,1) - 1)
  #if(defined(PostOrderVals[I]))
    #debug concat(str(PostOrderVals[I],7,-1), ", ")
  #end
#end
#debug "\n\n"


BSTDelete(BSTree, 12)
#declare InOrderVals = BSTiot(BSTree, 0);
#debug "BSTiot : "
#for(I, 0, dimension_size(InOrderVals,1) - 1)
  #if(defined(InOrderVals[I]))  // because one can define a bigger array than is
actually used.
    #debug concat(str(InOrderVals[I],7,-1), ", ")
  #end
#end
#debug "\n\n"

BSTDebug(BSTree)


#debug "\n"
#end // if inc..
---%<------%<------%<---


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.