Binary Tree program - Namir - 2025-09-22 08:45
Here is an HP Prime program (generated by Claude AI and needed some slight edits) that implements a binary tree structure using a global set of lists/arrays that store keys, data, and indices to left and right child nodes. After you run the program, you can view this information using the List option (Shift 7). You can run various programs to work with the binary tree:
1. TreeDemo performs a demo usage of the binary tree.
2. TreeInteractive is an interactive program that allows you to insert key/data information, delete nodes, print the binary tree, and so on.
3. TreeTest performs a comprhensive3 tree test.
4. TreeStats display the statistics of the binary tree.
5. TreePrint prints the nodes of the tree using indentation spaces.
The constant MAX_NODE specifies the maximum number of tree nodes and is currently set at 100.
I ran the code on my virtual emulator and not all PRINT command display results in the Terminal windows.
Save the list using a program name (e.g. binArrTree) and when you click on Run menu option you see the list of exported functions (including the ones i listed above). Click on the function you want to run.
Here is the code:
Code: // HP Prime Binary Tree Implementation Using Global Arrays
// Maximum number of nodes that can be stored
EXPORT MAX_NODES := 100;
// Global variables for the binary tree
EXPORT NodeCount; // Current number of nodes (0 = empty tree)
EXPORT nodeKeys; // Array of strings for key values
EXPORT nodeData; // Array of strings for data values
EXPORT nodeLeft; // Array of integers for left child indices (0 = null)
EXPORT nodeRight; // Array of integers for right child indices (0 = null)
EXPORT RootIndex; // Index of root node (0 = empty tree)
EXPORT FreeList; // List of available indices for reuse
// Initialize the binary tree data structures
EXPORT TreeInit()
BEGIN
LOCAL i;
NodeCount := 0;
RootIndex := 0;
FreeList := {};
// Initialize arrays with empty values
nodeKeys := {};
nodeData := {};
nodeLeft := {};
nodeRight := {};
// Pre-allocate arrays to MAX_NODES size
FOR i FROM 1 TO MAX_NODES DO
nodeKeys := CONCAT(nodeKeys, {""});
nodeData := CONCAT(nodeData, {""});
nodeLeft := CONCAT(nodeLeft, {0});
nodeRight := CONCAT(nodeRight, {0});
END;
RETURN "Tree initialized with " + STRING(MAX_NODES) + " slots";
END;
// Get next available index for a new node
EXPORT GetAvailableIndex()
BEGIN
LOCAL index;
// Check if we can reuse a freed index
IF SIZE(FreeList) > 0 THEN
index := FreeList[1];
FreeList := SUB(FreeList, 2, SIZE(FreeList));
RETURN index;
END;
// Find first unused index
FOR index FROM 1 TO MAX_NODES DO
IF nodeKeys[index] == "" THEN
RETURN index;
END;
END;
RETURN 0; // No space available
END;
// Create a new node at the given index
EXPORT CreateNode(index, key, data)
BEGIN
IF index <= 0 OR index > MAX_NODES THEN
RETURN 0; // Invalid index
END;
IF nodeKeys[index] <> "" THEN
RETURN 0; // Index already in use
END;
nodeKeys[index] := key;
nodeData[index] := data;
nodeLeft[index] := 0;
nodeRight[index] := 0;
NodeCount := NodeCount + 1;
RETURN 1; // Success
END;
// Delete node at given index (mark as free)
EXPORT DeleteNodeAt(index)
BEGIN
IF index <= 0 OR index > MAX_NODES THEN
RETURN 0;
END;
IF nodeKeys[index] == "" THEN
RETURN 0; // Already empty
END;
nodeKeys[index] := "";
nodeData[index] := "";
nodeLeft[index] := 0;
nodeRight[index] := 0;
NodeCount := NodeCount - 1;
// Add to free list for reuse
FreeList := CONCAT(FreeList, {index});
RETURN 1; // Success
END;
// Check if index represents a valid node
EXPORT IsValidNode(index)
BEGIN
IF index <= 0 OR index > MAX_NODES THEN
RETURN 0;
END;
RETURN nodeKeys[index] <> "";
END;
// Insert a new key-data pair into the tree
EXPORT TreeInsert(key, data)
BEGIN
LOCAL newIndex;
IF RootIndex == 0 THEN
// Tree is empty, create root
newIndex := GetAvailableIndex();
IF newIndex == 0 THEN
RETURN "Error: Tree is full!";
END;
IF CreateNode(newIndex, key, data) THEN
RootIndex := newIndex;
RETURN "Inserted root: " + STRING(key) + " = " + STRING(data);
ELSE
RETURN "Error: Could not create root node";
END;
ELSE
// Insert into existing tree
RootIndex := InsertHelper(RootIndex, key, data);
RETURN "Inserted: " + STRING(key) + " = " + STRING(data);
END;
END;
// Helper function for recursive insertion
EXPORT InsertHelper(currentIndex, key, data)
BEGIN
LOCAL newIndex;
// Base case: create new node
IF currentIndex == 0 THEN
newIndex := GetAvailableIndex();
IF newIndex == 0 THEN
PRINT("Error: No space available for new node");
RETURN 0;
END;
IF CreateNode(newIndex, key, data) THEN
RETURN newIndex;
ELSE
RETURN 0;
END;
END;
// Insert based on key comparison
IF key < nodeKeys[currentIndex] THEN
nodeLeft[currentIndex] := InsertHelper(nodeLeft[currentIndex], key, data);
ELSE
IF key > nodeKeys[currentIndex] THEN
nodeRight[currentIndex] := InsertHelper(nodeRight[currentIndex], key, data);
ELSE
// Key already exists, update data
nodeData[currentIndex] := data;
END;
END;
RETURN currentIndex;
END;
// Search for a key in the tree
EXPORT TreeSearch(key)
BEGIN
LOCAL foundIndex;
IF RootIndex == 0 THEN
RETURN "Tree is empty";
END;
foundIndex := SearchHelper(RootIndex, key);
IF foundIndex == 0 THEN
RETURN "Key '" + STRING(key) + "' not found";
ELSE
RETURN "Found: " + STRING(nodeKeys[foundIndex]) + " = " + STRING(nodeData[foundIndex]) + " at index " + STRING(foundIndex);
END;
END;
// Helper function for recursive search
EXPORT SearchHelper(currentIndex, key)
BEGIN
IF currentIndex == 0 OR NOT IsValidNode(currentIndex) THEN
RETURN 0; // Not found
END;
IF key == nodeKeys[currentIndex] THEN
RETURN currentIndex; // Found!
ELSE
IF key < nodeKeys[currentIndex] THEN
RETURN SearchHelper(nodeLeft[currentIndex], key);
ELSE
RETURN SearchHelper(nodeRight[currentIndex], key);
END;
END;
END;
// Find minimum node in subtree
EXPORT FindMin(currentIndex)
BEGIN
IF currentIndex == 0 THEN
RETURN 0;
END;
WHILE nodeLeft[currentIndex] <> 0 DO
currentIndex := nodeLeft[currentIndex];
END;
RETURN currentIndex;
END;
// Delete a node with the specified key
EXPORT TreeDelete(key)
BEGIN
LOCAL oldRoot;
IF RootIndex == 0 THEN
RETURN "Tree is empty - cannot delete";
END;
oldRoot := RootIndex;
RootIndex := DeleteHelper(RootIndex, key);
// Check if deletion was successful
IF SearchHelper(RootIndex, key) == 0 THEN
RETURN "Deleted: " + STRING(key);
ELSE
RETURN "Key '" + STRING(key) + "' not found for deletion";
END;
END;
// Helper function for recursive deletion
EXPORT DeleteHelper(currentIndex, key)
BEGIN
LOCAL successorIndex, temp;
IF currentIndex == 0 OR NOT IsValidNode(currentIndex) THEN
RETURN 0; // Key not found
END;
IF key < nodeKeys[currentIndex] THEN
nodeLeft[currentIndex] := DeleteHelper(nodeLeft[currentIndex], key);
ELSE
IF key > nodeKeys[currentIndex] THEN
nodeRight[currentIndex] := DeleteHelper(nodeRight[currentIndex], key);
ELSE
// Node to delete found
// Case 1: No left child
IF nodeLeft[currentIndex] == 0 THEN
temp := nodeRight[currentIndex];
DeleteNodeAt(currentIndex);
RETURN temp;
ELSE
// Case 2: No right child
IF nodeRight[currentIndex] == 0 THEN
temp := nodeLeft[currentIndex];
DeleteNodeAt(currentIndex);
RETURN temp;
END;
END;
// Case 3: Two children
successorIndex := FindMin(nodeRight[currentIndex]);
// Copy successor's content to current node
nodeKeys[currentIndex] := nodeKeys[successorIndex];
nodeData[currentIndex] := nodeData[successorIndex];
// Delete the successor
nodeRight[currentIndex] := DeleteHelper(nodeRight[currentIndex], nodeKeys[successorIndex]);
END;
END;
RETURN currentIndex;
END;
// In-order traversal of the tree
EXPORT TreeTraverse()
BEGIN
LOCAL result;
IF RootIndex == 0 THEN
RETURN "Tree is empty";
END;
result := {};
InOrderHelper(RootIndex, result);
RETURN result;
END;
// Helper function for in-order traversal
EXPORT InOrderHelper(currentIndex, result)
BEGIN
IF currentIndex <> 0 AND IsValidNode(currentIndex) THEN
// Traverse left
InOrderHelper(nodeLeft[currentIndex], result);
// Visit current
result := CONCAT(result, {{nodeKeys[currentIndex], nodeData[currentIndex]}});
// Traverse right
InOrderHelper(nodeRight[currentIndex], result);
END;
END;
// Print the tree structure
EXPORT TreePrint()
BEGIN
PRINT("Tree Structure:");
PRINT("===============");
IF RootIndex == 0 THEN
PRINT("Tree is empty");
ELSE
PRINT("Root index: " + STRING(RootIndex));
PrintTreeHelper(RootIndex, 0);
END;
PRINT("===============");
END;
// Helper function for printing tree structure
EXPORT PrintTreeHelper(currentIndex, indent)
BEGIN
LOCAL spaces, i;
IF currentIndex <> 0 AND IsValidNode(currentIndex) THEN
// Print right subtree
PrintTreeHelper(nodeRight[currentIndex], indent + 4);
// Print current node with indentation
spaces := "";
FOR i FROM 1 TO indent DO
spaces := spaces + " ";
END;
PRINT(spaces + STRING(nodeKeys[currentIndex]) + "(" + STRING(nodeData[currentIndex]) + ")[" + STRING(currentIndex) + "]");
// Print left subtree
PrintTreeHelper(nodeLeft[currentIndex], indent + 4);
END;
END;
// Display tree statistics
EXPORT TreeStats()
BEGIN
LOCAL usedNodes, i;
usedNodes := 0;
FOR i FROM 1 TO MAX_NODES DO
IF nodeKeys[i] <> "" THEN
usedNodes := usedNodes + 1;
END;
END;
PRINT("Tree Statistics:");
PRINT("================");
PRINT("Nodes in use: " + STRING(usedNodes) + "/" + STRING(MAX_NODES));
PRINT("NodeCount variable: " + STRING(NodeCount));
PRINT("Root index: " + STRING(RootIndex));
PRINT("Free indices available: " + STRING(SIZE(FreeList)));
PRINT("Memory utilization: " + STRING(IP(1000 * usedNodes / MAX_NODES) / 10) + "%");
PRINT("================");
END;
// Level-order traversal
EXPORT TreeLevelOrder()
BEGIN
LOCAL queue, result, currentIndex, front;
IF RootIndex == 0 THEN
RETURN "Tree is empty";
END;
queue := {RootIndex};
result := {};
WHILE SIZE(queue) > 0 DO
currentIndex := queue[1];
queue := SUB(queue, 2, SIZE(queue));
IF IsValidNode(currentIndex) THEN
result := CONCAT(result, {{nodeKeys[currentIndex], nodeData[currentIndex], currentIndex}});
IF nodeLeft[currentIndex] <> 0 THEN
queue := CONCAT(queue, {nodeLeft[currentIndex]});
END;
IF nodeRight[currentIndex] <> 0 THEN
queue := CONCAT(queue, {nodeRight[currentIndex]});
END;
END;
END;
RETURN result;
END;
// Display array contents for debugging
EXPORT DebugArrays()
BEGIN
LOCAL i;
PRINT("Array Contents (first 20 slots):");
PRINT("=================================");
PRINT("Idx | Key | Data | Left | Right");
PRINT("----|----------|----------|------|------");
FOR i FROM 1 TO MIN(20, MAX_NODES) DO
IF nodeKeys[i] <> "" THEN
PRINT(STRING(i) + " | " + nodeKeys[i] + " | " + nodeData[i] + " | " + STRING(nodeLeft[i]) + " | " + STRING(nodeRight[i]));
END;
END;
PRINT("=================================");
IF NodeCount > 20 THEN
PRINT("... and " + STRING(NodeCount - 20) + " more nodes");
END;
END;
// Comprehensive test function
EXPORT TreeTest()
BEGIN
LOCAL i, pair, inOrderResult, item, afterDeleteResult;
LOCAL levelOrderResult;
PRINT("=== HP Prime Array-Based Binary Tree Test ===");
PRINT("");
// Test 1: Initialize tree
PRINT("Test 1: Initialization");
PRINT("----------------------");
PRINT(TreeInit());
TreeStats();
PRINT("");
// Test 2: Basic insertions
PRINT("Test 2: Basic insertions");
PRINT("------------------------");
PRINT(TreeInsert("dog", "loyal pet"));
PRINT(TreeInsert("cat", "independent"));
PRINT(TreeInsert("bird", "flies"));
PRINT(TreeInsert("fish", "swims"));
PRINT(TreeInsert("elephant", "large mammal"));
PRINT(TreeInsert("ant", "tiny insect"));
PRINT(TreeInsert("zebra", "striped"));
PRINT("");
TreeStats();
PRINT("");
// Test 3: Search operations
PRINT("Test 3: Search operations");
PRINT("-------------------------");
PRINT(TreeSearch("cat"));
PRINT(TreeSearch("dog"));
PRINT(TreeSearch("elephant"));
PRINT(TreeSearch("unicorn")); // Not found
PRINT("");
// Test 4: Tree traversals
PRINT("Test 4: Tree traversals");
PRINT("-----------------------");
inOrderResult := TreeTraverse();
PRINT("In-order traversal:");
FOR i FROM 1 TO SIZE(inOrderResult) DO
pair := inOrderResult[i];
PRINT(" " + STRING(pair[1]) + " : " + STRING(pair[2]));
END;
PRINT("");
levelOrderResult := TreeLevelOrder();
PRINT("Level-order traversal:");
FOR i FROM 1 TO SIZE(levelOrderResult) DO
item := levelOrderResult[i];
PRINT(" " + STRING(item[1]) + " : " + STRING(item[2]) + " [index " + STRING(item[3]) + "]");
END;
PRINT("");
// Test 5: Tree structure
PRINT("Test 5: Tree structure");
PRINT("----------------------");
TreePrint();
PRINT("");
// Test 6: Array debugging
PRINT("Test 6: Array contents");
PRINT("----------------------");
DebugArrays();
PRINT("");
// Test 7: Deletion operations
PRINT("Test 7: Deletion operations");
PRINT("---------------------------");
PRINT(TreeDelete("cat"));
PRINT(TreeDelete("elephant"));
PRINT(TreeDelete("unicorn")); // Not found
PRINT("");
PRINT("Tree after deletions:");
afterDeleteResult := TreeTraverse();
FOR i FROM 1 TO SIZE(afterDeleteResult) DO
pair := afterDeleteResult[i];
PRINT(" " + STRING(pair[1]) + " : " + STRING(pair[2]));
END;
PRINT("");
TreePrint();
PRINT("");
// Test 8: Test index reuse
PRINT("Test 8: Index reuse after deletion");
PRINT("-----------------------------------");
PRINT(TreeInsert("bear", "omnivore"));
PRINT(TreeInsert("rabbit", "herbivore"));
PRINT("");
DebugArrays();
TreeStats();
PRINT("");
RETURN "All tests completed!";
END;
// Interactive tree operations
EXPORT TreeInteractive()
BEGIN
LOCAL choice, key, data;
LOCAL i, result, pair;
PRINT("=== Interactive HP Prime Tree ===");
TreeInit();
REPEAT
PRINT("");
PRINT("1. Insert key-data pair");
PRINT("2. Search for key");
PRINT("3. Delete key");
PRINT("4. Show tree structure");
PRINT("5. Show traversal");
PRINT("6. Show statistics");
PRINT("7. Debug arrays");
PRINT("0. Exit");
INPUT(choice, "Enter choice (0-7):");
CASE
IF choice == 1 THEN
INPUT(key, "Enter key:");
INPUT(data, "Enter data:");
PRINT(TreeInsert(key, data));
END;
IF choice == 2 THEN
INPUT(key, "Enter key to search:");
PRINT(TreeSearch(key));
END;
IF choice == 3 THEN
INPUT(key, "Enter key to delete:");
PRINT(TreeDelete(key));
END;
IF choice == 4 THEN
TreePrint();
END;
IF choice == 5 THEN
result := TreeTraverse();
PRINT("Tree traversal:");
FOR i FROM 1 TO SIZE(result) DO
pair := result[i];
PRINT(" " + STRING(pair[1]) + " : " + STRING(pair[2]));
END;
END;
IF choice == 6 THEN
TreeStats();
END;
IF choice == 7 THEN
DebugArrays();
END;
DEFAULT
// choice == 0 or invalid
END;
UNTIL choice == 0;
RETURN "Interactive session ended";
END;
// Quick demo function
EXPORT TreeDemo()
BEGIN
LOCAL i, result, pair;
PRINT("=== Quick HP Prime Tree Demo ===");
TreeInit();
// Add some sample data
TreeInsert("cherry", "small red fruit");
TreeInsert("banana", "yellow fruit");
TreeInsert("apple", "red fruit");
TreeInsert("date", "sweet fruit");
TreeInsert("elderberry", "purple berry");
PRINT("");
PRINT("Sample tree created:");
result := TreeTraverse();
FOR i FROM 1 TO SIZE(result) DO
pair := result[i];
PRINT(STRING(pair[1]) + " : " + STRING(pair[2]));
END;
PRINT("");
TreePrint();
PRINT("");
PRINT("Search test:");
PRINT(TreeSearch("banana"));
PRINT(TreeSearch("grape")); // Not found
TreeStats();
RETURN "Demo completed!";
END;
|