Bladeren bron

sorry, *this* is the initial commit for program 3 files

Natalie Pueyo 7 jaren geleden
bovenliggende
commit
d4d523b275

+ 3 - 0
program2/priorityqueue.cpp

@@ -1,3 +1,6 @@
+// based off of:
+// https://www.geeksforgeeks.org/binary-heap/
+
 #include <iostream>
 #include <cstdio>
 #include <string>

+ 264 - 0
program3/AVLCommands.cpp

@@ -0,0 +1,264 @@
+#include "AVLCommand.h"
+
+// examples of AVL tree algorithms:
+// https://tfetimes.com/c-avl-tree/
+// https://stackoverflow.com/questions/29866315/class-for-avl-trees-c
+// http://www.sanfoundry.com/cpp-program-implement-avl-trees/
+
+// AVL explanation:
+// http://www.btechsmartclass.com/DS/U5_T2.html
+
+// combination of geeksforgeeks AVL insert and delete code
+// written for C
+
+// => convert into a C++ class
+
+//constructor: builds an AVL tree from BST tree bst
+AVLCommands::AVLCommands() {
+  BST bst(); // initialize BST with root null and sized 0
+}
+
+// An AVL tree node
+struct Node
+{
+    int key;
+    struct Node *left;
+    struct Node *right;
+    int height;
+};
+
+// A utility function to get maximum of two integers
+int max(int a, int b);
+
+// A utility function to get height of the tree
+int height(struct Node *N) {
+    if (N == NULL)
+        return 0;
+    return N->height;
+}
+
+// A utility function to get maximum of two integers
+int max(int a, int b) {
+    return (a > b)? a : b;
+}
+
+/* Helper function that allocates a new node with the given key and
+    NULL left and right pointers. */
+struct Node* newNode(int key)
+{
+   struct Node* node = (struct Node*)
+                        malloc(sizeof(struct Node));
+    node->key   = key;
+    node->left   = NULL;
+    node->right  = NULL;
+    node->height = 1;  // new node is initially added at leaf
+    return(node);
+}
+
+// A utility function to right rotate subtree rooted with y
+// See the diagram given above.
+struct Node *rightRotate(struct Node *y)
+{
+    struct Node *x = y->left;
+    struct Node *T2 = x->right;
+
+    // Perform rotation
+    x->right = y;
+    y->left = T2;
+
+    // Update heights
+    y->height = max(height(y->left), height(y->right))+1;
+    x->height = max(height(x->left), height(x->right))+1;
+
+    // Return new root
+    return x;
+}
+
+// A utility function to left rotate subtree rooted with x
+// See the diagram given above.
+struct Node *leftRotate(struct Node *x)
+{
+    struct Node *y = x->right;
+    struct Node *T2 = y->left;
+
+    // Perform rotation
+    y->left = x;
+    x->right = T2;
+
+    //  Update heights
+    x->height = max(height(x->left), height(x->right))+1;
+    y->height = max(height(y->left), height(y->right))+1;
+
+    // Return new root
+    return y;
+}
+
+// Get Balance factor of node N
+int getBalance(struct Node *N)
+{
+    if (N == NULL)
+        return 0;
+    return height(N->left) - height(N->right);
+}
+
+// Recursive function to insert key in subtree rooted
+// with node and returns new root of subtree.
+struct Node* insert(struct Node* node, int key)
+{
+    /* 1.  Perform the normal BST insertion */
+    if (node == NULL)
+        return(newNode(key));
+
+    if (key < node->key)
+        node->left  = insert(node->left, key);
+    else if (key > node->key)
+        node->right = insert(node->right, key);
+    else // Equal keys are not allowed in BST
+        return node;
+
+    /* 2. Update height of this ancestor node */
+    node->height = 1 + max(height(node->left),
+                           height(node->right));
+
+    /* 3. Get the balance factor of this ancestor
+          node to check whether this node became
+          unbalanced */
+    int balance = getBalance(node);
+
+    // If this node becomes unbalanced, then
+    // there are 4 cases
+
+    // Left Left Case
+    if (balance > 1 && key < node->left->key)
+        return rightRotate(node);
+
+    // Right Right Case
+    if (balance < -1 && key > node->right->key)
+        return leftRotate(node);
+
+    // Left Right Case
+    if (balance > 1 && key > node->left->key)
+    {
+        node->left =  leftRotate(node->left);
+        return rightRotate(node);
+    }
+
+    // Right Left Case
+    if (balance < -1 && key < node->right->key)
+    {
+        node->right = rightRotate(node->right);
+        return leftRotate(node);
+    }
+
+    /* return the (unchanged) node pointer */
+    return node;
+}
+
+/* Given a non-empty binary search tree, return the
+   node with minimum key value found in that tree.
+   Note that the entire tree does not need to be
+   searched. */
+struct Node * minValueNode(struct Node* node)
+{
+    struct Node* current = node;
+
+    /* loop down to find the leftmost leaf */
+    while (current->left != NULL)
+        current = current->left;
+
+    return current;
+}
+
+// Recursive function to delete a node with given key
+// from subtree with given root. It returns root of
+// the modified subtree.
+struct Node* deleteNode(struct Node* root, int key)
+{
+    // STEP 1: PERFORM STANDARD BST DELETE
+
+    if (root == NULL)
+        return root;
+
+    // If the key to be deleted is smaller than the
+    // root's key, then it lies in left subtree
+    if ( key < root->key )
+        root->left = deleteNode(root->left, key);
+
+    // If the key to be deleted is greater than the
+    // root's key, then it lies in right subtree
+    else if( key > root->key )
+        root->right = deleteNode(root->right, key);
+
+    // if key is same as root's key, then This is
+    // the node to be deleted
+    else
+    {
+        // node with only one child or no child
+        if( (root->left == NULL) || (root->right == NULL) )
+        {
+            struct Node *temp = root->left ? root->left :
+                                             root->right;
+
+            // No child case
+            if (temp == NULL)
+            {
+                temp = root;
+                root = NULL;
+            }
+            else // One child case
+             *root = *temp; // Copy the contents of
+                            // the non-empty child
+            free(temp);
+        }
+        else
+        {
+            // node with two children: Get the inorder
+            // successor (smallest in the right subtree)
+            struct Node* temp = minValueNode(root->right);
+
+            // Copy the inorder successor's data to this node
+            root->key = temp->key;
+
+            // Delete the inorder successor
+            root->right = deleteNode(root->right, temp->key);
+        }
+    }
+
+    // If the tree had only one node then return
+    if (root == NULL)
+      return root;
+
+    // STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
+    root->height = 1 + max(height(root->left),
+                           height(root->right));
+
+    // STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to
+    // check whether this node became unbalanced)
+    int balance = getBalance(root);
+
+    // If this node becomes unbalanced, then there are 4 cases
+
+    // Left Left Case
+    if (balance > 1 && getBalance(root->left) >= 0)
+        return rightRotate(root);
+
+    // Left Right Case
+    if (balance > 1 && getBalance(root->left) < 0)
+    {
+        root->left =  leftRotate(root->left);
+        return rightRotate(root);
+    }
+
+    // Right Right Case
+    if (balance < -1 && getBalance(root->right) <= 0)
+        return leftRotate(root);
+
+    // Right Left Case
+    if (balance < -1 && getBalance(root->right) > 0)
+    {
+        root->right = rightRotate(root->right);
+        return leftRotate(root);
+    }
+
+    return root;
+}

+ 27 - 0
program3/AVLCommands.h

@@ -0,0 +1,27 @@
+// include guard
+#ifndef AVLC_H
+#define AVLC_H
+
+#include <iostream>
+#include <cstdio>
+#include <string>
+#include "json.hpp"
+#include "BST.h"
+
+class AVLCommands{
+  int *heapArray;                // pointer to heap array
+  int max_size;                  // max size of heap array
+  int heap_size;                 // elements in heap
+  void swap(int*, int*);         // swaps two keys in the heap
+  void heapifyUp(int);           // moves keys up if they are larger than their parent key
+  void heapifyDown(int);         // moves keys down if they are smaller than their parent key
+public:
+  // required functions from PDF
+  void Insert(int key);          // inserts a new key into AVL tree
+  void Delete(int key);          // deletes specified key
+  void DeleteMin();              // removes the minimum value key
+  // helpful functions
+  void printJSONTree(int, int);  // prints the heap as a JSON object
+};
+
+#endif

+ 2 - 0
program3/AVLCommands.sh

@@ -0,0 +1,2 @@
+#!/bin/bash
+./AVLCommands $1

+ 209 - 0
program3/BST.cpp

@@ -0,0 +1,209 @@
+#include "BST.h"
+
+#include <cassert>
+#include <iostream>
+#include <string>
+#include <queue>
+
+#include "json.hpp"
+
+
+BSTNode::BSTNode(int key) :
+	key_(key),
+	parent_(std::weak_ptr<BSTNode>()),
+	left_(nullptr),
+	right_(nullptr) {}
+
+BSTNode::BSTNode(int key, std::weak_ptr<BSTNode> parent) :
+	key_(key),
+	parent_(parent),
+	left_(nullptr),
+	right_(nullptr) {}
+
+bool BSTNode::IsLeaf() const {
+	return left_ == nullptr && right_ == nullptr;
+}
+
+bool BSTNode::HasLeftChild() const {
+	return left_ != nullptr;
+}
+
+bool BSTNode::HasRightChild() const {
+	return right_ != nullptr;
+}
+
+void BSTNode::DeleteChild(std::shared_ptr<BSTNode> v) {
+	if (left_ == v) {
+		left_ = nullptr;
+	} else if (right_ == v) {
+		right_ = nullptr;
+	} else {
+		std::cerr << "BSTNode::DeleteChild Error: non-child passed as argument\n";
+		exit(EXIT_FAILURE);
+	}
+}
+
+void BSTNode::ReplaceChild(std::shared_ptr<BSTNode> v, std::shared_ptr<BSTNode> u) {
+	if (left_ == u || right_ == u) {
+		std::cerr << "BSTNode::ReplaceChild Error: child passed as replacement\n";
+	}
+	if (left_ == v) {
+		left_ = u;
+		u->parent_ = v->parent_;
+	} else if (right_ == v) {
+		right_ = u;
+		u->parent_ = v->parent_;
+	} else {
+		std::cerr << "BSTNode::ReplaceChild Error: non-child passed as argument\n";
+		exit(EXIT_FAILURE);
+	}
+}
+
+BST::BST() : root_(nullptr), size_(0) {}
+
+void BST::Insert(int key) {
+	if (root_ == nullptr) {
+		root_ = std::make_shared<BSTNode>(key);
+		size_++;
+		return;
+	}
+	std::shared_ptr<BSTNode> currentNode = root_, lastNode = nullptr;
+	while (currentNode != nullptr) {
+		lastNode = currentNode;
+		currentNode = (key < currentNode->key_) ?
+			currentNode->left_ : currentNode->right_;
+	}
+	if (key < lastNode->key_) {
+		lastNode->left_ = std::make_shared<BSTNode>(key, lastNode);
+	} else {
+		lastNode->right_ = std::make_shared<BSTNode>(key, lastNode);
+	}
+	size_++;
+}
+
+bool BST::Delete(int key) {
+	std::shared_ptr<BSTNode> currentNode = root_;
+	while (currentNode != nullptr) {
+		if (currentNode->key_ == key) {
+			if (currentNode->IsLeaf()) {
+				DeleteLeaf(currentNode);
+			} else if (currentNode->left_ == nullptr) {
+				assert(currentNode->right_ != nullptr);
+				std::shared_ptr<BSTNode> parent = currentNode->parent_.lock();
+				parent->ReplaceChild(currentNode, currentNode->right_);
+				size_--; assert(size_ >= 0);
+			} else if (currentNode->right_ == nullptr) {
+				assert(currentNode->left_ != nullptr);
+				std::shared_ptr<BSTNode> parent = currentNode->parent_.lock();
+				parent->ReplaceChild(currentNode, currentNode->left_);
+				size_--; assert(size_ >= 0);
+			} else {
+				currentNode->key_ = DeleteMin(currentNode);
+			}
+		}
+		currentNode = (key < currentNode->key_) ?
+			currentNode->left_ : currentNode->right_;
+	}
+	return false;
+}
+
+int BST::DeleteMin() {
+	return DeleteMin(root_);
+}
+
+
+void BST::DeleteLeaf(std::shared_ptr<BSTNode> currentNode) {
+	std::shared_ptr<BSTNode> parent = currentNode->parent_.lock();
+	if (parent == nullptr) {
+		// Delete root
+		root_ = nullptr;
+		size_--; assert(size_ == 0);
+	} else {
+		if (parent->right_ == currentNode) {
+			parent->right_ = nullptr;
+		} else if (parent->left_ == currentNode) {
+			parent->left_ = nullptr;
+		} else {
+			std::cerr << "BST::DeleteLeaf Error: inconsistent state\n";
+		}
+		size_--; assert(size_ >= 0);
+	}
+}
+
+int BST::DeleteMin(std::shared_ptr<BSTNode> currentNode) {
+	std::shared_ptr<BSTNode> lastNode = nullptr;
+	while (currentNode != nullptr) {
+		lastNode = currentNode;
+		currentNode = currentNode->left_;
+	}
+	int result = lastNode->key_;
+	std::shared_ptr<BSTNode> parent = lastNode->parent_.lock();
+	if (parent == nullptr) {
+		// lastNode is root
+		if (lastNode->right_ != nullptr) {
+			root_ = lastNode->right_;
+			lastNode->right_->parent_.reset();
+		} else {
+			root_ = nullptr;
+		}
+	} else {
+		// lastNode under the root
+		if (lastNode->right_ != nullptr) {
+			parent->left_ = lastNode->right_;
+			lastNode->right_->parent_ = parent;
+		} else {
+			parent->left_ = nullptr;
+		}
+  }
+	size_--; assert(size_ >= 0);
+	return result;
+}
+
+size_t BST::size() const {
+	return size_;
+}
+
+bool BST::empty() const {
+	return size_ == 0;
+}
+
+bool BST::Find(int key) const {
+	std::shared_ptr<BSTNode> currentNode = root_;
+	while (currentNode != nullptr) {
+		if (currentNode->key_ == key) {
+			return true;
+		}
+		currentNode = (key < currentNode->key_) ?
+			currentNode->left_ : currentNode->right_;
+	}
+	return false;
+}
+
+std::string BST::JSON() const {
+	nlohmann::json result;
+	std::queue< std::shared_ptr<BSTNode> > nodes;
+	if (root_ != nullptr) {
+		result["root"] = root_->key_;
+		nodes.push(root_);
+		while (!nodes.empty()) {
+			auto v = nodes.front();
+			nodes.pop();
+			std::string key = std::to_string(v->key_);
+			if (v->left_ != nullptr) {
+				result[key]["left"] = v->left_->key_;
+				nodes.push(v->left_);
+			}
+			if (v->right_ != nullptr) {
+				result[key]["right"] = v->right_->key_;
+				nodes.push(v->right_);
+			}
+			if (v->parent_.lock() != nullptr) {
+				result[key]["parent"] = v->parent_.lock()->key_;
+			} else {
+				result[key]["root"] = true;
+			}
+		}
+	}
+	result["size"] = size_;
+	return result.dump(2) + "\n";
+}

+ 44 - 0
program3/BST.h

@@ -0,0 +1,44 @@
+#include <memory>
+#include <string>
+
+class BST;
+
+class BSTNode {
+ public:
+ 	BSTNode(int key);
+ 	BSTNode(int key, std::weak_ptr<BSTNode> parent);
+ 	bool IsLeaf() const;
+ 	bool IsMissingChild() const;
+ 	bool HasLeftChild() const;
+ 	bool HasRightChild() const;
+ 	void DeleteChild(std::shared_ptr<BSTNode> v);
+ 	void ReplaceChild(std::shared_ptr<BSTNode> v, std::shared_ptr<BSTNode> u);
+
+ private:
+  int key_;
+  std::weak_ptr<BSTNode> parent_;
+  std::shared_ptr<BSTNode> left_;
+  std::shared_ptr<BSTNode> right_;
+
+  friend BST;
+}; // class BSTNode
+
+class BST {
+ public:
+ 	BST();
+
+ 	void Insert(int key);
+ 	bool Delete(int key);
+ 	bool Find(int key) const;
+ 	std::string JSON() const;
+ 	size_t size() const;
+ 	bool empty() const;
+ 	int DeleteMin();
+
+ private:
+	void DeleteLeaf(std::shared_ptr<BSTNode> currentNode);
+	int DeleteMin(std::shared_ptr<BSTNode> currentNode);
+
+ 	std::shared_ptr<BSTNode> root_;
+ 	size_t size_;
+}; // class BST

+ 52 - 0
program3/BSTSanityCheck.cxx

@@ -0,0 +1,52 @@
+#include <algorithm>
+#include <cassert>
+#include <iostream>
+#include <random>
+#include <vector>
+
+#include "BST.h"
+
+#define SAMPLE_SIZE 1000
+#define NUM_TESTS 10000
+
+int main() {
+
+	// C++11 random number tutorial: https://gist.github.com/PhDP/5289449
+	// Seed random number generator
+	std::mt19937_64 rng(time(0));
+	// Create uniform distribution
+	std::uniform_int_distribution<int> unif(
+		std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
+	std::uniform_int_distribution<int> op(0,10);
+
+	std::vector<int> sampleData, BSTSortedData;
+	sampleData.reserve(SAMPLE_SIZE);
+	BSTSortedData.reserve(SAMPLE_SIZE);
+	std::cout << "Running tests..." << std::flush;
+	for (unsigned int sample = 0; sample < NUM_TESTS; sample++) {
+		BST T;
+		// On size_t usage here: https://stackoverflow.com/questions/131803/unsigned-int-vs-size-t
+		for (size_t i = 0; i < SAMPLE_SIZE; i++) {
+			if (op(rng) == 0 && !T.empty()) {
+				T.Delete(sampleData.back());
+				sampleData.pop_back();
+			} else {			
+				// Add random integer to array
+				int x = unif(rng);
+				T.Insert(x);
+				sampleData.push_back(x);
+			}
+		}
+		while (!T.empty()) {
+			BSTSortedData.push_back(T.DeleteMin());
+		}
+		std::sort(sampleData.begin(), sampleData.end());
+		assert(sampleData == BSTSortedData);
+		BSTSortedData.clear();
+		sampleData.clear();
+		if (sample % (NUM_TESTS / 10) == 0) {
+			std::cout << "." << std::flush;
+		}
+	}
+	std::cout << "Tests complete.\n";
+}

+ 27 - 0
program3/Makefile

@@ -0,0 +1,27 @@
+CC=g++
+DEV=-Wall -g -std=c++14
+OPT=-O3 -std=c++14
+
+.PHONY: all
+all: BSTSanityCheck CreateData
+
+CreateData: CreateData.cxx json.hpp
+	$(CC) $(OPT) CreateData.cxx -o CreateData
+
+BSTSanityCheck: BSTSanityCheck.cxx BST.o
+	$(CC) $(DEV) BSTSanityCheck.cxx BST.o -o BSTSanityCheck
+
+BST.o: BST.cpp BST.h
+	$(CC) $(DEV) -c BST.cpp
+
+# Build
+.PHONY: clean
+clean:
+	rm -f *.o
+	rm -f *.exe
+	rm -rf *dSYM
+
+.PHONY: update
+update:
+	make clean
+	make all

+ 1 - 0
program3/compile.sh

@@ -0,0 +1 @@
+#!/bin/bash

BIN
program3/program3.pdf