diff --git a/YASI_12/YASI_12.vcxproj b/YASI_12/YASI_12.vcxproj
index 5d673ee..81a27c4 100644
--- a/YASI_12/YASI_12.vcxproj
+++ b/YASI_12/YASI_12.vcxproj
@@ -76,10 +76,12 @@
+
+
diff --git a/YASI_12/YASI_12.vcxproj.filters b/YASI_12/YASI_12.vcxproj.filters
index 2377fdd..ad4aa77 100644
--- a/YASI_12/YASI_12.vcxproj.filters
+++ b/YASI_12/YASI_12.vcxproj.filters
@@ -153,6 +153,12 @@
Header Files\Data Structures\List
+ Header Files\Data Structures\List
+
+
+ Header Files
+
+
Header Files
diff --git a/YASI_12/ds.arraybinarytree.h b/YASI_12/ds.arraybinarytree.h
index 647d681..5fb048a 100644
--- a/YASI_12/ds.arraybinarytree.h
+++ b/YASI_12/ds.arraybinarytree.h
@@ -8,8 +8,12 @@
#include
#include
+using namespace std;
+
+// enable-disable testing classes in this file
+#include "test.this.module.h"
+
namespace yasi{
- using namespace std;
namespace ds{
///// abstract class
@@ -36,7 +40,7 @@ namespace yasi{
template
class IndexedBTNode : public virtual IArrayBinaryTreeNode,
public virtual TreeNode {
- friend class IndexedBTNodeTest; // enable testing
+ FRIEND_TEST_CLASS( IndexedBTNodeTest); // enable testing
protected:
int _index; /// -1 by default
const int NULL_INDEX; // marks whether a node is empty/invalid
@@ -98,8 +102,8 @@ namespace yasi{
class ArrayBinaryTree : public virtual IArrayBinaryTree >,
public virtual BinaryTreeBase>{
///////////// enable testing ////////////////
- friend class ArrayBinaryTreeTest;
- friend class BinaryHeapTest;
+ FRIEND_TEST_CLASS(ArrayBinaryTreeTest);
+ FRIEND_TEST_CLASS(BinaryHeapTest);
typedef IndexedBTNode node_t;
const int ROOT_INDEX = 1; // for quick parent-child indexing, 1 instead of 0
@@ -584,423 +588,6 @@ namespace yasi{
return out;
}
- ///
- /// Test IndexedBTNode
- ///
- class IndexedBTNodeTest :public yasi::Test{
- protected:
- void init(){
- IndexedBTNode n1;
- ASSERT_EQ(-1, n1._index) << "Default index should be -1" ;
- n1.setIndex(5);
- ASSERT_EQ(5, n1.index()) << "index should be 5";
- n1.setElement(7);
- ASSERT_EQ(7, n1.element) << "element should be 5";
-
- n1.makeNull();
- ASSERT_EQ(1, n1.isNull()) << "makeNull() and isNull() disagree";
- }
- void indexing(){
- const int N = 7;
- IndexedBTNode n[N];
- for (int i = 0; i < N; i++){
- n[i].setIndex(i);
- }
- ASSERT_EQ(0, n[0].leftIndex()) << "left of 0 must be 0";
- ASSERT_EQ(1, n[0].rightIndex()) << "right of 0 must be 1";
-
- ASSERT_EQ(1, n[2].parentIndex()) << "parent of 2 must be 1";
- ASSERT_EQ(1, n[3].parentIndex()) << "parent of 3 must be 1";
- ASSERT_EQ(2, n[4].parentIndex()) << "parent of 4 must be 2";
- ASSERT_EQ(4, n[2].leftIndex()) << "left of 2 must be 4";
- ASSERT_EQ(5, n[2].rightIndex()) << "right of 2 must be 5";
-
- }
- };
- ADD_TEST_F(IndexedBTNodeTest, init);
- ADD_TEST_F(IndexedBTNodeTest, indexing);
- ////////////// end testing IndexedBTNode
-
- ///
- /// Test ArrayBinaryTree
- ///
- class ArrayBinaryTreeTest : public yasi::Test{
- protected:
- typedef ArrayBinaryTree::node_t node_t;
- typedef ArrayBinaryTree::node_t* node_tptr;
- public:
-
- template
- static void checkElements(ArrayBinaryTree *pBt, const E* pElemsArr, const int numElems){
- // finally, check array
- E *pTreeElems;
- int n;
- ArrayBinaryTree& bt = *pBt; // must use reference, otherwise the tree will be destroyed upon exit
- bt.elements(&pTreeElems, n);
- ASSERT_EQ(n, numElems) << "actual array size " << n << " should equal target size " << numElems << endl
- << "actual : " << arrToString(pTreeElems, n) << endl
- << "expected: " << arrToString(pElemsArr, n);
-
- ASSERT_EQ(true, arrcmp(pTreeElems, pElemsArr, n)) << "elements array not right." << endl
- << "actual : " << arrToString(pTreeElems, n) << endl
- << "expected: " << arrToString(pElemsArr, n);
-
- // done
- DELETE_ARR_SAFE(pTreeElems);
- }
-
- void constructor(){
- ArrayBinaryTree bt;
- ASSERT_EQ(1, bt.ROOT_INDEX) << "Index of root is not 1";
- ASSERT_LE(bt.INIT_CAPACITY, bt._arr.capacity() ) << "Initial _capacity must be <= containers capacity";
- ASSERT_LE(2, bt._arr.capacity()) << "Initial capacity must be >= 2";
- ASSERT_EQ(0, bt.size()) << "Initial size is not zero";
- for (int i = 0; i < bt._capacity; i++){
- ASSERT_EQ(0, bt._arr[i]) << "Pointer at index " << i << " is not initialized to NULL";
- }
-
- ASSERT_EQ(NULL, bt.root()) << "root should have been NULL";
- }
-
- void elements(){
- int srcArr[] = { 10, 20, 30, 40, 50, 60 };
- int n = ARR_LENGTH(srcArr);
- ArrayBinaryTree bt(srcArr, n);
-
- int* pElemArr;
- int numElems;
- bt.elements(&pElemArr, numElems);
- ASSERT_EQ(n, numElems) << "number of elements is not " << n;
- for (int i = 0; i < numElems; i++){
- ASSERT_EQ(srcArr[i], pElemArr[i]) << "element mismatch at index " << i;
- }
- DELETE_ARR_SAFE(pElemArr);
- }
-
- void fromArr(){
- int srcArr[] = {10, 20, 30, 40, 50, 60};
- int n = ARR_LENGTH(srcArr);
- ArrayBinaryTree bt(srcArr, n );
- ASSERT_EQ(n, bt.size()) << "size of tree is not " << n;
- // check node-ptrs stored in internal container
- int i = 0;
- for (int i = 0; i < bt._capacity; i++){
- if (i >= 1 && i <= n){
- // valid node-ptrs
- ASSERT_NE(0, (int)bt._arr[i]) << "Pointer NULL at index " << i;
- ASSERT_EQ(srcArr[i-1], bt._arr[i]->element) << "array element mismatch for internal index " << i;
- }
- else{
- // invalid node-ptrs
- ASSERT_EQ(0, (int)bt._arr[i]) << "Pointer not NULL at index " << i;
- }
- }
- // also, use elements() method
- int* pElemArr;
- int numElems;
- bt.elements(&pElemArr, numElems);
- ASSERT_EQ(n, numElems) << "number of elements is not " << n;
- for (int i = 0; i < numElems; i++){
- ASSERT_EQ(srcArr[i], pElemArr[i]) << "element mismatch at index " << i;
- }
- DELETE_ARR_SAFE(pElemArr);
- }
-
- void isArrIndex(){
- ArrayBinaryTree bt;
- ASSERT_EQ(false, bt.isArrIndex(-1)) << "Negative index is accepted";
- ASSERT_EQ(true, bt.isArrIndex(0)) << "0 index is rejected";
- ASSERT_EQ(true, bt.isArrIndex(bt._capacity - 1)) << "index (capacity - 1) is rejected";
- ASSERT_EQ(false, bt.isArrIndex(bt._capacity)) << "index beyond capacity is accepted";
- }
-
- void nodeAt(){
- ArrayBinaryTree bt;
- bt.addRoot(5);
-
- bt.nodeAt(-1);
-
- ASSERT_EQ(0, (int) bt.nodeAt(-1)) << "Negative index is accepted";
- ASSERT_EQ(0, (int) bt.nodeAt(0)) << "Index 0 is accepted";
- ASSERT_EQ(0, (int) bt.nodeAt(bt._capacity)) << "Too large index is accepted";
- ASSERT_NE(0, (int) bt.nodeAt(1)) << "The root is not recognized";
-
- int e;
- bt.remove(bt.root(), e); // remove root
- ASSERT_EQ(0, (int) bt.nodeAt(1)) << "TreeNode accepted after deletion";
- }
-
- void nodeNotNull(){
- ArrayBinaryTree bt;
- bt.addRoot(5);
-
- ASSERT_EQ(false, bt.nodeNotNull(-1)) << "Negative index is accepted";
- ASSERT_EQ(false, bt.nodeNotNull(0)) << "Zero index is accepted";
- ASSERT_EQ(false, bt.nodeNotNull(bt._capacity)) << "Too large index is accepted";
- ASSERT_EQ(true, bt.nodeNotNull(1)) << "The root is not recognized";
-
- int e;
- bt.remove(bt.root(), e); // remove root
- ASSERT_EQ(false, bt.nodeNotNull(1)) << "TreeNode accepted after deletion";
- }
-
- void addRoot(){
- ArrayBinaryTree bt;
- ASSERT_EQ(0, bt.size());
- bt.addRoot(10);
- ASSERT_EQ(1, bt.size()) << "tree-size should have been 1";
- ASSERT_EQ(0, (int) bt.nodeAt(0)) << "As per Goodrich-Tamassia convention, first slot in the array should have been empty";
- ASSERT_EQ(10, bt.nodeAt(1)->element) << "Value at the root should have been 10";
- ASSERT_EQ(false, bt.isLeft(bt.root())) << "root cannot be a left child";
- ASSERT_EQ(false, bt.isRight(bt.root())) << "root cannot be a right child";
- ASSERT_EQ(false, bt.isInternal(bt.root())) << "root should have been external";
- ASSERT_EQ(false, bt.hasLeft(bt.root())) << "root does not have a left child";
- ASSERT_EQ(false, bt.hasRight(bt.root())) << "root does not have a right child";
- }
-
- void insertAt(){
- ArrayBinaryTree bt;
- EXPECT_EQ(0, (int)bt.insertAt(4, -1)) << "inserting at negative index succeeded";
- EXPECT_EQ(0, (int)bt.insertAt(4, 0)) << "inserting at 0 index succeeded";
- EXPECT_NE(0, (int)bt.insertAt(4, 2 * bt._capacity)) << "inserting at too large index failed";
- ASSERT_NE(0, (int)bt.insertAt(4, 1)) << "inserting at index 1 failed";
- ASSERT_EQ(0, (int)bt.insertAt(4, 1)) << "inserting at an occupied index succeeded";
- bt.remove(bt.nodeAt(1));
- ASSERT_NE(0, (int)bt.insertAt(4, 1)) << "inserting at a recently deleted slot failed";
- }
-
- void replaceAt(){
- ArrayBinaryTree bt;
- EXPECT_EQ(0, (int)bt.replaceAt(4, -1)) << "replacing at negative index succeeded";
- EXPECT_EQ(0, (int)bt.replaceAt(4, 0)) << "replacing at 0 index succeeded";
- EXPECT_EQ(0, (int)bt.replaceAt(4, 2 * bt._capacity)) << "replacing at too large index succeeded";
- ASSERT_EQ(0, (int)bt.replaceAt(4, 1)) << "replacing at unused index 1 succeeded";
- bt.addRoot(10);
- ASSERT_NE(0, (int)bt.replaceAt(4, 1)) << "replacing at occupied index 1 failed";
- int index = bt.root()->index();
- bt.remove(bt.root());
- ASSERT_EQ(0, (int)bt.replaceAt(4, index) ) << "replacing at a recently deleted index succeeded";
- }
-
- void sibling(){
- ArrayBinaryTree bt;
- ASSERT_EQ(0, (int)bt.sibling(bt.nodeAt(0))) << "sibling of NULL node succeeded";
- bt.addRoot(4);
- ASSERT_EQ(0, (int)bt.sibling(bt.root())) << "sibling of root node succeeded";
- ArrayBinaryTree::node_t* n1 = bt.addLeft(5, bt.root());
- ASSERT_EQ(0, (int)bt.sibling(n1)) << "sibling of only-child succeeded";
- ArrayBinaryTree::node_t* n2 = bt.addRight(5, bt.root());
- ASSERT_EQ(n2, bt.sibling(n1)) << "sibling of valid node failed";
- bt.remove(bt.left(bt.root())); // remove n1
- ASSERT_EQ(0, (int) bt.sibling(n2)) << "sibling of a deleted-sibling-node succeeded";
-
- }
-
- void resize(){
- int srcArr[] = { 10, 20, 30, 40, 50 };
- int n = ARR_LENGTH(srcArr);
- ArrayBinaryTree bt(srcArr, n);
- int oldCapacity = bt._capacity;
- // copy current data
- // node_tptr is actually int (because it is a pointer)
- node_tptr* pOldArr = new node_tptr[oldCapacity];
- memcpy(pOldArr, (node_tptr*)bt._arr.data(), sizeof(node_tptr) * oldCapacity);
-
- bt.resize(2 * oldCapacity + 5, 0);
- int newCapacity = bt._capacity;
- const node_tptr* pNewArr = (node_tptr*)bt._arr.data();
- // all new slots must be initialized to zero
- for (int i = 0; i < newCapacity; i++){
- if (i < oldCapacity){
- // old slots
- ASSERT_EQ(pOldArr[i], pNewArr[i]) << "content mismatch at index " << i;
- }
- else{
- // new slots
- ASSERT_EQ(0, pNewArr[i]) << "new slots contain non-NULL pointer at index " << i;
- }
- }
- // done test
- DELETE_ARR_SAFE(pOldArr);
- }
-
- void toString(){
- int srcArr[] = { 10, 20, 30, 40, 50, 60, 70 };
- int n = ARR_LENGTH(srcArr);
- ArrayBinaryTree bt(srcArr, n);
- // delete 50 and 60
- int e1, e2;
- bool ok = bt.remove(bt.nodeAt(5), e1);
- ASSERT_EQ(true, ok) << "falied to remove 50";
- ASSERT_EQ(50, e1) << "50 was not deleted";
- ok = bt.remove(bt.nodeAt(6), e2);
- ASSERT_EQ(true, ok) << "falied to remove 60";
- ASSERT_EQ(60, e2) << "60 was not deleted";
-
- // now print
- const char* sDelim = "|"; // need to be single-char for testing purpose
- const char* sEmptySlot = ""; // need to be empty for testing purpose
- string strBt = bt.toStringNodeArray(sDelim, sEmptySlot);
- // remove trailing single-char delimiters
- for (int i = strBt.length() - 1; strBt[i] == sDelim[0]; i--){
- strBt[i] = NULL;
- }
- strBt = string(strBt.c_str());
- // now strBt should equal "|10|20|30|40|||70"
- string strExpected = "|10|20|30|40|||70";
- ASSERT_EQ(strExpected, strBt) << "Expected " << strExpected << " but found " << strBt;
-
-
- bt.clear();
- bt.fromArray(srcArr, n);// 10 20 30 40 50 60 70
- /////////// preorder
- strBt = bt.toStringPreOrder();
- strBt = strPurge(strBt, "| ");
- strExpected = "10204050306070";
- ASSERT_EQ(strExpected, strBt) << "preorder mismatch";
-
- /////////// postorder
- strBt = bt.toStringPostOrder();
- strBt = strPurge(strBt, "| ");
- strExpected = "40502060703010";
- ASSERT_EQ(strExpected, strBt) << "postorder mismatch";
-
- /////////// inorder
- strBt = bt.toStringInOrder();
- strBt = strPurge(strBt, "| ");
- strExpected = "40205010603070";
- ASSERT_EQ(strExpected, strBt) << "inorder mismatch";
-
-
- /////////// BFSorder
- strBt = bt.toStringBFS();
- strBt = strPurge(strBt, "| ");
- strExpected = "10203040506070";
- ASSERT_EQ(strExpected, strBt) << "BFS order mismatch";
- }
-
- void remove(){
- int e;
- int srcArr[] = { 10, 20, 30, 40, 50, 60 };
- int n = ARR_LENGTH(srcArr);
- ArrayBinaryTree bt(srcArr, n);
- {
- SCOPED_TRACE("tree arr before remove");
- checkElements(&bt, srcArr, n);
- }
- //bt.toString(&cBt);
- //DELETE_ARR_SAFE(cBt);
-
-
- bool ok = bt.remove(bt.nodeAt(0));
- ASSERT_EQ(false, ok) << "removing from index 0 succeeded";
- ok = bt.remove(bt.nodeAt(-1));
- ASSERT_EQ(false, ok) << "removing from negative index succeeded";
-
- //bt.toString(&cBt);
- //DELETE_ARR_SAFE(cBt);
-
- // removing the root will remove the entire tree
- ok = bt.remove(bt.root(), e); // 10
- ASSERT_EQ(true, ok) << "remove(root) failed";
- ASSERT_EQ(10, e) << "removed element should have been 10";
- ASSERT_EQ(0, bt.size()) << "Deleting subtree at root should make the size zero.";
-
- // remove a subtree
- bt.fromArray(srcArr, ARR_LENGTH(srcArr));
- // arr = { 10, 20, 30, 40, 50, 60 };
- ok = bt.remove(bt.left(bt.root()), e); // remove subtree 20
- ASSERT_EQ(true, ok) << "remove(20) failed";
- ASSERT_EQ(20, e) << "removed element should have been 20";
- ASSERT_EQ(ARR_LENGTH(srcArr) - 3, bt.size()) << "Remaining tree has improper size";
- {
- SCOPED_TRACE("remove(20)");
- int newArr[] = {10, 30, 60};
- checkElements(&bt, newArr, ARR_LENGTH(newArr));
- }
- }
-
- void removeNode(){
- int e;
- int srcArr[] = { 10, 20, 30, 40, 50, 60 };
- int n = ARR_LENGTH(srcArr);
- ArrayBinaryTree bt(srcArr, n);
- {
- SCOPED_TRACE("tree arr before remove");
- checkElements(&bt, srcArr, n);
- }
-
- // remove a single node
- bool ok = bt.removeNode(bt.root(), e); // 10
- ASSERT_EQ(true, ok) << "remove(root) failed";
- ASSERT_EQ(10, e) << "removed element should have been 10";
- // arr = { ?, 20, 30, 40, 50, 60 };
- {
- SCOPED_TRACE("removeNode(10)");
- int newArr[] = { 20, 30, 40, 50, 60 };
- checkElements(&bt, newArr, 5);
-
- ASSERT_EQ(5, bt.size()) << "size of the tree should be 5";
- ASSERT_EQ(0, (int)bt.nodeAt(1)) << "the pointer at the deleted position must be NULL";
- }
-
- // remove another single node
- ok = bt.removeNode(bt.nodeAt(3), e); // 30
- ASSERT_EQ(true, ok) << "removeNode(30) failed";
- ASSERT_EQ(30, e) << "removed element should have been 30";
- // arr = { ?, 20, ?, 40, 50, 60 };
- {
- SCOPED_TRACE("removeNode(30)");
- int newArr[] = { 20, 40, 50, 60 };
- checkElements(&bt, newArr, 4);
-
- ASSERT_EQ(4, bt.size()) << "size of the tree should be 4";
- ASSERT_EQ(0, (int)bt.nodeAt(3)) << "the pointer at the deleted position must be NULL";
- }
-
- }
-
- void clear(){
- int srcArr[] = { 10, 20, 30, 40, 50, 60 };
- int n = ARR_LENGTH(srcArr);
- ArrayBinaryTree bt(srcArr, n);
- bt.clear();
- ASSERT_EQ(0, bt.size()) << "size not 0";
- ASSERT_EQ(true, bt.empty()) << "tree not empty";
- ASSERT_EQ(NULL, bt.root()) << "root not NULL";
-
- }
-
- //void addElements(){
- // ArrayBinaryTree bt;
- // bt.addRoot(10);
- // bt.addLeft(20, bt.root());
- // bt.addRight(30, bt.root());
- // ASSERT_EQ(true, bt.isInternal(bt.root())) << "root should have been internal";
- // ASSERT_EQ(true, bt.isExternal(bt.left(bt.root()))) << "root's left child should have been external";
- // bt.addLeft(40, bt.left(bt.root()));
- // ASSERT_EQ(false, bt.isExternal(bt.left(bt.root()))) << "root's left child should have been internal";
- // bt.addRight(70, bt.right(bt.root()));
- //}
- };
-
- // create tests
- ADD_TEST_F(ArrayBinaryTreeTest, constructor);
- ADD_TEST_F(ArrayBinaryTreeTest, isArrIndex);
- ADD_TEST_F(ArrayBinaryTreeTest, nodeAt);
- ADD_TEST_F(ArrayBinaryTreeTest, nodeNotNull);
- ADD_TEST_F(ArrayBinaryTreeTest, addRoot);
- ADD_TEST_F(ArrayBinaryTreeTest, insertAt);
- ADD_TEST_F(ArrayBinaryTreeTest, replaceAt);
- ADD_TEST_F(ArrayBinaryTreeTest, remove);
- ADD_TEST_F(ArrayBinaryTreeTest, removeNode);
- ADD_TEST_F(ArrayBinaryTreeTest, sibling);
- ADD_TEST_F(ArrayBinaryTreeTest, elements);
- ADD_TEST_F(ArrayBinaryTreeTest, fromArr);
- ADD_TEST_F(ArrayBinaryTreeTest, resize);
- ADD_TEST_F(ArrayBinaryTreeTest, toString);
- ADD_TEST_F(ArrayBinaryTreeTest, clear);
-
}
}
\ No newline at end of file
diff --git a/YASI_12/ds.arraybinarytree.test.h b/YASI_12/ds.arraybinarytree.test.h
new file mode 100644
index 0000000..27c50c0
--- /dev/null
+++ b/YASI_12/ds.arraybinarytree.test.h
@@ -0,0 +1,429 @@
+#pragma once
+
+#if YASI_TEST_THIS_MODULE != 1
+#define YASI_TEST_THIS_MODULE 1
+#endif
+#include "ds.arraybinarytree.h"
+
+namespace yasi{
+ namespace ds{
+
+ ///
+ /// Test IndexedBTNode
+ ///
+ class IndexedBTNodeTest :public yasi::Test{
+ protected:
+ void init(){
+ IndexedBTNode n1;
+ ASSERT_EQ(-1, n1._index) << "Default index should be -1";
+ n1.setIndex(5);
+ ASSERT_EQ(5, n1.index()) << "index should be 5";
+ n1.setElement(7);
+ ASSERT_EQ(7, n1.element) << "element should be 5";
+
+ n1.makeNull();
+ ASSERT_EQ(1, n1.isNull()) << "makeNull() and isNull() disagree";
+ }
+ void indexing(){
+ const int N = 7;
+ IndexedBTNode n[N];
+ for (int i = 0; i < N; i++){
+ n[i].setIndex(i);
+ }
+ ASSERT_EQ(0, n[0].leftIndex()) << "left of 0 must be 0";
+ ASSERT_EQ(1, n[0].rightIndex()) << "right of 0 must be 1";
+
+ ASSERT_EQ(1, n[2].parentIndex()) << "parent of 2 must be 1";
+ ASSERT_EQ(1, n[3].parentIndex()) << "parent of 3 must be 1";
+ ASSERT_EQ(2, n[4].parentIndex()) << "parent of 4 must be 2";
+ ASSERT_EQ(4, n[2].leftIndex()) << "left of 2 must be 4";
+ ASSERT_EQ(5, n[2].rightIndex()) << "right of 2 must be 5";
+
+ }
+ };
+ ADD_TEST_F(IndexedBTNodeTest, init);
+ ADD_TEST_F(IndexedBTNodeTest, indexing);
+ ////////////// end testing IndexedBTNode
+
+ ///
+ /// Test ArrayBinaryTree
+ ///
+ class ArrayBinaryTreeTest : public yasi::Test{
+ protected:
+ typedef ArrayBinaryTree::node_t node_t;
+ typedef ArrayBinaryTree::node_t* node_tptr;
+ public:
+
+ template
+ static void checkElements(ArrayBinaryTree *pBt, const E* pElemsArr, const int numElems){
+ // finally, check array
+ E *pTreeElems;
+ int n;
+ ArrayBinaryTree& bt = *pBt; // must use reference, otherwise the tree will be destroyed upon exit
+ bt.elements(&pTreeElems, n);
+ ASSERT_EQ(n, numElems) << "actual array size " << n << " should equal target size " << numElems << endl
+ << "actual : " << arrToString(pTreeElems, n) << endl
+ << "expected: " << arrToString(pElemsArr, n);
+
+ ASSERT_EQ(true, arrcmp(pTreeElems, pElemsArr, n)) << "elements array not right." << endl
+ << "actual : " << arrToString(pTreeElems, n) << endl
+ << "expected: " << arrToString(pElemsArr, n);
+
+ // done
+ DELETE_ARR_SAFE(pTreeElems);
+ }
+
+ void constructor(){
+ ArrayBinaryTree bt;
+ ASSERT_EQ(1, bt.ROOT_INDEX) << "Index of root is not 1";
+ ASSERT_LE(bt.INIT_CAPACITY, bt._arr.capacity()) << "Initial _capacity must be <= containers capacity";
+ ASSERT_LE(2, bt._arr.capacity()) << "Initial capacity must be >= 2";
+ ASSERT_EQ(0, bt.size()) << "Initial size is not zero";
+ for (int i = 0; i < bt._capacity; i++){
+ ASSERT_EQ(0, bt._arr[i]) << "Pointer at index " << i << " is not initialized to NULL";
+ }
+
+ ASSERT_EQ(NULL, bt.root()) << "root should have been NULL";
+ }
+
+ void elements(){
+ int srcArr[] = { 10, 20, 30, 40, 50, 60 };
+ int n = ARR_LENGTH(srcArr);
+ ArrayBinaryTree bt(srcArr, n);
+
+ int* pElemArr;
+ int numElems;
+ bt.elements(&pElemArr, numElems);
+ ASSERT_EQ(n, numElems) << "number of elements is not " << n;
+ for (int i = 0; i < numElems; i++){
+ ASSERT_EQ(srcArr[i], pElemArr[i]) << "element mismatch at index " << i;
+ }
+ DELETE_ARR_SAFE(pElemArr);
+ }
+
+ void fromArr(){
+ int srcArr[] = { 10, 20, 30, 40, 50, 60 };
+ int n = ARR_LENGTH(srcArr);
+ ArrayBinaryTree bt(srcArr, n);
+ ASSERT_EQ(n, bt.size()) << "size of tree is not " << n;
+ // check node-ptrs stored in internal container
+ int i = 0;
+ for (int i = 0; i < bt._capacity; i++){
+ if (i >= 1 && i <= n){
+ // valid node-ptrs
+ ASSERT_NE(0, (int)bt._arr[i]) << "Pointer NULL at index " << i;
+ ASSERT_EQ(srcArr[i - 1], bt._arr[i]->element) << "array element mismatch for internal index " << i;
+ }
+ else{
+ // invalid node-ptrs
+ ASSERT_EQ(0, (int)bt._arr[i]) << "Pointer not NULL at index " << i;
+ }
+ }
+ // also, use elements() method
+ int* pElemArr;
+ int numElems;
+ bt.elements(&pElemArr, numElems);
+ ASSERT_EQ(n, numElems) << "number of elements is not " << n;
+ for (int i = 0; i < numElems; i++){
+ ASSERT_EQ(srcArr[i], pElemArr[i]) << "element mismatch at index " << i;
+ }
+ DELETE_ARR_SAFE(pElemArr);
+ }
+
+ void isArrIndex(){
+ ArrayBinaryTree bt;
+ ASSERT_EQ(false, bt.isArrIndex(-1)) << "Negative index is accepted";
+ ASSERT_EQ(true, bt.isArrIndex(0)) << "0 index is rejected";
+ ASSERT_EQ(true, bt.isArrIndex(bt._capacity - 1)) << "index (capacity - 1) is rejected";
+ ASSERT_EQ(false, bt.isArrIndex(bt._capacity)) << "index beyond capacity is accepted";
+ }
+
+ void nodeAt(){
+ ArrayBinaryTree bt;
+ bt.addRoot(5);
+
+ bt.nodeAt(-1);
+
+ ASSERT_EQ(0, (int)bt.nodeAt(-1)) << "Negative index is accepted";
+ ASSERT_EQ(0, (int)bt.nodeAt(0)) << "Index 0 is accepted";
+ ASSERT_EQ(0, (int)bt.nodeAt(bt._capacity)) << "Too large index is accepted";
+ ASSERT_NE(0, (int)bt.nodeAt(1)) << "The root is not recognized";
+
+ int e;
+ bt.remove(bt.root(), e); // remove root
+ ASSERT_EQ(0, (int)bt.nodeAt(1)) << "TreeNode accepted after deletion";
+ }
+
+ void nodeNotNull(){
+ ArrayBinaryTree bt;
+ bt.addRoot(5);
+
+ ASSERT_EQ(false, bt.nodeNotNull(-1)) << "Negative index is accepted";
+ ASSERT_EQ(false, bt.nodeNotNull(0)) << "Zero index is accepted";
+ ASSERT_EQ(false, bt.nodeNotNull(bt._capacity)) << "Too large index is accepted";
+ ASSERT_EQ(true, bt.nodeNotNull(1)) << "The root is not recognized";
+
+ int e;
+ bt.remove(bt.root(), e); // remove root
+ ASSERT_EQ(false, bt.nodeNotNull(1)) << "TreeNode accepted after deletion";
+ }
+
+ void addRoot(){
+ ArrayBinaryTree bt;
+ ASSERT_EQ(0, bt.size());
+ bt.addRoot(10);
+ ASSERT_EQ(1, bt.size()) << "tree-size should have been 1";
+ ASSERT_EQ(0, (int)bt.nodeAt(0)) << "As per Goodrich-Tamassia convention, first slot in the array should have been empty";
+ ASSERT_EQ(10, bt.nodeAt(1)->element) << "Value at the root should have been 10";
+ ASSERT_EQ(false, bt.isLeft(bt.root())) << "root cannot be a left child";
+ ASSERT_EQ(false, bt.isRight(bt.root())) << "root cannot be a right child";
+ ASSERT_EQ(false, bt.isInternal(bt.root())) << "root should have been external";
+ ASSERT_EQ(false, bt.hasLeft(bt.root())) << "root does not have a left child";
+ ASSERT_EQ(false, bt.hasRight(bt.root())) << "root does not have a right child";
+ }
+
+ void insertAt(){
+ ArrayBinaryTree bt;
+ EXPECT_EQ(0, (int)bt.insertAt(4, -1)) << "inserting at negative index succeeded";
+ EXPECT_EQ(0, (int)bt.insertAt(4, 0)) << "inserting at 0 index succeeded";
+ EXPECT_NE(0, (int)bt.insertAt(4, 2 * bt._capacity)) << "inserting at too large index failed";
+ ASSERT_NE(0, (int)bt.insertAt(4, 1)) << "inserting at index 1 failed";
+ ASSERT_EQ(0, (int)bt.insertAt(4, 1)) << "inserting at an occupied index succeeded";
+ bt.remove(bt.nodeAt(1));
+ ASSERT_NE(0, (int)bt.insertAt(4, 1)) << "inserting at a recently deleted slot failed";
+ }
+
+ void replaceAt(){
+ ArrayBinaryTree bt;
+ EXPECT_EQ(0, (int)bt.replaceAt(4, -1)) << "replacing at negative index succeeded";
+ EXPECT_EQ(0, (int)bt.replaceAt(4, 0)) << "replacing at 0 index succeeded";
+ EXPECT_EQ(0, (int)bt.replaceAt(4, 2 * bt._capacity)) << "replacing at too large index succeeded";
+ ASSERT_EQ(0, (int)bt.replaceAt(4, 1)) << "replacing at unused index 1 succeeded";
+ bt.addRoot(10);
+ ASSERT_NE(0, (int)bt.replaceAt(4, 1)) << "replacing at occupied index 1 failed";
+ int index = bt.root()->index();
+ bt.remove(bt.root());
+ ASSERT_EQ(0, (int)bt.replaceAt(4, index)) << "replacing at a recently deleted index succeeded";
+ }
+
+ void sibling(){
+ ArrayBinaryTree bt;
+ ASSERT_EQ(0, (int)bt.sibling(bt.nodeAt(0))) << "sibling of NULL node succeeded";
+ bt.addRoot(4);
+ ASSERT_EQ(0, (int)bt.sibling(bt.root())) << "sibling of root node succeeded";
+ ArrayBinaryTree::node_t* n1 = bt.addLeft(5, bt.root());
+ ASSERT_EQ(0, (int)bt.sibling(n1)) << "sibling of only-child succeeded";
+ ArrayBinaryTree::node_t* n2 = bt.addRight(5, bt.root());
+ ASSERT_EQ(n2, bt.sibling(n1)) << "sibling of valid node failed";
+ bt.remove(bt.left(bt.root())); // remove n1
+ ASSERT_EQ(0, (int)bt.sibling(n2)) << "sibling of a deleted-sibling-node succeeded";
+
+ }
+
+ void resize(){
+ int srcArr[] = { 10, 20, 30, 40, 50 };
+ int n = ARR_LENGTH(srcArr);
+ ArrayBinaryTree bt(srcArr, n);
+ int oldCapacity = bt._capacity;
+ // copy current data
+ // node_tptr is actually int (because it is a pointer)
+ node_tptr* pOldArr = new node_tptr[oldCapacity];
+ memcpy(pOldArr, (node_tptr*)bt._arr.data(), sizeof(node_tptr) * oldCapacity);
+
+ bt.resize(2 * oldCapacity + 5, 0);
+ int newCapacity = bt._capacity;
+ const node_tptr* pNewArr = (node_tptr*)bt._arr.data();
+ // all new slots must be initialized to zero
+ for (int i = 0; i < newCapacity; i++){
+ if (i < oldCapacity){
+ // old slots
+ ASSERT_EQ(pOldArr[i], pNewArr[i]) << "content mismatch at index " << i;
+ }
+ else{
+ // new slots
+ ASSERT_EQ(0, pNewArr[i]) << "new slots contain non-NULL pointer at index " << i;
+ }
+ }
+ // done test
+ DELETE_ARR_SAFE(pOldArr);
+ }
+
+ void toString(){
+ int srcArr[] = { 10, 20, 30, 40, 50, 60, 70 };
+ int n = ARR_LENGTH(srcArr);
+ ArrayBinaryTree bt(srcArr, n);
+ // delete 50 and 60
+ int e1, e2;
+ bool ok = bt.remove(bt.nodeAt(5), e1);
+ ASSERT_EQ(true, ok) << "falied to remove 50";
+ ASSERT_EQ(50, e1) << "50 was not deleted";
+ ok = bt.remove(bt.nodeAt(6), e2);
+ ASSERT_EQ(true, ok) << "falied to remove 60";
+ ASSERT_EQ(60, e2) << "60 was not deleted";
+
+ // now print
+ const char* sDelim = "|"; // need to be single-char for testing purpose
+ const char* sEmptySlot = ""; // need to be empty for testing purpose
+ string strBt = bt.toStringNodeArray(sDelim, sEmptySlot);
+ // remove trailing single-char delimiters
+ for (int i = strBt.length() - 1; strBt[i] == sDelim[0]; i--){
+ strBt[i] = NULL;
+ }
+ strBt = string(strBt.c_str());
+ // now strBt should equal "|10|20|30|40|||70"
+ string strExpected = "|10|20|30|40|||70";
+ ASSERT_EQ(strExpected, strBt) << "Expected " << strExpected << " but found " << strBt;
+
+
+ bt.clear();
+ bt.fromArray(srcArr, n);// 10 20 30 40 50 60 70
+ /////////// preorder
+ strBt = bt.toStringPreOrder();
+ strBt = strPurge(strBt, "| ");
+ strExpected = "10204050306070";
+ ASSERT_EQ(strExpected, strBt) << "preorder mismatch";
+
+ /////////// postorder
+ strBt = bt.toStringPostOrder();
+ strBt = strPurge(strBt, "| ");
+ strExpected = "40502060703010";
+ ASSERT_EQ(strExpected, strBt) << "postorder mismatch";
+
+ /////////// inorder
+ strBt = bt.toStringInOrder();
+ strBt = strPurge(strBt, "| ");
+ strExpected = "40205010603070";
+ ASSERT_EQ(strExpected, strBt) << "inorder mismatch";
+
+
+ /////////// BFSorder
+ strBt = bt.toStringBFS();
+ strBt = strPurge(strBt, "| ");
+ strExpected = "10203040506070";
+ ASSERT_EQ(strExpected, strBt) << "BFS order mismatch";
+ }
+
+ void remove(){
+ int e;
+ int srcArr[] = { 10, 20, 30, 40, 50, 60 };
+ int n = ARR_LENGTH(srcArr);
+ ArrayBinaryTree bt(srcArr, n);
+ {
+ SCOPED_TRACE("tree arr before remove");
+ checkElements(&bt, srcArr, n);
+ }
+ //bt.toString(&cBt);
+ //DELETE_ARR_SAFE(cBt);
+
+
+ bool ok = bt.remove(bt.nodeAt(0));
+ ASSERT_EQ(false, ok) << "removing from index 0 succeeded";
+ ok = bt.remove(bt.nodeAt(-1));
+ ASSERT_EQ(false, ok) << "removing from negative index succeeded";
+
+ //bt.toString(&cBt);
+ //DELETE_ARR_SAFE(cBt);
+
+ // removing the root will remove the entire tree
+ ok = bt.remove(bt.root(), e); // 10
+ ASSERT_EQ(true, ok) << "remove(root) failed";
+ ASSERT_EQ(10, e) << "removed element should have been 10";
+ ASSERT_EQ(0, bt.size()) << "Deleting subtree at root should make the size zero.";
+
+ // remove a subtree
+ bt.fromArray(srcArr, ARR_LENGTH(srcArr));
+ // arr = { 10, 20, 30, 40, 50, 60 };
+ ok = bt.remove(bt.left(bt.root()), e); // remove subtree 20
+ ASSERT_EQ(true, ok) << "remove(20) failed";
+ ASSERT_EQ(20, e) << "removed element should have been 20";
+ ASSERT_EQ(ARR_LENGTH(srcArr) - 3, bt.size()) << "Remaining tree has improper size";
+ {
+ SCOPED_TRACE("remove(20)");
+ int newArr[] = { 10, 30, 60 };
+ checkElements(&bt, newArr, ARR_LENGTH(newArr));
+ }
+ }
+
+ void removeNode(){
+ int e;
+ int srcArr[] = { 10, 20, 30, 40, 50, 60 };
+ int n = ARR_LENGTH(srcArr);
+ ArrayBinaryTree bt(srcArr, n);
+ {
+ SCOPED_TRACE("tree arr before remove");
+ checkElements(&bt, srcArr, n);
+ }
+
+ // remove a single node
+ bool ok = bt.removeNode(bt.root(), e); // 10
+ ASSERT_EQ(true, ok) << "remove(root) failed";
+ ASSERT_EQ(10, e) << "removed element should have been 10";
+ // arr = { ?, 20, 30, 40, 50, 60 };
+ {
+ SCOPED_TRACE("removeNode(10)");
+ int newArr[] = { 20, 30, 40, 50, 60 };
+ checkElements(&bt, newArr, 5);
+
+ ASSERT_EQ(5, bt.size()) << "size of the tree should be 5";
+ ASSERT_EQ(0, (int)bt.nodeAt(1)) << "the pointer at the deleted position must be NULL";
+ }
+
+ // remove another single node
+ ok = bt.removeNode(bt.nodeAt(3), e); // 30
+ ASSERT_EQ(true, ok) << "removeNode(30) failed";
+ ASSERT_EQ(30, e) << "removed element should have been 30";
+ // arr = { ?, 20, ?, 40, 50, 60 };
+ {
+ SCOPED_TRACE("removeNode(30)");
+ int newArr[] = { 20, 40, 50, 60 };
+ checkElements(&bt, newArr, 4);
+
+ ASSERT_EQ(4, bt.size()) << "size of the tree should be 4";
+ ASSERT_EQ(0, (int)bt.nodeAt(3)) << "the pointer at the deleted position must be NULL";
+ }
+
+ }
+
+ void clear(){
+ int srcArr[] = { 10, 20, 30, 40, 50, 60 };
+ int n = ARR_LENGTH(srcArr);
+ ArrayBinaryTree bt(srcArr, n);
+ bt.clear();
+ ASSERT_EQ(0, bt.size()) << "size not 0";
+ ASSERT_EQ(true, bt.empty()) << "tree not empty";
+ ASSERT_EQ(NULL, bt.root()) << "root not NULL";
+
+ }
+
+ //void addElements(){
+ // ArrayBinaryTree bt;
+ // bt.addRoot(10);
+ // bt.addLeft(20, bt.root());
+ // bt.addRight(30, bt.root());
+ // ASSERT_EQ(true, bt.isInternal(bt.root())) << "root should have been internal";
+ // ASSERT_EQ(true, bt.isExternal(bt.left(bt.root()))) << "root's left child should have been external";
+ // bt.addLeft(40, bt.left(bt.root()));
+ // ASSERT_EQ(false, bt.isExternal(bt.left(bt.root()))) << "root's left child should have been internal";
+ // bt.addRight(70, bt.right(bt.root()));
+ //}
+ };
+
+ // create tests
+ ADD_TEST_F(ArrayBinaryTreeTest, constructor);
+ ADD_TEST_F(ArrayBinaryTreeTest, isArrIndex);
+ ADD_TEST_F(ArrayBinaryTreeTest, nodeAt);
+ ADD_TEST_F(ArrayBinaryTreeTest, nodeNotNull);
+ ADD_TEST_F(ArrayBinaryTreeTest, addRoot);
+ ADD_TEST_F(ArrayBinaryTreeTest, insertAt);
+ ADD_TEST_F(ArrayBinaryTreeTest, replaceAt);
+ ADD_TEST_F(ArrayBinaryTreeTest, remove);
+ ADD_TEST_F(ArrayBinaryTreeTest, removeNode);
+ ADD_TEST_F(ArrayBinaryTreeTest, sibling);
+ ADD_TEST_F(ArrayBinaryTreeTest, elements);
+ ADD_TEST_F(ArrayBinaryTreeTest, fromArr);
+ ADD_TEST_F(ArrayBinaryTreeTest, resize);
+ ADD_TEST_F(ArrayBinaryTreeTest, toString);
+ ADD_TEST_F(ArrayBinaryTreeTest, clear);
+
+ }
+}
\ No newline at end of file
diff --git a/YASI_12/ds.binarytree.h b/YASI_12/ds.binarytree.h
index dc8d8e2..194dc08 100644
--- a/YASI_12/ds.binarytree.h
+++ b/YASI_12/ds.binarytree.h
@@ -7,6 +7,8 @@
#include
using namespace std;
+#include "test.this.module.h"
+
namespace yasi{
namespace ds{
@@ -68,7 +70,7 @@ class BinaryTreeNode : public virtual TreeNode,
template >
class BinaryTree : public virtual BinaryTreeBase {
//////////////// enable testing ////////////
- friend class BinaryTreeTest;
+ FRIEND_TEST_CLASS(BinaryTreeTest);
protected:
typedef Node node_t;
@@ -182,351 +184,6 @@ class BinaryTree : public virtual BinaryTreeBase {
};
-// test
-class BinaryTreeTest : public yasi::Test{
-public:
- typedef BinaryTree > Tree;
- typedef Tree::node_t node_t;
- ///////////////////////////
- /////// IBinaryTree methods
- ///////////////////////////
-
- // size, empty
- // left, right, parent, sibling, root, numChildren
- // isLeft, isRight, hasLeft, hasRight
- // isInternal, isExternal, isRoot
- // addLeft, addRight, addRoot
- void add(){
- Tree t;
-
- // add root
- node_t* n0 = t.addRoot(0);
- ASSERT_EQ(1, t.size()) << "size not 1";
- ASSERT_EQ(false, t.empty()) << "tree empty";
- ASSERT_EQ(n0, t.root()) << "root not n0";
- ASSERT_EQ(true, t.isRoot(n0)) << "root not n0";
- ASSERT_EQ(0, n0->element) << "root-element not 0";
- ASSERT_EQ(false, t.isLeft(n0)) << "n0 not a left child";
- ASSERT_EQ(false, t.isRight(n0)) << "n0 not a right child";
- ASSERT_EQ(false, t.hasLeft(n0)) << "root has not left child";
- ASSERT_EQ(false, t.hasRight(n0)) << "root has no right child";
- ASSERT_EQ(false, t.isInternal(n0)) << "root not internal yet";
- ASSERT_EQ(true, t.isExternal(n0)) << "root should be external now";
- ASSERT_EQ(NULL, t.left(n0)) << "left(root) should be NULL";
- ASSERT_EQ(NULL, t.right(n0)) << "right(root) should be NULL";
- ASSERT_EQ(NULL, t.parent(n0)) << "parent(root) should be NULL";
- ASSERT_EQ(NULL, t.sibling(n0)) << "sibling(root) should be NULL";
- ASSERT_EQ(0, t.numChildren(n0)) << "numChildren(root) should be 0";
-
- /////////////// add root->left
- node_t* n1 = t.addLeft(1, t.root());
- ASSERT_EQ(2, t.size()) << "size not 2";
- ASSERT_EQ(false, t.empty()) << "tree empty";
- // about root
- ASSERT_EQ(n0, t.root()) << "root not n0";
- ASSERT_EQ(n0, t.parent(n1)) << "n1 not child of n0";
- ASSERT_EQ(true, t.hasLeft(n0)) << "root has a left child";
- ASSERT_EQ(false, t.hasRight(n0)) << "root has no right child";
- ASSERT_EQ(true, t.isInternal(n0)) << "root is internal";
- ASSERT_EQ(false, t.isExternal(n0)) << "root not external now";
- ASSERT_EQ(NULL, t.right(n0)) << "right(root) should be NULL";
- ASSERT_EQ(NULL, t.parent(n0)) << "parent(root) should be NULL";
- ASSERT_EQ(NULL, t.sibling(n0)) << "sibling(root) should be NULL";
- ASSERT_EQ(1, t.numChildren(n0)) << "numChildren(root) should be 1";
- // about root->left
- ASSERT_EQ(1, n1->element) << "element not 1";
- ASSERT_EQ(n1, t.left(n0)) << "n1 not left child of n0";
- ASSERT_NE(n1, t.right(n0)) << "n1 right child of n0";
- ASSERT_EQ(true, t.isLeft(n1)) << "n1 is a left child";
- ASSERT_EQ(false, t.isRight(n1)) << "n1 is a right child";
- ASSERT_EQ(n0, t.parent(n1)) << "n0 not parent of n1";
- ASSERT_EQ(NULL, t.sibling(n1)) << "sibling(n1) wrong";
- ASSERT_EQ(false, t.isInternal(n1)) << "n1 is external";
- ASSERT_EQ(true, t.isExternal(n1)) << "n1 not internal now";
- ASSERT_EQ(false, t.hasLeft(n1)) << "n1 has left child";
- ASSERT_EQ(false, t.hasRight(n1)) << "n1 has right child";
- ASSERT_EQ(0, t.numChildren(n1)) << "numChildren(n1) should be 0";
- ASSERT_EQ(NULL, t.addLeft(-3, t.root())) << "root->left overwritten by addLeft()";
-
- /////////// add root->right
- node_t* n2 = t.addRight(2, t.root());
- ASSERT_EQ(3, t.size()) << "size not 3";
- ASSERT_EQ(false, t.empty()) << "tree empty";
- // about root
- ASSERT_EQ(n0, t.root()) << "root not n0";
- ASSERT_EQ(n0, t.parent(n2)) << "n2 not child of n0";
- ASSERT_EQ(true, t.hasLeft(n0)) << "root has a left child";
- ASSERT_EQ(true, t.hasRight(n0)) << "root has no right child";
- ASSERT_EQ(true, t.isInternal(n0)) << "root is internal";
- ASSERT_EQ(false, t.isExternal(n0)) << "root not external now";
- ASSERT_EQ(n2, t.right(n0)) << "right(root) should be n2";
- ASSERT_EQ(NULL, t.parent(n0)) << "parent(root) should be NULL";
- ASSERT_EQ(NULL, t.sibling(n0)) << "sibling(root) should be NULL";
- ASSERT_EQ(2, t.numChildren(n0)) << "numChildren(root) should be 2";
- // about root->left
- ASSERT_EQ(1, n1->element) << "element not 1";
- ASSERT_EQ(n1, t.left(n0)) << "n1 not left child of n0";
- ASSERT_NE(n1, t.right(n0)) << "n1 right child of n0";
- ASSERT_EQ(true, t.isLeft(n1)) << "n1 is a left child";
- ASSERT_EQ(false, t.isRight(n1)) << "n1 is a right child";
- ASSERT_EQ(n0, t.parent(n1)) << "n0 not parent of n1";
- ASSERT_EQ(n2, t.sibling(n1)) << "sibling(n1) wrong";
- ASSERT_EQ(false, t.isInternal(n1)) << "n1 is external";
- ASSERT_EQ(true, t.isExternal(n1)) << "n1 not internal now";
- ASSERT_EQ(false, t.hasLeft(n1)) << "n1 has left child";
- ASSERT_EQ(false, t.hasRight(n1)) << "n1 has right child";
- ASSERT_EQ(0, t.numChildren(n1)) << "numChildren(n1) should be 0";
- // about root->right
- ASSERT_EQ(2, n2->element) << "element not 2";
- ASSERT_EQ(n2, t.right(n0)) << "n2 not right child of n0";
- ASSERT_NE(n2, t.left(n0)) << "n2 left child of n0";
- ASSERT_EQ(false, t.isLeft(n2)) << "n2 is a left child";
- ASSERT_EQ(true, t.isRight(n2)) << "n2 not a right child";
- ASSERT_EQ(n0, t.parent(n2)) << "n0 not parent of n2";
- ASSERT_EQ(n1, t.sibling(n2)) << "sibling(n2) should be n1";
- ASSERT_EQ(false, t.isInternal(n2)) << "n2 is external";
- ASSERT_EQ(true, t.isExternal(n2)) << "n2 not internal now";
- ASSERT_EQ(false, t.hasLeft(n2)) << "n2 has left child";
- ASSERT_EQ(false, t.hasRight(n2)) << "n2 has right child";
- ASSERT_EQ(0, t.numChildren(n2)) << "numChildren(n2) should be 0";
- ASSERT_EQ(NULL, t.addRight(-3, t.root())) << "root->right overwritten by addRight()";
-
- /////////// add root->left->right
- node_t* n4 = t.addRight(4, n1);
- ASSERT_EQ(4, t.size()) << "size not 4";
- ASSERT_EQ(false, t.empty()) << "tree empty";
- // about root
- ASSERT_EQ(n0, t.root()) << "root not n0";
- ASSERT_EQ(n0, t.parent(t.parent(n4))) << "n2 not grand child of n0";
- ASSERT_EQ(true, t.hasLeft(n0)) << "root has a left child";
- ASSERT_EQ(true, t.hasRight(n0)) << "root has no right child";
- ASSERT_EQ(true, t.isInternal(n0)) << "root is internal";
- ASSERT_EQ(false, t.isExternal(n0)) << "root not external now";
- ASSERT_EQ(n2, t.right(n0)) << "right(root) should be n2";
- ASSERT_EQ(n1, t.left(n0)) << "left(root) should be n1";
- ASSERT_EQ(NULL, t.parent(n0)) << "parent(root) should be NULL";
- ASSERT_EQ(NULL, t.sibling(n0)) << "sibling(root) should be NULL";
- ASSERT_EQ(2, t.numChildren(n0)) << "numChildren(root) should be 1";
- // about root->left
- ASSERT_EQ(1, n1->element) << "element not 1";
- ASSERT_EQ(n1, t.left(n0)) << "n1 not left child of n0";
- ASSERT_NE(n1, t.right(n0)) << "n1 right child of n0";
- ASSERT_EQ(true, t.isLeft(n1)) << "n1 is a left child";
- ASSERT_EQ(false, t.isRight(n1)) << "n1 is a right child";
- ASSERT_EQ(n0, t.parent(n1)) << "n0 not parent of n1";
- ASSERT_EQ(n2, t.sibling(n1)) << "sibling(n1) wrong";
- ASSERT_EQ(true, t.isInternal(n1)) << "n1 external";
- ASSERT_EQ(false, t.isExternal(n1)) << "n1 internal now";
- ASSERT_EQ(false, t.hasLeft(n1)) << "n1 has no left child";
- ASSERT_EQ(true, t.hasRight(n1)) << "n1 has no right child";
- ASSERT_EQ(1, t.numChildren(n1)) << "numChildren(n1) should be 1";
- // about root->right
- ASSERT_EQ(2, n2->element) << "element not 2";
- ASSERT_EQ(n2, t.right(n0)) << "n2 not right child of n0";
- ASSERT_NE(n2, t.left(n0)) << "n2 left child of n0";
- ASSERT_EQ(false, t.isLeft(n2)) << "n2 is a left child";
- ASSERT_EQ(true, t.isRight(n2)) << "n2 not a right child";
- ASSERT_EQ(n0, t.parent(n2)) << "n0 not parent of n2";
- ASSERT_EQ(n1, t.sibling(n2)) << "sibling(n2) should be n1";
- ASSERT_EQ(false, t.isInternal(n2)) << "n2 is external";
- ASSERT_EQ(true, t.isExternal(n2)) << "n2 not internal now";
- ASSERT_EQ(false, t.hasLeft(n2)) << "n2 has left child";
- ASSERT_EQ(false, t.hasRight(n2)) << "n2 has right child";
- ASSERT_EQ(0, t.numChildren(n2)) << "numChildren(n2) should be 0";
- // about root->left->right
- ASSERT_EQ(4, n4->element) << "element not 4";
- ASSERT_EQ(n4, t.right(n1)) << "n4 not right child of n1";
- ASSERT_NE(n4, t.left(n1)) << "n4 left child of n1";
- ASSERT_EQ(false, t.isLeft(n4)) << "n4 is a left child";
- ASSERT_EQ(true, t.isRight(n4)) << "n4 not a right child";
- ASSERT_EQ(n1, t.parent(n4)) << "n1 not parent of n4";
- ASSERT_EQ(NULL, t.sibling(n4)) << "sibling(n4) should be NULL";
- ASSERT_EQ(false, t.isInternal(n4)) << "n4 is external";
- ASSERT_EQ(true, t.isExternal(n4)) << "n4 not internal now";
- ASSERT_EQ(false, t.hasLeft(n4)) << "n4 has left child";
- ASSERT_EQ(false, t.hasRight(n4)) << "n4 has right child";
- ASSERT_EQ(0, t.numChildren(n4)) << "numChildren(n4) should be 0";
- ASSERT_EQ(NULL, t.addRight(-3, t.root()->left() )) << "root->left->right overwritten by addRight()";
-
-
-
- //ASSERT_EQ(0, 1) << "test incomplete";
-
- }
-
-
-
- // remove
- void removeNode(){
- Tree t;
- node_t* n0 = t.addRoot(0);
- node_t* n1 = t.addLeft(1, n0);
- node_t* n2 = t.addRight(2, n0);
- node_t* n4 = t.addRight(4, n1);
- // remove root->left->right
- int e;
- bool ok = t.removeNode(n4, e); // remove n4
- ASSERT_EQ(true, ok) << "remove failed";
- ASSERT_EQ(4, e) << "wrong element";
- ASSERT_EQ(3, t.size()) << "size not 3";
- ASSERT_EQ(NULL, n1->left()) << "n1->left not NULL";
- ASSERT_EQ(0, t.numChildren(n1)) << "n1 has children";
- ASSERT_EQ(false, t.isInternal(n1)) << "n1 still internal";
- ASSERT_EQ(true, t.isExternal(n1)) << "n1 not external";
-
- // now delete n2
- ok = t.removeNode(n2, e); // remove n4
- ASSERT_EQ(true, ok) << "remove failed";
- ASSERT_EQ(2, e) << "wrong element";
- ASSERT_EQ(2, t.size()) << "size not 2";
- ASSERT_EQ(NULL, n0->right()) << "n0->right not NULL";
- ASSERT_EQ(n1, n0->left()) << "n0->left not n1";
- ASSERT_EQ(false, t.hasRight(t.root())) << "root still has right";
- ASSERT_EQ(true, t.hasLeft(t.root())) << "root has no left";
- ASSERT_EQ(1, t.numChildren(t.root())) << "n1->left not NULL";
- ASSERT_EQ(NULL, t.sibling(n1)) << "n1 still has sibling";
-
- // try to remove an internal node (should not work)
- // add n4 back at root->left->right
- n4 = t.addRight(4, t.root()->left());
- ASSERT_EQ(true, t.isInternal(n1)) << "n1 still external";
- ASSERT_EQ(3, t.size()) << "size not 3";
- ok = t.removeNode(n1, e); // attempt removing n1
- ASSERT_EQ(false, ok) << "removeNode() deleted internal node";
-
- // try to delete root
- ok = t.removeNode(t.root(), e); // remove n1
- ASSERT_EQ(false, ok) << "removeNode() deleted root";
-
-
- }
-
- void remove(){
- Tree t;
- int e;
- node_t* n0 = t.addRoot(0);
- node_t* n1 = t.addLeft(1, n0);
- node_t* n2 = t.addRight(2, n0);
- node_t* n3 = t.addLeft(3, n1);
- node_t* n4 = t.addRight(4, n1);
-
- ///////////////// try deleting subtree at internal node
- ASSERT_EQ(5, t.size()) << "size not 4";
-
- bool ok = t.remove(n1, e); // remove subtree at n1
- ASSERT_EQ(true, ok) << "remove failed";
- ASSERT_EQ(2, t.size()) << "size not 2";
- ASSERT_EQ(1, e) << "wrong element removed";
- ASSERT_EQ(false, t.hasLeft(t.root())) << "root still has left";
- ASSERT_EQ(1, t.numChildren(t.root())) << "root does not have 1 child";
-
- // try removing external node
- ok = t.remove(n2, e); // remove subtree at n2 (single node)
- ASSERT_EQ(true, ok) << "remove failed";
- ASSERT_EQ(1, t.size()) << "size not 2";
- ASSERT_EQ(2, e) << "wrong element removed";
- ASSERT_EQ(false, t.isInternal(t.root())) << "root still internal";
- ASSERT_EQ(0, t.numChildren(t.root())) << "root does not have any child";
-
- // try deleting the entire tree
- n1 = t.addLeft(1, t.root());
- n2 = t.addRight(2, t.root());
- n3 = t.addLeft(3, n1);
- n4 = t.addRight(4, n1);
- node_t* n5 = t.addLeft(5, n2);
-
- ok = t.remove(t.root(), e); // remove subtree at root (whole tree)
- ASSERT_EQ(true, ok) << "remove failed";
- ASSERT_EQ(0, t.size()) << "size not 0";
- ASSERT_EQ(true, t.empty()) << "tree not empty";
- ASSERT_EQ(0, e) << "wrong element removed";
- ASSERT_EQ(NULL, t.root()) << "root not NULL";
-
- }
-
- void clear(){
- node_t *n0, *n1, *n2, *n3, *n4;
- Tree t;
- //////// clear
- t.clear(); // should have no effect
-
- n0 = t.addRoot(0);
- n1 = t.addLeft(1, t.root());
- n2 = t.addRight(2, t.root());
- n3 = t.addLeft(3, n1);
- n4 = t.addRight(4, n1);
-
- ASSERT_EQ(4, t.size()) << "size not 4";
- ASSERT_EQ(false, t.empty()) << "tree empty";
- ASSERT_NE(NULL, (int)t.root()) << "root NULL";
-
- t.clear();
-
- ASSERT_EQ(0, t.size()) << "size not 0";
- ASSERT_EQ(true, t.empty()) << "tree not empty";
- ASSERT_EQ(NULL, (int) t.root()) << "root not NULL";
-
- }
-
- void toString(){
- Tree t;
- node_t* n0 = t.addRoot(0);
-
- node_t* n1 = t.addLeft(1, n0);
- node_t* n2 = t.addRight(2, n0);
-
- node_t* n3 = t.addLeft(3, n1);
- // no 4
- node_t* n5 = t.addLeft(5, n2);
- node_t* n6 = t.addRight(6, n2);
- // no 7
- node_t* n8 = t.addRight(8, n3);
- /*
- 0
- 1 2
- 3 - 5 6
- - 8
-
- */
-
- const string preorderTrimmed = "0138256"; // preorder, without space
- string str = t.toString(); // result, with space
- // remove space
- string actualTrimmed = strPurge(str, "| "); // purge | and space
- ASSERT_EQ(actualTrimmed, preorderTrimmed) << "toString() mismatch";
-
- string strBt, strExpected;
- /////////// preorder
- strBt = t.toStringPreOrder();
- strBt = strPurge(strBt, "| ");
- strExpected = "0138256";
- ASSERT_EQ(strExpected, strBt) << "preorder mismatch";
-
- /////////// postorder
- strBt = t.toStringPostOrder();
- strBt = strPurge(strBt, "| ");
- strExpected = "8315620";
- ASSERT_EQ(strExpected, strBt) << "postorder mismatch";
-
- /////////// inorder
- strBt = t.toStringInOrder();
- strBt = strPurge(strBt, "| ");
- strExpected = "3810526";
- ASSERT_EQ(strExpected, strBt) << "inorder mismatch";
-
-
- /////////// BFSorder
- strBt = t.toStringBFS();
- strBt = strPurge(strBt, "| ");
- strExpected = "0123568";
- ASSERT_EQ(strExpected, strBt) << "BFS order mismatch";
- }
-
-};
-ADD_TEST_F(BinaryTreeTest, add);
-ADD_TEST_F(BinaryTreeTest, removeNode);
-ADD_TEST_F(BinaryTreeTest, remove);
-ADD_TEST_F(BinaryTreeTest, toString);
} // namespace ds
} // namespace yasi
\ No newline at end of file
diff --git a/YASI_12/ds.binarytree.test.h b/YASI_12/ds.binarytree.test.h
new file mode 100644
index 0000000..29291ea
--- /dev/null
+++ b/YASI_12/ds.binarytree.test.h
@@ -0,0 +1,357 @@
+#pragma once
+
+#if YASI_TEST_THIS_MODULE != 1
+#define YASI_TEST_THIS_MODULE 1
+#endif
+#include "ds.binarytree.h"
+
+namespace yasi{
+ namespace ds{
+
+ // test
+ class BinaryTreeTest : public yasi::Test{
+ public:
+ typedef BinaryTree > Tree;
+ typedef Tree::node_t node_t;
+ ///////////////////////////
+ /////// IBinaryTree methods
+ ///////////////////////////
+
+ // size, empty
+ // left, right, parent, sibling, root, numChildren
+ // isLeft, isRight, hasLeft, hasRight
+ // isInternal, isExternal, isRoot
+ // addLeft, addRight, addRoot
+ void add(){
+ Tree t;
+
+ // add root
+ node_t* n0 = t.addRoot(0);
+ ASSERT_EQ(1, t.size()) << "size not 1";
+ ASSERT_EQ(false, t.empty()) << "tree empty";
+ ASSERT_EQ(n0, t.root()) << "root not n0";
+ ASSERT_EQ(true, t.isRoot(n0)) << "root not n0";
+ ASSERT_EQ(0, n0->element) << "root-element not 0";
+ ASSERT_EQ(false, t.isLeft(n0)) << "n0 not a left child";
+ ASSERT_EQ(false, t.isRight(n0)) << "n0 not a right child";
+ ASSERT_EQ(false, t.hasLeft(n0)) << "root has not left child";
+ ASSERT_EQ(false, t.hasRight(n0)) << "root has no right child";
+ ASSERT_EQ(false, t.isInternal(n0)) << "root not internal yet";
+ ASSERT_EQ(true, t.isExternal(n0)) << "root should be external now";
+ ASSERT_EQ(NULL, t.left(n0)) << "left(root) should be NULL";
+ ASSERT_EQ(NULL, t.right(n0)) << "right(root) should be NULL";
+ ASSERT_EQ(NULL, t.parent(n0)) << "parent(root) should be NULL";
+ ASSERT_EQ(NULL, t.sibling(n0)) << "sibling(root) should be NULL";
+ ASSERT_EQ(0, t.numChildren(n0)) << "numChildren(root) should be 0";
+
+ /////////////// add root->left
+ node_t* n1 = t.addLeft(1, t.root());
+ ASSERT_EQ(2, t.size()) << "size not 2";
+ ASSERT_EQ(false, t.empty()) << "tree empty";
+ // about root
+ ASSERT_EQ(n0, t.root()) << "root not n0";
+ ASSERT_EQ(n0, t.parent(n1)) << "n1 not child of n0";
+ ASSERT_EQ(true, t.hasLeft(n0)) << "root has a left child";
+ ASSERT_EQ(false, t.hasRight(n0)) << "root has no right child";
+ ASSERT_EQ(true, t.isInternal(n0)) << "root is internal";
+ ASSERT_EQ(false, t.isExternal(n0)) << "root not external now";
+ ASSERT_EQ(NULL, t.right(n0)) << "right(root) should be NULL";
+ ASSERT_EQ(NULL, t.parent(n0)) << "parent(root) should be NULL";
+ ASSERT_EQ(NULL, t.sibling(n0)) << "sibling(root) should be NULL";
+ ASSERT_EQ(1, t.numChildren(n0)) << "numChildren(root) should be 1";
+ // about root->left
+ ASSERT_EQ(1, n1->element) << "element not 1";
+ ASSERT_EQ(n1, t.left(n0)) << "n1 not left child of n0";
+ ASSERT_NE(n1, t.right(n0)) << "n1 right child of n0";
+ ASSERT_EQ(true, t.isLeft(n1)) << "n1 is a left child";
+ ASSERT_EQ(false, t.isRight(n1)) << "n1 is a right child";
+ ASSERT_EQ(n0, t.parent(n1)) << "n0 not parent of n1";
+ ASSERT_EQ(NULL, t.sibling(n1)) << "sibling(n1) wrong";
+ ASSERT_EQ(false, t.isInternal(n1)) << "n1 is external";
+ ASSERT_EQ(true, t.isExternal(n1)) << "n1 not internal now";
+ ASSERT_EQ(false, t.hasLeft(n1)) << "n1 has left child";
+ ASSERT_EQ(false, t.hasRight(n1)) << "n1 has right child";
+ ASSERT_EQ(0, t.numChildren(n1)) << "numChildren(n1) should be 0";
+ ASSERT_EQ(NULL, t.addLeft(-3, t.root())) << "root->left overwritten by addLeft()";
+
+ /////////// add root->right
+ node_t* n2 = t.addRight(2, t.root());
+ ASSERT_EQ(3, t.size()) << "size not 3";
+ ASSERT_EQ(false, t.empty()) << "tree empty";
+ // about root
+ ASSERT_EQ(n0, t.root()) << "root not n0";
+ ASSERT_EQ(n0, t.parent(n2)) << "n2 not child of n0";
+ ASSERT_EQ(true, t.hasLeft(n0)) << "root has a left child";
+ ASSERT_EQ(true, t.hasRight(n0)) << "root has no right child";
+ ASSERT_EQ(true, t.isInternal(n0)) << "root is internal";
+ ASSERT_EQ(false, t.isExternal(n0)) << "root not external now";
+ ASSERT_EQ(n2, t.right(n0)) << "right(root) should be n2";
+ ASSERT_EQ(NULL, t.parent(n0)) << "parent(root) should be NULL";
+ ASSERT_EQ(NULL, t.sibling(n0)) << "sibling(root) should be NULL";
+ ASSERT_EQ(2, t.numChildren(n0)) << "numChildren(root) should be 2";
+ // about root->left
+ ASSERT_EQ(1, n1->element) << "element not 1";
+ ASSERT_EQ(n1, t.left(n0)) << "n1 not left child of n0";
+ ASSERT_NE(n1, t.right(n0)) << "n1 right child of n0";
+ ASSERT_EQ(true, t.isLeft(n1)) << "n1 is a left child";
+ ASSERT_EQ(false, t.isRight(n1)) << "n1 is a right child";
+ ASSERT_EQ(n0, t.parent(n1)) << "n0 not parent of n1";
+ ASSERT_EQ(n2, t.sibling(n1)) << "sibling(n1) wrong";
+ ASSERT_EQ(false, t.isInternal(n1)) << "n1 is external";
+ ASSERT_EQ(true, t.isExternal(n1)) << "n1 not internal now";
+ ASSERT_EQ(false, t.hasLeft(n1)) << "n1 has left child";
+ ASSERT_EQ(false, t.hasRight(n1)) << "n1 has right child";
+ ASSERT_EQ(0, t.numChildren(n1)) << "numChildren(n1) should be 0";
+ // about root->right
+ ASSERT_EQ(2, n2->element) << "element not 2";
+ ASSERT_EQ(n2, t.right(n0)) << "n2 not right child of n0";
+ ASSERT_NE(n2, t.left(n0)) << "n2 left child of n0";
+ ASSERT_EQ(false, t.isLeft(n2)) << "n2 is a left child";
+ ASSERT_EQ(true, t.isRight(n2)) << "n2 not a right child";
+ ASSERT_EQ(n0, t.parent(n2)) << "n0 not parent of n2";
+ ASSERT_EQ(n1, t.sibling(n2)) << "sibling(n2) should be n1";
+ ASSERT_EQ(false, t.isInternal(n2)) << "n2 is external";
+ ASSERT_EQ(true, t.isExternal(n2)) << "n2 not internal now";
+ ASSERT_EQ(false, t.hasLeft(n2)) << "n2 has left child";
+ ASSERT_EQ(false, t.hasRight(n2)) << "n2 has right child";
+ ASSERT_EQ(0, t.numChildren(n2)) << "numChildren(n2) should be 0";
+ ASSERT_EQ(NULL, t.addRight(-3, t.root())) << "root->right overwritten by addRight()";
+
+ /////////// add root->left->right
+ node_t* n4 = t.addRight(4, n1);
+ ASSERT_EQ(4, t.size()) << "size not 4";
+ ASSERT_EQ(false, t.empty()) << "tree empty";
+ // about root
+ ASSERT_EQ(n0, t.root()) << "root not n0";
+ ASSERT_EQ(n0, t.parent(t.parent(n4))) << "n2 not grand child of n0";
+ ASSERT_EQ(true, t.hasLeft(n0)) << "root has a left child";
+ ASSERT_EQ(true, t.hasRight(n0)) << "root has no right child";
+ ASSERT_EQ(true, t.isInternal(n0)) << "root is internal";
+ ASSERT_EQ(false, t.isExternal(n0)) << "root not external now";
+ ASSERT_EQ(n2, t.right(n0)) << "right(root) should be n2";
+ ASSERT_EQ(n1, t.left(n0)) << "left(root) should be n1";
+ ASSERT_EQ(NULL, t.parent(n0)) << "parent(root) should be NULL";
+ ASSERT_EQ(NULL, t.sibling(n0)) << "sibling(root) should be NULL";
+ ASSERT_EQ(2, t.numChildren(n0)) << "numChildren(root) should be 1";
+ // about root->left
+ ASSERT_EQ(1, n1->element) << "element not 1";
+ ASSERT_EQ(n1, t.left(n0)) << "n1 not left child of n0";
+ ASSERT_NE(n1, t.right(n0)) << "n1 right child of n0";
+ ASSERT_EQ(true, t.isLeft(n1)) << "n1 is a left child";
+ ASSERT_EQ(false, t.isRight(n1)) << "n1 is a right child";
+ ASSERT_EQ(n0, t.parent(n1)) << "n0 not parent of n1";
+ ASSERT_EQ(n2, t.sibling(n1)) << "sibling(n1) wrong";
+ ASSERT_EQ(true, t.isInternal(n1)) << "n1 external";
+ ASSERT_EQ(false, t.isExternal(n1)) << "n1 internal now";
+ ASSERT_EQ(false, t.hasLeft(n1)) << "n1 has no left child";
+ ASSERT_EQ(true, t.hasRight(n1)) << "n1 has no right child";
+ ASSERT_EQ(1, t.numChildren(n1)) << "numChildren(n1) should be 1";
+ // about root->right
+ ASSERT_EQ(2, n2->element) << "element not 2";
+ ASSERT_EQ(n2, t.right(n0)) << "n2 not right child of n0";
+ ASSERT_NE(n2, t.left(n0)) << "n2 left child of n0";
+ ASSERT_EQ(false, t.isLeft(n2)) << "n2 is a left child";
+ ASSERT_EQ(true, t.isRight(n2)) << "n2 not a right child";
+ ASSERT_EQ(n0, t.parent(n2)) << "n0 not parent of n2";
+ ASSERT_EQ(n1, t.sibling(n2)) << "sibling(n2) should be n1";
+ ASSERT_EQ(false, t.isInternal(n2)) << "n2 is external";
+ ASSERT_EQ(true, t.isExternal(n2)) << "n2 not internal now";
+ ASSERT_EQ(false, t.hasLeft(n2)) << "n2 has left child";
+ ASSERT_EQ(false, t.hasRight(n2)) << "n2 has right child";
+ ASSERT_EQ(0, t.numChildren(n2)) << "numChildren(n2) should be 0";
+ // about root->left->right
+ ASSERT_EQ(4, n4->element) << "element not 4";
+ ASSERT_EQ(n4, t.right(n1)) << "n4 not right child of n1";
+ ASSERT_NE(n4, t.left(n1)) << "n4 left child of n1";
+ ASSERT_EQ(false, t.isLeft(n4)) << "n4 is a left child";
+ ASSERT_EQ(true, t.isRight(n4)) << "n4 not a right child";
+ ASSERT_EQ(n1, t.parent(n4)) << "n1 not parent of n4";
+ ASSERT_EQ(NULL, t.sibling(n4)) << "sibling(n4) should be NULL";
+ ASSERT_EQ(false, t.isInternal(n4)) << "n4 is external";
+ ASSERT_EQ(true, t.isExternal(n4)) << "n4 not internal now";
+ ASSERT_EQ(false, t.hasLeft(n4)) << "n4 has left child";
+ ASSERT_EQ(false, t.hasRight(n4)) << "n4 has right child";
+ ASSERT_EQ(0, t.numChildren(n4)) << "numChildren(n4) should be 0";
+ ASSERT_EQ(NULL, t.addRight(-3, t.root()->left())) << "root->left->right overwritten by addRight()";
+
+
+
+ //ASSERT_EQ(0, 1) << "test incomplete";
+
+ }
+
+
+
+ // remove
+ void removeNode(){
+ Tree t;
+ node_t* n0 = t.addRoot(0);
+ node_t* n1 = t.addLeft(1, n0);
+ node_t* n2 = t.addRight(2, n0);
+ node_t* n4 = t.addRight(4, n1);
+ // remove root->left->right
+ int e;
+ bool ok = t.removeNode(n4, e); // remove n4
+ ASSERT_EQ(true, ok) << "remove failed";
+ ASSERT_EQ(4, e) << "wrong element";
+ ASSERT_EQ(3, t.size()) << "size not 3";
+ ASSERT_EQ(NULL, n1->left()) << "n1->left not NULL";
+ ASSERT_EQ(0, t.numChildren(n1)) << "n1 has children";
+ ASSERT_EQ(false, t.isInternal(n1)) << "n1 still internal";
+ ASSERT_EQ(true, t.isExternal(n1)) << "n1 not external";
+
+ // now delete n2
+ ok = t.removeNode(n2, e); // remove n4
+ ASSERT_EQ(true, ok) << "remove failed";
+ ASSERT_EQ(2, e) << "wrong element";
+ ASSERT_EQ(2, t.size()) << "size not 2";
+ ASSERT_EQ(NULL, n0->right()) << "n0->right not NULL";
+ ASSERT_EQ(n1, n0->left()) << "n0->left not n1";
+ ASSERT_EQ(false, t.hasRight(t.root())) << "root still has right";
+ ASSERT_EQ(true, t.hasLeft(t.root())) << "root has no left";
+ ASSERT_EQ(1, t.numChildren(t.root())) << "n1->left not NULL";
+ ASSERT_EQ(NULL, t.sibling(n1)) << "n1 still has sibling";
+
+ // try to remove an internal node (should not work)
+ // add n4 back at root->left->right
+ n4 = t.addRight(4, t.root()->left());
+ ASSERT_EQ(true, t.isInternal(n1)) << "n1 still external";
+ ASSERT_EQ(3, t.size()) << "size not 3";
+ ok = t.removeNode(n1, e); // attempt removing n1
+ ASSERT_EQ(false, ok) << "removeNode() deleted internal node";
+
+ // try to delete root
+ ok = t.removeNode(t.root(), e); // remove n1
+ ASSERT_EQ(false, ok) << "removeNode() deleted root";
+
+
+ }
+
+ void remove(){
+ Tree t;
+ int e;
+ node_t* n0 = t.addRoot(0);
+ node_t* n1 = t.addLeft(1, n0);
+ node_t* n2 = t.addRight(2, n0);
+ node_t* n3 = t.addLeft(3, n1);
+ node_t* n4 = t.addRight(4, n1);
+
+ ///////////////// try deleting subtree at internal node
+ ASSERT_EQ(5, t.size()) << "size not 4";
+
+ bool ok = t.remove(n1, e); // remove subtree at n1
+ ASSERT_EQ(true, ok) << "remove failed";
+ ASSERT_EQ(2, t.size()) << "size not 2";
+ ASSERT_EQ(1, e) << "wrong element removed";
+ ASSERT_EQ(false, t.hasLeft(t.root())) << "root still has left";
+ ASSERT_EQ(1, t.numChildren(t.root())) << "root does not have 1 child";
+
+ // try removing external node
+ ok = t.remove(n2, e); // remove subtree at n2 (single node)
+ ASSERT_EQ(true, ok) << "remove failed";
+ ASSERT_EQ(1, t.size()) << "size not 2";
+ ASSERT_EQ(2, e) << "wrong element removed";
+ ASSERT_EQ(false, t.isInternal(t.root())) << "root still internal";
+ ASSERT_EQ(0, t.numChildren(t.root())) << "root does not have any child";
+
+ // try deleting the entire tree
+ n1 = t.addLeft(1, t.root());
+ n2 = t.addRight(2, t.root());
+ n3 = t.addLeft(3, n1);
+ n4 = t.addRight(4, n1);
+ node_t* n5 = t.addLeft(5, n2);
+
+ ok = t.remove(t.root(), e); // remove subtree at root (whole tree)
+ ASSERT_EQ(true, ok) << "remove failed";
+ ASSERT_EQ(0, t.size()) << "size not 0";
+ ASSERT_EQ(true, t.empty()) << "tree not empty";
+ ASSERT_EQ(0, e) << "wrong element removed";
+ ASSERT_EQ(NULL, t.root()) << "root not NULL";
+
+ }
+
+ void clear(){
+ node_t *n0, *n1, *n2, *n3, *n4;
+ Tree t;
+ //////// clear
+ t.clear(); // should have no effect
+
+ n0 = t.addRoot(0);
+ n1 = t.addLeft(1, t.root());
+ n2 = t.addRight(2, t.root());
+ n3 = t.addLeft(3, n1);
+ n4 = t.addRight(4, n1);
+
+ ASSERT_EQ(4, t.size()) << "size not 4";
+ ASSERT_EQ(false, t.empty()) << "tree empty";
+ ASSERT_NE(NULL, (int)t.root()) << "root NULL";
+
+ t.clear();
+
+ ASSERT_EQ(0, t.size()) << "size not 0";
+ ASSERT_EQ(true, t.empty()) << "tree not empty";
+ ASSERT_EQ(NULL, (int)t.root()) << "root not NULL";
+
+ }
+
+ void toString(){
+ Tree t;
+ node_t* n0 = t.addRoot(0);
+
+ node_t* n1 = t.addLeft(1, n0);
+ node_t* n2 = t.addRight(2, n0);
+
+ node_t* n3 = t.addLeft(3, n1);
+ // no 4
+ node_t* n5 = t.addLeft(5, n2);
+ node_t* n6 = t.addRight(6, n2);
+ // no 7
+ node_t* n8 = t.addRight(8, n3);
+ /*
+ 0
+ 1 2
+ 3 - 5 6
+ - 8
+
+ */
+
+ const string preorderTrimmed = "0138256"; // preorder, without space
+ string str = t.toString(); // result, with space
+ // remove space
+ string actualTrimmed = strPurge(str, "| "); // purge | and space
+ ASSERT_EQ(actualTrimmed, preorderTrimmed) << "toString() mismatch";
+
+ string strBt, strExpected;
+ /////////// preorder
+ strBt = t.toStringPreOrder();
+ strBt = strPurge(strBt, "| ");
+ strExpected = "0138256";
+ ASSERT_EQ(strExpected, strBt) << "preorder mismatch";
+
+ /////////// postorder
+ strBt = t.toStringPostOrder();
+ strBt = strPurge(strBt, "| ");
+ strExpected = "8315620";
+ ASSERT_EQ(strExpected, strBt) << "postorder mismatch";
+
+ /////////// inorder
+ strBt = t.toStringInOrder();
+ strBt = strPurge(strBt, "| ");
+ strExpected = "3810526";
+ ASSERT_EQ(strExpected, strBt) << "inorder mismatch";
+
+
+ /////////// BFSorder
+ strBt = t.toStringBFS();
+ strBt = strPurge(strBt, "| ");
+ strExpected = "0123568";
+ ASSERT_EQ(strExpected, strBt) << "BFS order mismatch";
+ }
+
+ };
+ ADD_TEST_F(BinaryTreeTest, add);
+ ADD_TEST_F(BinaryTreeTest, removeNode);
+ ADD_TEST_F(BinaryTreeTest, remove);
+ ADD_TEST_F(BinaryTreeTest, toString);
+ }
+}
\ No newline at end of file
diff --git a/YASI_12/ds.binarytreebase.h b/YASI_12/ds.binarytreebase.h
index 0e47c10..a3f1629 100644
--- a/YASI_12/ds.binarytreebase.h
+++ b/YASI_12/ds.binarytreebase.h
@@ -1,5 +1,6 @@
#pragma once
#include "common.h"
+#include "ds.tree.h"
#include "ds.doublylinkedlist.h"
#include
using namespace std;
diff --git a/YASI_12/main.cpp b/YASI_12/main.cpp
index 14941fc..ac4a420 100644
--- a/YASI_12/main.cpp
+++ b/YASI_12/main.cpp
@@ -1,7 +1,5 @@
#include "common.h"
-//#include "utils.h"
-//#include "ds.singlylinkedlist.h"
-//#include "ds.doublylinkedlist.h"
+
//#include "ds.arraybinarytree.h"
//#include "ds.binaryheap.h"
//#include "ds.binarytree.h"
@@ -31,6 +29,8 @@ using namespace std;
#include "ds.iterator.test.h"
#include "ds.singlylinkedlist.test.h"
#include "ds.doublylinkedlist.test.h"
+#include "ds.binarytree.test.h"
+#include "ds.arraybinarytree.test.h"
int testAll(int* argc, char** argv){