Why are the unique pointers annoying to use
This commit is contained in:
parent
f3de22da46
commit
8370fa19f1
@ -1,37 +1,69 @@
|
|||||||
#ifndef TREES_HPP
|
#ifndef TREES_HPP
|
||||||
#define TREES_HPP
|
#define TREES_HPP
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// Namespace for different implementations of trees
|
// Namespace for different implementations of trees
|
||||||
namespace tree_implementation
|
namespace tree_implementation
|
||||||
{
|
{
|
||||||
// Base Tree class
|
// General nodes for Tree
|
||||||
class Tree
|
struct TreeNode
|
||||||
|
{
|
||||||
|
std::string key;
|
||||||
|
std::string color;
|
||||||
|
std::unique_ptr<TreeNode> leftChild;
|
||||||
|
std::unique_ptr<TreeNode> rightChild;
|
||||||
|
std::unique_ptr<TreeNode> parent;
|
||||||
|
TreeNode(std::string word);
|
||||||
|
~TreeNode(void);
|
||||||
|
TreeNode(const TreeNode& rhs);
|
||||||
|
TreeNode& operator=(const TreeNode& rhs);
|
||||||
|
};
|
||||||
|
|
||||||
|
// General list for Tree
|
||||||
|
class TreeList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Tree(void);
|
std::unique_ptr<TreeNode> head;
|
||||||
void Insert(void);
|
TreeList(void);
|
||||||
void Search(void);
|
void InsertAtStart(std::string word);
|
||||||
void InOrderTreeTraversal(void);
|
void InsertAtEnd(std::string word);
|
||||||
|
void InsertAtPosition(std::string word);
|
||||||
|
void Remove(std::string word);
|
||||||
|
void Print(void);
|
||||||
protected:
|
protected:
|
||||||
virtual void PrintParentKey(std::string key) = 0;
|
;
|
||||||
virtual void PrintLeftChild(std::string key) = 0;
|
|
||||||
virtual void PrintRightChild(std::string key) = 0;
|
|
||||||
virtual void PrintPathToRoot(std::string key) = 0;
|
|
||||||
private:
|
private:
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Binary Search Tree operations
|
// Base Tree class
|
||||||
// TODO: Implement BST
|
class TreeInterface
|
||||||
class BinarySearchTree : public Tree
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
TreeList tree;
|
||||||
|
TreeInterface(void);
|
||||||
|
TreeNode* Search(std::string wordToFind);
|
||||||
|
bool IsSearchSuccessful(std::unique_ptr<TreeNode> foundNode);
|
||||||
|
void InOrderTreeTraversal(std::unique_ptr<TreeNode> viewedNode);
|
||||||
void PrintParentKey(std::string key);
|
void PrintParentKey(std::string key);
|
||||||
void PrintLeftChild(std::string key);
|
void PrintLeftChild(std::string key);
|
||||||
void PrintRightChild(std::string key);
|
void PrintRightChild(std::string key);
|
||||||
|
protected:
|
||||||
|
virtual void Insert(std::unique_ptr<TreeNode> z);
|
||||||
|
virtual void PrintPathToRoot(std::string key) = 0;
|
||||||
|
private:
|
||||||
|
TreeNode* Insert(std::unique_ptr<TreeNode> root, std::unique_ptr<TreeNode> newNode);
|
||||||
|
TreeNode* Search(std::unique_ptr<TreeNode> viewedNode, std::string wordToFind);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Binary Search Tree operations
|
||||||
|
class BinarySearchTree : public TreeInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Insert(std::string keyToInsert);
|
||||||
void PrintPathToRoot(std::string key);
|
void PrintPathToRoot(std::string key);
|
||||||
protected:
|
protected:
|
||||||
;
|
;
|
||||||
@ -40,13 +72,10 @@ namespace tree_implementation
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Red-Black Tree operations
|
// Red-Black Tree operations
|
||||||
// TODO: Implement Red-black tree
|
class RedBlackTree : public TreeInterface
|
||||||
class RedBlackTree : public Tree
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void PrintParentKey(std::string key);
|
void Insert(std::string keyToInsert);
|
||||||
void PrintLeftChild(std::string key);
|
|
||||||
void PrintRightChild(std::string key);
|
|
||||||
void PrintPathToRoot(std::string key);
|
void PrintPathToRoot(std::string key);
|
||||||
void PrintColor(std::string key);
|
void PrintColor(std::string key);
|
||||||
void PrintParentColor(std::string key);
|
void PrintParentColor(std::string key);
|
||||||
@ -54,7 +83,10 @@ namespace tree_implementation
|
|||||||
protected:
|
protected:
|
||||||
;
|
;
|
||||||
private:
|
private:
|
||||||
;
|
void InsertFixup(std::unique_ptr<TreeNode> z);
|
||||||
|
std::unique_ptr<TreeNode> GetUncleNode(std::unique_ptr<TreeNode> startNode);
|
||||||
|
void LeftRotate(std::unique_ptr<TreeNode> x);
|
||||||
|
void RightRotate(std::unique_ptr<TreeNode> x);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
274
src/trees.cpp
274
src/trees.cpp
@ -1,81 +1,297 @@
|
|||||||
#include "trees.hpp"
|
#include "trees.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace tree_implementation
|
namespace tree_implementation
|
||||||
{
|
{
|
||||||
Tree::Tree(void)
|
|
||||||
|
TreeNode::TreeNode(std::string word)
|
||||||
{
|
{
|
||||||
;
|
key = word;
|
||||||
|
color = "red";
|
||||||
|
leftChild = nullptr;
|
||||||
|
rightChild = nullptr;
|
||||||
|
this->parent = nullptr;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tree::Insert(void)
|
TreeNode::~TreeNode(void)
|
||||||
{
|
{
|
||||||
;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tree::Search(void)
|
TreeNode::TreeNode(const TreeNode& rhs)
|
||||||
{
|
{
|
||||||
;
|
key = rhs.key;
|
||||||
|
color = rhs.color;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tree::InOrderTreeTraversal(void)
|
TreeNode& TreeNode::operator=(const TreeNode& rhs)
|
||||||
{
|
{
|
||||||
;
|
key = rhs.key;
|
||||||
|
color = rhs.color;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinarySearchTree::PrintParentKey(std::string key)
|
|
||||||
|
TreeList::TreeList(void)
|
||||||
{
|
{
|
||||||
;
|
head = nullptr;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinarySearchTree::PrintLeftChild(std::string key)
|
TreeInterface::TreeInterface(void)
|
||||||
{
|
{
|
||||||
;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinarySearchTree::PrintRightChild(std::string key)
|
// Inserts a node into a BST
|
||||||
|
void TreeInterface::Insert(std::unique_ptr<TreeNode> z)
|
||||||
{
|
{
|
||||||
;
|
std::unique_ptr<TreeNode> y(nullptr);
|
||||||
|
std::unique_ptr<TreeNode> x(tree.head.release());
|
||||||
|
while (x)
|
||||||
|
{
|
||||||
|
y = x.release();
|
||||||
|
if (z->key < x->key)
|
||||||
|
x = x->leftChild.release();
|
||||||
|
else
|
||||||
|
x = x->rightChild.release();
|
||||||
|
}
|
||||||
|
z->parent = y.release();
|
||||||
|
if (!y)
|
||||||
|
tree.head = z.release();
|
||||||
|
else if (z->key < y->key)
|
||||||
|
y->leftChild = z.release();
|
||||||
|
else
|
||||||
|
y->rightChild = z.release();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Searches for the given word in a tree
|
||||||
|
TreeNode* TreeInterface::Search(std::string wordToFind)
|
||||||
|
{
|
||||||
|
return _Search(tree.head, wordToFind);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSearchSuccessful(std::unique_ptr<TreeNode> foundNode)
|
||||||
|
{
|
||||||
|
if (foundNode)
|
||||||
|
return true;
|
||||||
|
std::cout << "No node found with key '" << foundNode->key << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints tree while traversing it
|
||||||
|
void TreeInterface::InOrderTreeTraversal(std::unique_ptr<TreeNode> viewedNode)
|
||||||
|
{
|
||||||
|
if (viewedNode)
|
||||||
|
InOrderTreeTraversal(viewedNode->leftChild);
|
||||||
|
std::cout << viewedNode.key << '\n';
|
||||||
|
InOrderTreeTraversal(viewedNode->rightChild);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the given word's parent's word if found
|
||||||
|
void TreeInterface::PrintParentKey(std::string key)
|
||||||
|
{
|
||||||
|
std::unique_ptr<TreeNode> foundNode = std::move(Search(key));
|
||||||
|
if (!IsSearchSuccessful(foundNode)) return;
|
||||||
|
std::cout << "The parent's word is " << foundNode->parent->key << '\n';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the given word's left child's word if found
|
||||||
|
void TreeInterface::PrintLeftChild(std::string key)
|
||||||
|
{
|
||||||
|
std::unique_ptr<TreeNode> foundNode = std::move(Search(key));
|
||||||
|
if (!IsSearchSuccessful(foundNode)) return;
|
||||||
|
std::cout << "The left child's word is " << foundNode->leftChild->key << '\n';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the given word's right child's word if found
|
||||||
|
void TreeInterface::PrintRightChild(std::string key)
|
||||||
|
{
|
||||||
|
std::unique_ptr<TreeNode> foundNode = std::move(Search(key));
|
||||||
|
if (!IsSearchSuccessful(foundNode)) return;
|
||||||
|
std::cout << "The right child's word is " << foundNode->rightChild->key << '\n';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursive insertion function for Insert()
|
||||||
|
TreeNode* TreeInterface::Insert(std::unique_ptr<TreeNode> root, std::unique_ptr<TreeNode> newNode)
|
||||||
|
{
|
||||||
|
if (!tree.head)
|
||||||
|
return newNode.release();
|
||||||
|
if (newNode->key < root->key)
|
||||||
|
{
|
||||||
|
root->leftChild = _Insert(root->leftChild, newNode);
|
||||||
|
root->leftChild->parent = root.release();
|
||||||
|
} else if (newNode->key > root->key) {
|
||||||
|
root->rightChild = _Insert(root->rightChild, newNode);
|
||||||
|
root->rightChild->parent = root.release();
|
||||||
|
}
|
||||||
|
return root.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursive search function for Search()
|
||||||
|
TreeNode* TreeInterface::Search(std::unique_ptr<TreeNode> viewedNode, std::string wordToFind)
|
||||||
|
{
|
||||||
|
if ((!viewedNode) || (wordToFind == viewedNode->key))
|
||||||
|
return viewedNode.release();
|
||||||
|
if (wordToFind < viewedNode->key)
|
||||||
|
return _Search(viewedNode->leftChild, wordToFind);
|
||||||
|
return _Search(viewedNode->rightChild, wordToFind);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert a node into a BST
|
||||||
|
void RedBlackTree::Insert(std::string keyToInsert)
|
||||||
|
{
|
||||||
|
std::unique_ptr<TreeNode> newNode = new TreeNode(keyToInsert);
|
||||||
|
TreeInterface::Insert(newNode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the path to root in a BST
|
||||||
|
// TODO: Implement printing path to root for BST
|
||||||
void BinarySearchTree::PrintPathToRoot(std::string key)
|
void BinarySearchTree::PrintPathToRoot(std::string key)
|
||||||
{
|
{
|
||||||
;
|
std::unique_ptr<TreeNode> selectedNode = std::move(Search(key));
|
||||||
}
|
if (!IsSearchSuccessful(selectedNode)) return;
|
||||||
|
int timesPrintedOnLine = 0;
|
||||||
void RedBlackTree::PrintParentKey(std::string key)
|
std::cout << "Path:\n" << selectedNode->key;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
;
|
selectedNode = selectedNode->parent;
|
||||||
|
std::cout << " -> " << selectedNode->parent->key;
|
||||||
|
if (timesPrintedOnLine < 10) ++timesPrintedOnLine;
|
||||||
|
else std::cout << "\n";
|
||||||
|
} while (selectedNode->parent);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RedBlackTree::PrintLeftChild(std::string key)
|
// Insert a node into a RBT
|
||||||
|
void RedBlackTree::Insert(std::string keyToInsert)
|
||||||
{
|
{
|
||||||
;
|
std::unique_ptr<TreeNode> newNode = new TreeNode(keyToInsert);
|
||||||
}
|
TreeInterface::Insert(newNode);
|
||||||
|
InsertFixup(newNode);
|
||||||
void RedBlackTree::PrintRightChild(std::string key)
|
return;
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print path to root in RBT
|
||||||
|
// TODO: Implement printing path to root for RBT
|
||||||
void RedBlackTree::PrintPathToRoot(std::string key)
|
void RedBlackTree::PrintPathToRoot(std::string key)
|
||||||
{
|
{
|
||||||
;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print color of word if found in RBT
|
||||||
void RedBlackTree::PrintColor(std::string key)
|
void RedBlackTree::PrintColor(std::string key)
|
||||||
{
|
{
|
||||||
;
|
std::unique_ptr<TreeNode> foundNode = std::move(Search(key));
|
||||||
|
if (!IsSearchSuccessful(foundNode)) return;
|
||||||
|
std::cout << "The color is " << foundNode->color << '\n';
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print color of word's parent if found in RBT
|
||||||
void RedBlackTree::PrintParentColor(std::string key)
|
void RedBlackTree::PrintParentColor(std::string key)
|
||||||
{
|
{
|
||||||
;
|
std::unique_ptr<TreeNode> foundNode = std::move(Search(key));
|
||||||
|
if (!IsSearchSuccessful(foundNode)) return;
|
||||||
|
std::cout << "The color is " << foundNode->parent->color << '\n';
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print color of word's uncle if found in RBT
|
||||||
void RedBlackTree::PrintUncleColor(std::string key)
|
void RedBlackTree::PrintUncleColor(std::string key)
|
||||||
{
|
{
|
||||||
|
std::unique_ptr<TreeNode> foundNode = std::move(Search(key));
|
||||||
|
if (!IsSearchSuccessful(foundNode)) return;
|
||||||
|
std::cout << "The color is " << GetUncleNode(foundNode)->color << '\n';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RedBlackTree::InsertFixup(std::unique_ptr<TreeNode> z)
|
||||||
|
{
|
||||||
|
std::unique_ptr<TreeNode> y;
|
||||||
|
while (z->parent->color == "red")
|
||||||
|
{
|
||||||
|
if (z->parent == z->parent->parent->leftChild)
|
||||||
|
{
|
||||||
|
y = std::move(z->parent->parent->rightChild);
|
||||||
|
if (y->color == "red")
|
||||||
|
{
|
||||||
|
z->parent->color = "black";
|
||||||
|
y->color = "black";
|
||||||
|
z->parent->parent->color = "red";
|
||||||
|
z = std::move(z->parent->parent);
|
||||||
|
} else if (z == z->parent->rightChild) {
|
||||||
|
z = std::move(z->parent);
|
||||||
|
LeftRotate(z);
|
||||||
|
z->parent->color = "black";
|
||||||
|
z->parent->parent->color = "red";
|
||||||
|
RightRotate(z->parent->parent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// same as then clause with "right" and "left" exchanged
|
||||||
|
// TODO: Add else statement
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
tree.head->color = "black";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the uncle node in RBT
|
||||||
|
std::unique_ptr<TreeNode> RedBlackTree::GetUncleNode(std::unique_ptr<TreeNode> startNode)
|
||||||
|
{
|
||||||
|
if (startNode->parent == startNode->parent->parent->leftChild)
|
||||||
|
return std::move(startNode->parent->parent->rightChild);
|
||||||
|
return std::move(startNode->parent->parent->leftChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs left rotate on a given node
|
||||||
|
void RedBlackTree::LeftRotate(std::unique_ptr<TreeNode> x)
|
||||||
|
{
|
||||||
|
std::unique_ptr<TreeNode> y(std::move(x->rightChild));
|
||||||
|
x->rightChild = std::move(y->leftChild);
|
||||||
|
if (y->rightChild)
|
||||||
|
y->rightChild->parent = std::move(x);
|
||||||
|
y->parent = std::move(x->parent);
|
||||||
|
if (!x->parent)
|
||||||
|
tree.head = std::move(y);
|
||||||
|
else if (x == x->parent->leftChild)
|
||||||
|
x->parent->leftChild = std::move(y);
|
||||||
|
else
|
||||||
|
x->parent->rightChild = std::move(y);
|
||||||
|
y->leftChild = std::move(x);
|
||||||
|
x->parent = std::move(y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs right rotate on a given node
|
||||||
|
void RedBlackTree::RightRotate(std::unique_ptr<TreeNode> x)
|
||||||
|
{
|
||||||
|
std::unique_ptr<TreeNode> y(std::move(x->rightChild));
|
||||||
|
x->rightChild = std::move(y->leftChild);
|
||||||
|
if (y->leftChild)
|
||||||
|
y->leftChild->parent = std::move(x);
|
||||||
|
y->parent = std::move(x->parent);
|
||||||
|
if (!x->parent)
|
||||||
|
tree.head = std::move(y);
|
||||||
|
else if (x == x->parent->leftChild)
|
||||||
|
x->parent->leftChild = std::move(y);
|
||||||
|
else
|
||||||
|
x->parent->rightChild = std::move(y);
|
||||||
|
y->leftChild = std::move(x);
|
||||||
|
x->parent = std::move(y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user