Cleaning up and adding comments
This commit is contained in:
@@ -1,10 +1,6 @@
|
||||
#include "TAVL.h"
|
||||
|
||||
#include <ios>
|
||||
#include <iostream>
|
||||
#include <unordered_set>
|
||||
#include <bits/ios_base.h>
|
||||
|
||||
#include "TTreeQueue.h"
|
||||
#include "Utils.h"
|
||||
|
||||
@@ -57,7 +53,10 @@ AVLNode *TAVL::rotateLeft(AVLNode *x)
|
||||
return y;
|
||||
}
|
||||
|
||||
// Comment out std::cout lines for no rotation output lines
|
||||
// Recursive AVL insert:
|
||||
// - Insert key as in a normal BST.
|
||||
// - Update node height.
|
||||
// - Compute balance factor and apply the appropriate rotation if unbalanced.
|
||||
AVLNode *TAVL::insert(AVLNode *n, const int key)
|
||||
{
|
||||
if (!n)
|
||||
@@ -74,23 +73,25 @@ AVLNode *TAVL::insert(AVLNode *n, const int key)
|
||||
|
||||
if (balance > 1 && key < n->left->key)
|
||||
{
|
||||
std::cout << "L-L rotation on [" << n->key << "]" << std::endl;
|
||||
//std::cout << "L-L rotation on [" << n->key << "]" << std::endl; <--- uncomment for terminal output of rotations
|
||||
return rotateRight(n);
|
||||
}
|
||||
|
||||
if (balance < -1 && key > n->right->key)
|
||||
{
|
||||
std::cout << "R-R rotation on [" << n->key << "]" << std::endl;
|
||||
//std::cout << "R-R rotation on [" << n->key << "]" << std::endl; <--- uncomment for terminal output of rotations
|
||||
return rotateLeft(n);
|
||||
}
|
||||
|
||||
if (balance > 1 && key > n->left->key)
|
||||
{ std::cout << "L-R rotation on [" << n->key << "]" << std::endl;
|
||||
{
|
||||
//std::cout << "L-R rotation on [" << n->key << "]" << std::endl; <--- uncomment for terminal output of rotations
|
||||
n->left = rotateLeft(n->left);
|
||||
return rotateRight(n);
|
||||
}
|
||||
if (balance < -1 && key < n->right->key)
|
||||
{ std::cout << "R-L rotation on [" << n->key << "]" << std::endl;
|
||||
{
|
||||
//std::cout << "R-L rotation on [" << n->key << "]" << std::endl; <--- uncomment for terminal output of rotations
|
||||
n->right = rotateRight(n->right);
|
||||
return rotateLeft(n);
|
||||
}
|
||||
@@ -144,11 +145,17 @@ void TAVL::levelorder(const AVLNode* node)
|
||||
}
|
||||
|
||||
// Public functions
|
||||
///<summary> Insert node </summary
|
||||
///<param name="key"> Node key value (int) </param>
|
||||
/// <returns> None </returns>
|
||||
void TAVL::Insert(const int key)
|
||||
{
|
||||
root = insert(root, key);
|
||||
}
|
||||
|
||||
///<summary> Inorder callback </summary
|
||||
///<param name=""> AVLNode *node </param>
|
||||
/// <returns> Bool </returns>
|
||||
bool TAVL::Inorder(const AVLNode *node)
|
||||
{
|
||||
if (!node)
|
||||
@@ -158,6 +165,9 @@ bool TAVL::Inorder(const AVLNode *node)
|
||||
return true;
|
||||
}
|
||||
|
||||
///<summary> Postorder callback </summary
|
||||
///<param name=""> AVLNode *node </param>
|
||||
/// <returns> Bool </returns>
|
||||
bool TAVL::Postorder(const AVLNode *node)
|
||||
{
|
||||
if (!node)
|
||||
@@ -167,6 +177,9 @@ bool TAVL::Postorder(const AVLNode *node)
|
||||
return true;
|
||||
}
|
||||
|
||||
///<summary> Preorder callback </summary
|
||||
///<param name=""> AVLNode *node </param>
|
||||
/// <returns> Bool </returns>
|
||||
bool TAVL::Preorder(const AVLNode *node)
|
||||
{
|
||||
if (!node)
|
||||
@@ -176,6 +189,9 @@ bool TAVL::Preorder(const AVLNode *node)
|
||||
return true;
|
||||
}
|
||||
|
||||
///<summary> LevelOrder callback </summary
|
||||
///<param name=""> AVLNode *node </param>
|
||||
/// <returns> Bool </returns>
|
||||
bool TAVL::LevelOrder(const AVLNode *node)
|
||||
{
|
||||
if (!node)
|
||||
@@ -185,6 +201,9 @@ bool TAVL::LevelOrder(const AVLNode *node)
|
||||
return true;
|
||||
}
|
||||
|
||||
///<summary> Prints the desired sorting order </summary
|
||||
///<param name="cb"> Callback for the desired ordering algorithm (e.g. PrintOrder(LevelOrder) will print the Level Order algorithm to the terminal)</param>
|
||||
/// <returns>None</returns>
|
||||
void TAVL::PrintOrder(FOrderTraversal cb)
|
||||
{
|
||||
if (!cb)
|
||||
@@ -192,6 +211,8 @@ void TAVL::PrintOrder(FOrderTraversal cb)
|
||||
cb(root);
|
||||
}
|
||||
|
||||
// Helper to build an AVL tree with 'count' unique random keys
|
||||
// in the range [minRange, maxRange]. Used only for demonstration in RunApp()
|
||||
///<summary> Populates AVL tree </summary
|
||||
///<param name="avl"> The AVL tree to be populated</param>
|
||||
///<param name"count">How many elements to be populated into the tree</param>
|
||||
@@ -205,7 +226,7 @@ void TAVL::Populate(TAVL* avl, const int count, const int minRange, const int ma
|
||||
int val = Utils::RandomInt(minRange, maxRange);
|
||||
while (AVLset.count(val))
|
||||
val = Utils::RandomInt(minRange, maxRange);
|
||||
std::cout << "Inserting [" << val << "]" << std::endl;
|
||||
//std::cout << "Inserting [" << val << "]" << std::endl; <----- Uncomment for terminal output of insertions
|
||||
avl->Insert(val);
|
||||
AVLset.insert(val);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#ifndef IKT203_COURSE_ASSIGNMENTS_TAVL_H
|
||||
#define IKT203_COURSE_ASSIGNMENTS_TAVL_H
|
||||
#include <unordered_set>
|
||||
|
||||
|
||||
// Node used in the AVL tree.
|
||||
// Stores only an integer key and height (no TEmployee data).
|
||||
struct AVLNode {
|
||||
int key;
|
||||
AVLNode* left;
|
||||
@@ -14,6 +14,8 @@ struct AVLNode {
|
||||
|
||||
typedef bool (*FOrderTraversal)(const AVLNode* AVLNode);
|
||||
|
||||
// Self-balancing AVL tree used to demonstrate rotations and traversals.
|
||||
// Only stores integer keys; no payload data is required for this assignment.
|
||||
class TAVL {
|
||||
private:
|
||||
AVLNode* root;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "TBST.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "TTreeQueue.h"
|
||||
|
||||
|
||||
@@ -11,10 +9,15 @@ void TBST::destroy(BSTNode *node)
|
||||
return;
|
||||
destroy(node->left);
|
||||
destroy(node->right);
|
||||
// TBST owns the TEmployee* stored in each node, so delete it here.
|
||||
delete node->data;
|
||||
delete node;
|
||||
}
|
||||
|
||||
///<summary> Insert node </summary
|
||||
///<param name="key"> Node key value (int) </param>
|
||||
///<param name="data"> Employee data (TEmployee) </param>
|
||||
/// <returns> None </returns>
|
||||
void TBST::Insert(const int key, TEmployee *data)
|
||||
{
|
||||
root = insert(root, key, data);
|
||||
@@ -30,12 +33,19 @@ BSTNode* TBST::insert(BSTNode* node, const int key, TEmployee *data)
|
||||
node->left = insert(node->left, key, data);
|
||||
else if (key > node->key)
|
||||
node->right = insert(node->right, key, data);
|
||||
else
|
||||
std::cout << "Error with node insertion" << std::endl;
|
||||
|
||||
else {
|
||||
// Duplicate key: do not modify the existing node.
|
||||
// 'data' was allocated by the caller, so we must delete it here
|
||||
// to avoid a memory leak.
|
||||
std::cout << "Duplicate key [" << key << "], ignoring insert." << std::endl;
|
||||
delete data;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
///<summary> Search for node </summary
|
||||
///<param name="key"> Node key value (int) </param>
|
||||
/// <returns> TEmployee </returns>
|
||||
TEmployee *TBST::Search(int key) const
|
||||
{
|
||||
const BSTNode* result = search(root, key);
|
||||
@@ -54,6 +64,9 @@ BSTNode* TBST::search(BSTNode* node, const int key)
|
||||
return search(node->right, key);
|
||||
}
|
||||
|
||||
///<summary> Delete node </summary
|
||||
///<param name="key"> Node key value (int) </param>
|
||||
/// <returns> None </returns>
|
||||
void TBST::Delete(const int key)
|
||||
{
|
||||
root = remove(root, key);
|
||||
@@ -88,7 +101,10 @@ BSTNode *TBST::remove(BSTNode *node, const int key)
|
||||
delete node;
|
||||
return child;
|
||||
}
|
||||
// Two children
|
||||
// Two children:
|
||||
// 1) Find the smallest node in the right subtree (inorder successor)
|
||||
// 2) Copy its key + data into the current node
|
||||
// 3) Remove the successor node from the right subtree
|
||||
else {
|
||||
BSTNode* minRight = findMin(node->right);
|
||||
node->key = minRight->key;
|
||||
@@ -106,8 +122,8 @@ BSTNode* TBST::findMin(BSTNode* node)
|
||||
return node;
|
||||
}
|
||||
|
||||
/// Traversals
|
||||
/// Private helpers
|
||||
// Traversals
|
||||
// Private helpers
|
||||
void TBST::preorder(const BSTNode* node)
|
||||
{
|
||||
if (!node)
|
||||
@@ -153,24 +169,32 @@ void TBST::levelorder(const BSTNode* node)
|
||||
}
|
||||
}
|
||||
|
||||
///<summary> Inorder sorting </summary
|
||||
/// <returns> None </returns>
|
||||
void TBST::Inorder() const
|
||||
{
|
||||
inorder(root);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
///<summary> Preorder sorting </summary
|
||||
/// <returns> None </returns>
|
||||
void TBST::Preorder() const
|
||||
{
|
||||
preorder(root);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
///<summary> Postorder sorting </summary
|
||||
/// <returns> None </returns>
|
||||
void TBST::Postorder() const
|
||||
{
|
||||
postorder(root);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
///<summary> LevelOrder sorting </summary
|
||||
/// <returns> None </returns>
|
||||
void TBST::LevelOrder() const
|
||||
{
|
||||
levelorder(root);
|
||||
|
||||
@@ -2,13 +2,19 @@
|
||||
#define IKT203_COURSE_ASSIGNMENTS_TBST_H
|
||||
#include "TEmployee.h"
|
||||
|
||||
// Node in the Binary Search Tree.
|
||||
// Owns a single TEmployee* which is deleted by TBST::destroy/remove.
|
||||
struct BSTNode {
|
||||
int key;
|
||||
TEmployee* data;
|
||||
int key; // employee ID
|
||||
TEmployee* data; // employee record
|
||||
BSTNode* left;
|
||||
BSTNode* right;
|
||||
};
|
||||
|
||||
// Standard Binary Search Tree for TEmployee* keyed by employee ID.
|
||||
// Responsibilities:
|
||||
// - Owns all TEmployee objects it contains.
|
||||
// - Provides insert, search, delete, and four traversal methods.
|
||||
class TBST {
|
||||
private:
|
||||
BSTNode* root;
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
|
||||
// Simple employee record used in Category 3.
|
||||
// 'id' is set later by IdGenerator and used as the BST key.
|
||||
struct TEmployee {
|
||||
std::string firstName;
|
||||
std::string lastName;
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
#define MAX_SIZE 200
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "TBST.h"
|
||||
|
||||
|
||||
// Fixed-size circular queue used by the BST and AVL level-order traversals.
|
||||
// Stores raw pointers to tree nodes (T*). Does not own the nodes.
|
||||
template <typename T>
|
||||
struct TTreeQueue {
|
||||
|
||||
@@ -22,7 +22,7 @@ struct TTreeQueue {
|
||||
void Enqueue(T* n)
|
||||
{
|
||||
if (n == nullptr)
|
||||
return;
|
||||
return; // ignore null pointers, nothing to enqueue
|
||||
if (IsFull())
|
||||
throw std::overflow_error("Queue Overflow");
|
||||
queue[tail] = n;
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
#include "option1.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
// Entry point for Category 3, Option 1.
|
||||
// Demonstrates:
|
||||
// 1) Building a BST of 200 employees from DATA/random_names.txt
|
||||
// 2) Running all BST traversals
|
||||
// 3) Searching and deleting by employee ID
|
||||
// 4) Building and printing an AVL tree with random integer keys
|
||||
int RunApp() {
|
||||
//Reading names from file for BST population
|
||||
bst = new TBST();
|
||||
/* Path to the names data file
|
||||
This is MY absolute path -- change to your local path for this to read properly
|
||||
something like "C:\Users\Username\FolderYouSavedTheSubmissionIn\Exam\IKT203Exam\DATA\random_names.txt"
|
||||
Double slash is needed for string to pass the correct file path */
|
||||
const std::string filename = "C:\\Users\\csand\\IKT203\\Exam\\IKT203Exam\\DATA\\random_names.txt";
|
||||
|
||||
// Read 200 employees from the names file and populate the BST.
|
||||
// IMPORTANT: Working directory must be the Portfolio/Assignment-03 folder
|
||||
// so that "DATA/random_names.txt" resolves correctly.
|
||||
const std::string filename = "DATA/random_names.txt";
|
||||
readNamesFromFile(filename, onNameRead);
|
||||
|
||||
// BST traversal -- comment out the entire block
|
||||
// when done inspecting for more manageable terminal output
|
||||
// --- BST traversals ---
|
||||
// These calls demonstrate all four traversal orders on the employee BST.
|
||||
// Comment out this block if the console output becomes too noisy.
|
||||
pack("Inorder traversal (sorted by ID)");
|
||||
bst->Inorder();
|
||||
|
||||
@@ -26,6 +32,8 @@ int RunApp() {
|
||||
pack("Postorder traversal");
|
||||
bst->Postorder();
|
||||
|
||||
// --- BST search demo ---
|
||||
// Ask the user for an ID, search in the BST, and print the matching employee (if any).
|
||||
pack("Search function");
|
||||
std::cout << "\nInput the ID you want to search for\n" << std::endl;
|
||||
int choice;
|
||||
@@ -36,6 +44,9 @@ int RunApp() {
|
||||
else
|
||||
std::cout << "ID not found" << std::endl;
|
||||
|
||||
// --- BST delete demo ---
|
||||
// Ask the user for an ID, delete it from the BST if it exists,
|
||||
// then print the new inorder traversal to show the updated structure.
|
||||
pack("Remove function");
|
||||
std::cout << "\nInput the ID you want to remove\n" << std::endl;
|
||||
std::cin >> choice;
|
||||
@@ -49,13 +60,13 @@ int RunApp() {
|
||||
bst->Inorder();
|
||||
// End of BST block
|
||||
|
||||
// Start of AVL block
|
||||
// Again, comment out the block if terminal output is
|
||||
// too noisy
|
||||
// --- AVL demo ---
|
||||
// Build an AVL tree using random integers in [1, 200].
|
||||
// This tree only stores keys (no TEmployee data) and is used
|
||||
// to demonstrate balancing and traversals.
|
||||
pack("AVL");
|
||||
avl = new TAVL;
|
||||
|
||||
|
||||
TAVL::Populate(avl, 100, 1, 200);
|
||||
pack("Inorder");
|
||||
avl->PrintOrder(TAVL::Inorder);
|
||||
@@ -71,9 +82,9 @@ int RunApp() {
|
||||
// End of AVL block
|
||||
|
||||
|
||||
// Cleaning to free up memory.
|
||||
// Used only at end of runtime, but useful for when runtime needs
|
||||
// to be continuous
|
||||
// --- Cleanup ---
|
||||
// TBST destructor deletes all TEmployee objects it owns.
|
||||
// Here we delete the tree objects themselves to avoid leaks.
|
||||
pack ("Cleaning up");
|
||||
delete bst;
|
||||
delete avl;
|
||||
|
||||
@@ -3,25 +3,24 @@
|
||||
#ifndef OPTION1_H
|
||||
#define OPTION1_H
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <TTreeQueue.h>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "TAVL.h"
|
||||
#include "TBST.h"
|
||||
#include "TEmployee.h"
|
||||
#include "Utils.h"
|
||||
#include "../../Submissions/Submission-04/BankAccount.h"
|
||||
|
||||
/// To keep track of used ID values to ensure
|
||||
/// all unique IDs
|
||||
// Global state for Category 3, Option 1:
|
||||
// - bst: owns all TEmployee objects (deleted in TBST destructor)
|
||||
// - avl: separate AVL tree used only to demonstrate balancing on int keys
|
||||
inline std::unordered_set<int> usedIds;
|
||||
static TBST* bst;
|
||||
static TAVL* avl;
|
||||
|
||||
int RunApp();
|
||||
|
||||
// Assign a unique random employee ID in the range [1, 1000].
|
||||
// Uses 'usedIds' to avoid duplicates so the BST always has unique keys.
|
||||
inline void IdGenerator(TEmployee* employee)
|
||||
{
|
||||
int id = Utils::RandomInt(1, 1000);
|
||||
@@ -32,6 +31,11 @@ inline void IdGenerator(TEmployee* employee)
|
||||
usedIds.insert(id);
|
||||
employee->id = id;
|
||||
}
|
||||
|
||||
// Callback used by readNamesFromFile.
|
||||
// - Creates a new TEmployee from the given name.
|
||||
// - Stops after 200 employees (as required by the assignment).
|
||||
// - Generates a unique ID and inserts the employee into the BST.
|
||||
static bool onNameRead(const int index, const int aTotalCount, const std::string& aFirstName, const std::string& aLastName)
|
||||
{
|
||||
const auto e = new TEmployee(aFirstName, aLastName);
|
||||
@@ -50,6 +54,7 @@ inline void printline()
|
||||
std::cout << "----------------------------------------" << std::endl;
|
||||
}
|
||||
|
||||
// Helper to visually separate different demos (traversals, search, etc.) in the console output.
|
||||
inline void pack(const std::string& line)
|
||||
{
|
||||
std::cout << "\n\n\n" << std::endl;
|
||||
|
||||
Reference in New Issue
Block a user