SDEV-324-81/week-02/Llewellyn_DA_week2.cpp

333 lines
11 KiB
C++
Raw Normal View History

2020-09-12 08:10:03 +00:00
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Champlain College SDEV-345-81
*
* C++ Week 2: Assignment (first semester) - Binary Search (2020/09/11)
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Given the following set of data [4.5,6,1,9.2,4,77,1200,16.4]
* find the value 9.2 and its index value using binary search.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Written by Llewellyn van der Merwe <llewellyn.vandermerw@mymail.champlain.edu>, September 2020
* Copyright (C) 2020. All Rights Reserved
* License GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include <vector>
using namespace std;
// Adaption from Starting out with C++ Early Objects (9 Edition)
// IntBinaryTree class - Chapter 19 on page 1130
// Binary Tree Class
class Btree
{
private:
// insert counter
int counter;
// internal object
struct BtreeNode
{
// insert position
int position;
// type of value
int type; // 1 = int; 2 = float;
// union value
union {
int ival;
float fval;
} value;
// tree pointers
BtreeNode* left;
BtreeNode* right;
// tree constructors
BtreeNode(int value1, int &counter, BtreeNode *left1 = nullptr, BtreeNode *right1 = nullptr) {
value.ival = value1;
left = left1;
right = right1;
type = 1;
position = counter++;
}
BtreeNode(float value1, int &counter, BtreeNode *left1 = nullptr, BtreeNode *right1 = nullptr) {
value.fval = value1;
left = left1;
right = right1;
type = 2;
position = counter++;
}
};
BtreeNode* root; // Pointer to the root of the tree
// Various helper member functions.
void insert(BtreeNode *&tree, int num) {
// If the tree is empty, make a new node and make it
// the root of the tree
if (!tree) {
tree = new BtreeNode(num, counter);
return;
}
// If num is already in tree:
if (tree->value.ival == num)
return;
// The tree is not empty: insert the new node into the
// left or right subtree
if ((tree->type == 1 && num < tree->value.ival) || (tree->type == 2 && num < tree->value.fval))
insert(tree->left, num);
else
insert(tree->right, num);
}
void insert(BtreeNode *&tree, float num) {
// If the tree is empty, make a new node and make it
// the root of the tree
if (!tree) {
tree = new BtreeNode(num, counter);
return;
}
// If num is already in tree:
if (tree->value.fval == num)
return;
// The tree is not empty: insert the new node into the
// left or right subtree
if ((tree->type == 1 && num < tree->value.ival) || (tree->type == 2 && num < tree->value.fval))
insert(tree->left, num);
else
insert(tree->right, num);
}
void destroySubtree(BtreeNode *tree) {
if (!tree) return;
destroySubtree(tree->left);
destroySubtree(tree->right);
// Delete the node at the root
delete tree;
}
void remove(BtreeNode *&tree, int num) {
if (tree == nullptr) return;
if ((tree->type == 1 && num < tree->value.ival) || (tree->type == 2 && num < tree->value.fval))
remove(tree->left, num);
else if ((tree->type == 1 && num > tree->value.ival) || (tree->type == 2 && num > tree->value.fval))
remove(tree->right, num);
else
// We have found the node to delete.
makeDeletion (tree);
}
void remove(BtreeNode *&tree, float num) {
if (tree == nullptr) return;
if ((tree->type == 1 && num < tree->value.ival) || (tree->type == 2 && num < tree->value.fval))
remove(tree->left, num);
else if ((tree->type == 1 && num > tree->value.ival) || (tree->type == 2 && num > tree->value.fval))
remove(tree->right, num);
else
// We have found the node to delete .
makeDeletion (tree);
}
void makeDeletion(BtreeNode *&tree) {
// Used to hold node that will be deleted
BtreeNode *nodeToDelete = tree;
// Used to locate the point where the
// left subtree is attached
BtreeNode *attachPoint;
if (tree->right == nullptr) {
// Replace tree with its left subtree
tree = tree->left ;
} else if (tree->left == nullptr) {
// Replace tree with its right subtree
tree = tree->right;
} else {
// The node has two children
// Move to right subtree
attachPoint = tree->right;
// Locate the smallest node in the right subtree
// by moving as far to the left as possible
while (attachPoint->left != nullptr)
attachPoint = attachPoint->left;
// Attach the left subtree of the original tree
// as the left subtree of the smallest node
// in the right subtree
attachPoint->left = tree->left;
// Replace the original tree with its right subtree
tree = tree->right;
}
// Delete root of original tree
delete nodeToDelete;
}
void displayInOrder(BtreeNode *tree) const {
if (tree) {
displayInOrder(tree->left);
if (tree->type == 1) {
cout << tree->value.ival << " ";
} else {
cout << tree->value.fval << " ";
}
displayInOrder(tree->right);
}
}
// thanks to https://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion/
void displayIndexOrder(BtreeNode *tree) const {
int size = counter + 1;
stack<BtreeNode *> s;
string order[size];
BtreeNode *current = tree;
while(current != NULL || s.empty() == false){
/* Reach the left most Node of the
curr Node */
while (current != NULL)
{
/* place pointer to a tree node on
the stack before traversing
the node's left subtree */
s.push(current);
current = current->left;
}
/* Current must be NULL at this point */
current = s.top();
s.pop();
// add to our order bucket (not ideal...)
stringstream val;
if (current->type == 1) {
val << current->value.ival;
} else {
val << current->value.fval;
}
order[current->position] = "[" + to_string(current->position) + "]=>" + val.str();
/* we have visited the node and its
left subtree. Now, it's right
subtree's turn */
current = current->right;
}
// no print out the values
for (int i = 0; i < size; i++){
cout << order[i] << " ";
}
}
public:
// These member functions are the public interface.
// Constructor
Btree () {
root = nullptr;
counter = 0;
}
// Destructor
~Btree () {
destroySubtree(root);
}
// insert function
void insert(int num) {
insert(root, num);
}
// insert function
void insert(float num) {
insert(root, num);
}
// search function
bool search(int num) const {
BtreeNode *tree = root;
while (tree)
{
if (tree->value.ival == num)
return true;
else if ((tree->type == 1 && num < tree->value.ival) || (tree->type == 2 && num < tree->value.fval))
tree = tree->left;
else
tree = tree->right;
}
return false;
}
bool search(float num) const {
BtreeNode *tree = root;
while (tree)
{
if (tree->value.fval == num)
return true;
else if ((tree->type == 1 && num < tree->value.ival) || (tree->type == 2 && num < tree->value.fval))
tree = tree->left;
else
tree = tree->right;
}
return false;
}
int searchPosition(int num) const {
BtreeNode *tree = root;
while (tree)
{
if (tree->value.ival == num)
return tree->position;
else if ((tree->type == 1 && num < tree->value.ival) || (tree->type == 2 && num < tree->value.fval))
tree = tree->left;
else
tree = tree->right;
}
return -1;
}
int searchPosition(float num) const {
BtreeNode *tree = root;
while (tree)
{
if (tree->value.fval == num)
return tree->position;
else if ((tree->type == 1 && num < tree->value.ival) || (tree->type == 2 && num < tree->value.fval))
tree = tree->left;
else
tree = tree->right;
}
return -1;
}
// remove a node
void remove(int num) {
remove(root, num);
}
// remove a node
void remove(float num) {
remove(root, num);
}
// show in order
void showInOrder(void) const {
displayInOrder(root);
}
// show in original input order
void showIndexOrder() const {
displayIndexOrder(root);
}
};
int main() {
Btree tree;
cout << "Inserting the numbers 4.5, 6, 1, 9.2, 4, 77, 1200, 16.4" << endl;
tree.insert(4.5f);
tree.insert(6);
tree.insert(1);
tree.insert( 9.2f);
tree.insert(4);
tree.insert(77);
tree.insert(1200);
tree.insert(16.4f);
cout << "Here are the values in the tree" << endl;
tree.showIndexOrder();
cout << "\nWe found 9.2 at position: " << tree.searchPosition(9.2f) << endl;
cout << "We found 1200 at position: " << tree.searchPosition(1200) << endl;
cout << "Deleting 9.2..." << endl;
tree.remove(9.2f);
cout << "Deleting 77..." << endl;
tree.remove(77);
cout << "Now, here are the nodes values sorted" << endl;
tree.showInOrder();
// with removal I am not yet fixing the index ordering ;)
return 0;
}