diff --git a/YASI_12/YASI_12.vcxproj b/YASI_12/YASI_12.vcxproj
index 81a27c4..a47d2e8 100644
--- a/YASI_12/YASI_12.vcxproj
+++ b/YASI_12/YASI_12.vcxproj
@@ -79,6 +79,7 @@
+
@@ -99,8 +100,13 @@
+
+
+
+
+
diff --git a/YASI_12/YASI_12.vcxproj.filters b/YASI_12/YASI_12.vcxproj.filters
index ad4aa77..4fa2405 100644
--- a/YASI_12/YASI_12.vcxproj.filters
+++ b/YASI_12/YASI_12.vcxproj.filters
@@ -155,10 +155,28 @@
Header Files\Data Structures\List
+
+ Header Files\Data Structures\Tree
+
+ Header Files\Data Structures\Tree
+
+
+ Header Files\Data Structures\Heap
+
+
+ Header Files\Data Structures\Heap
+
+
+ Header Files\Data Structures\Heap
+
+
Header Files
-
+
+ Header Files
+
+
Header Files
diff --git a/YASI_12/ds.binaryheap.h b/YASI_12/ds.binaryheap.h
index 880f29b..1453180 100644
--- a/YASI_12/ds.binaryheap.h
+++ b/YASI_12/ds.binaryheap.h
@@ -7,10 +7,12 @@
#include "ds.aux.hastree.h"
#include "ds.kvpair.h"
+using namespace std;
-namespace yasi{
+// enable-disable testing classes in this file
+#include "test.this.module.h"
-using namespace std;
+namespace yasi{
namespace ds{
@@ -68,7 +70,7 @@ class BinaryHeapBase : public IBinaryHeap >,
//
template >
class BinaryHeap : public BinaryHeapBase{
- friend class BinaryHeapTest;
+ FRIEND_TEST_CLASS( BinaryHeapTest);
public:
// public typedef
typedef ArrayBinaryTree Tree;
@@ -344,490 +346,6 @@ class BinaryHeap : public BinaryHeapBase{
};
-// test the BinaryHeap class
-class BinaryHeapTest : public yasi::Test{
-protected:
- typedef BinaryHeap::node_t node_t;
-
-public:
-
- template >
- void checkHeapElements(HeapType* pHeap, const E* pElemsArr, const int numElems){
- return ArrayBinaryTreeTest::checkElements(&pHeap->bt, pElemsArr, numElems);
- }
-
- void heapify(){
- const int heapSize = 5;
- int arr[] = { 10, 5, 20, 15, 25 };
- int n = ARR_LENGTH(arr);
- BinaryHeap h;
- bool ok = h.heapify(arr, n);
- ASSERT_EQ(true, ok) << "heapify failed";
-
- // assuming min-heap
- {
- SCOPED_TRACE("heapify #1");
- int newArr[] = { 5, 10, 20, 15, 25 };
- checkHeapElements(&h, newArr, heapSize);
- }
-
- ok = h.heapify(arr, -1);
- ASSERT_EQ(false, ok) << "heapify succeeded with negative size";
-
- ok = h.heapify(NULL, 4);
- ASSERT_EQ(false, ok) << "heapify succeeded with NULL array";
-
- }
-
- void top(){
- int e;
- bool ok = true;
- BinaryHeap h;
-
- h.insert(15);
- h.insert(5);
- h.insert(25);
- h.insert(10);
- h.insert(20);
-
- // assuming min-heap
- ASSERT_EQ(5, h.size()) << "heap size should have been 5";
- e = h.top();
- ASSERT_EQ(5, e) << "top should have been 5";
- e = h.top();
- ASSERT_EQ(5, e) << "top should still have been 5";
- h.pop(); // pop 5
- e = h.top();
- ASSERT_EQ(10, e) << "top should still have been 10";
- h.pop(); // pop 10
- e = h.top();
- ASSERT_EQ(15, e) << "top should have been 15";
- h.pop(); // pop 15
- e = h.top();
- ASSERT_EQ(20, e) << "top should have been 20";
- h.pop(); // pop 20
- e = h.top();
- ASSERT_EQ(25, e) << "top should have been 25";
- h.pop(); // pop 25
- ASSERT_EQ(0, h.size()) << "heap size should have been 0";
-
-
- }
-
- void bubbleUp(){
- const int heapSize = 6;
- int arr[] = { 5, 10, 15, 2, 30, 7 }; // 2 (child of 10) and 7 (child of 15), violate heap property
- int n = ARR_LENGTH(arr);
- BinaryHeap h;
- h.setTree(arr, n);
- // now the binary tree has heap-property violations
-
- node_t* pNode = h.bt.nodeAt(4); // 2
- h.bubbleUp(pNode);
- // arr = {2, 5, 15, 10, 30, 7}
- {
- SCOPED_TRACE("bubbleUp(2)");
- int newArr[] = { 2, 5, 15, 10, 30, 7 };
- checkHeapElements(&h, newArr, heapSize);
- }
-
- pNode = h.bt.nodeAt(6); // 7
- h.bubbleUp(pNode); // 7 should stop as a child of 2
- // arr = {2, 5, 7, 10, 30, 15}
- {
- SCOPED_TRACE("bubbleUp(7)");
- int newArr[] = { 2, 5, 7, 10, 30, 15 };
- checkHeapElements(&h, newArr, heapSize);
- }
- }
-
- void selectChildForBubbleDown(){
- BinaryHeap h;
- // case: bubbleDown along right child
- int arr[] = { 10, 20, 30 }; // 35 (parent of 100 and 15) and 15 (parent of 7) violate heap property
- h.setTree(arr, 3);
- node_t* pNode = h.selectChildForBubbleDown(h.bt.root()); // should be NULL
- ASSERT_EQ(0, (int)pNode) << "should not bubble down";
-
- h.clear();
- int arr2[] = { 10, 5, 8 };
- h.setTree(arr2, 3);
- pNode = h.selectChildForBubbleDown(h.bt.root()); // should be 5
- ASSERT_EQ(5, pNode->element) << "should be 5";
-
- h.clear();
- int arr3[] = { 10, 15, 8 };
- h.setTree(arr3, 3);
- pNode = h.selectChildForBubbleDown(h.bt.root()); // should be 8
- ASSERT_EQ(8, pNode->element) << "should be 8";
-
- h.clear();
- int arr4[] = { 5, 10, 10 };
- h.setTree(arr4, 3);
- pNode = h.selectChildForBubbleDown(h.bt.root()); // should be right child of root
- ASSERT_EQ(0, (int) pNode) << "should not bubble down";
-
- h.clear();
- int arr5[] = { 10, 10, 10 };
- h.setTree(arr5, 3);
- pNode = h.selectChildForBubbleDown(h.bt.root()); // should not bubble down
- ASSERT_EQ(0, (int) pNode) << "should not bubble down when all equal";
- }
-
- void bubbleDown(){
- const int heapSize = 6;
- // case: bubbleDown along right child
- int arr[] = { 35, 100, 15, 50, 30, 7 }; // 35 (parent of 100 and 15) and 15 (parent of 7) violate heap property
- int n = ARR_LENGTH(arr);
- BinaryHeap h;
- h.setTree(arr, n);
- // now the binary tree has heap-property violations
-
- node_t* pNode = h.bt.root(); // 35
- h.bubbleDown(pNode);
- // arr={15, 100, 7, 50, 30, 35}
- {
- SCOPED_TRACE("bubbleDown(35)");
- int newArr[] = { 15, 100, 7, 50, 30, 35 };
- checkHeapElements(&h, newArr, heapSize);
- }
-
- h.bubbleDown(h.bt.root()); // 15
- // arr={7, 100, 15, 50, 30, 35}
- {
- SCOPED_TRACE("bubbleDown(15)");
- int newArr[] = { 7, 100, 15, 50, 30, 35 };
- checkHeapElements(&h, newArr, heapSize);
- }
-
- h.bubbleDown(h.bt.nodeAt(4)); // no effect: external
- // arr={7, 100, 15, 50, 30, 35}
- {
- SCOPED_TRACE("bubbleDown(50)");
- int newArr[] = { 7, 100, 15, 50, 30, 35 };
- checkHeapElements(&h, newArr, heapSize);
- }
-
- // case: bubbleDown along left child
- int arr2[] = { 35, 15, 100, 50, 30, 7 }; // 35 (parent of 100 and 15) and 100 (parent of 7) violate heap property
- n = ARR_LENGTH(arr2);
- BinaryHeap h2;
- h2.setTree(arr2, n);
- // now the binary tree has heap-property violations
-
- pNode = h2.bt.root(); // 35
- h2.bubbleDown(pNode);
- // arr={15, 30, 100, 50, 35, 7}
- {
- SCOPED_TRACE("bubbleDown(35)");
- int newArr[] = { 15, 30, 100, 50, 35, 7 };
- checkHeapElements(&h2, newArr, heapSize);
- }
- }
-
- void insert(){
- BinaryHeap h;
-
- // root
- h.insert(5);
- // arr={5}
- {
- SCOPED_TRACE("insert(5)");
- int newArr[] = { 5 };
- checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
- }
-
- // add a large element, should not bubble up
- h.insert(10);
- // arr={5, 10}
- {
- SCOPED_TRACE("insert(10)");
- int newArr[] = { 5, 10 };
- checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
- }
-
- // add a small element, should bubble up
- h.insert(3);
- // arr = {3, 10, 5}
- {
- SCOPED_TRACE("insert(3)");
- int newArr[] = { 3, 10, 5 };
- checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
- }
-
- // add another small element, should bubble up
- h.insert(1);
- // arr = {1, 3, 5, 10}
- {
- SCOPED_TRACE("insert(1)");
- int newArr[] = { 1, 3, 5, 10 };
- checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
- }
-
- h.insert(2);
- // arr = {1, 2, 5, 10, 3}
- {
- SCOPED_TRACE("insert(2)");
- int newArr[] = { 1, 2, 5, 10, 3 };
- checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
- }
-
- }
-
- void pop(){
- const int heapSize = 6;
- int arr[] = { 5, 10, 15, 20, 25, 30 }; // valid heap
- int n = ARR_LENGTH(arr);
- BinaryHeap h;
- h.setTree(arr, n); // valid heap
- int e;
-
- e = h.top(); // e = 5
- h.pop();
- ASSERT_EQ(5, e) << "top elem should be 5";
- // arr={10, 20, 15, 30, 25}
- {
- SCOPED_TRACE("pop #1");
- int newArr[] = { 10, 20, 15, 30, 25 };
- checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
- }
-
- e = h.top(); // e = 10
- h.pop();
- ASSERT_EQ(10, e) << "top elem should be 10";
- // arr={15, 20, 25, 30}
- {
- SCOPED_TRACE("pop #2");
- int newArr[] = { 15, 20, 25, 30 };
- checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
- }
-
- e = h.top(); // e = 15
- h.pop();
- ASSERT_EQ(15, e) << "top elem should be 15";
- // arr={20, 30, 25}
- {
- SCOPED_TRACE("pop #3");
- int newArr[] = { 20, 30, 25 };
- checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
- }
-
- e = h.top(); // e = 20
- h.pop();
- ASSERT_EQ(20, e) << "top elem should be 20";
- // arr={25, 30}
- {
- SCOPED_TRACE("pop #4");
- int newArr[] = { 25, 30 };
- checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
- }
-
- e = h.top(); // e = 25
- h.pop();
- ASSERT_EQ(25, e) << "top elem should be 25";
- // arr={30}
- {
- SCOPED_TRACE("pop #5");
- int newArr[] = { 30 };
- checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
- }
-
- e = h.top(); // e = 30
- h.pop();
- ASSERT_EQ(30, e) << "top elem should be 30";
- // arr={}
- ASSERT_EQ(true, h.empty()) << "heap should have been empty";
-
- }
-
- void maxHeap(){
- const int heapSize = 5;
- int arr[] = { 10, 5, 20, 15, 25 };
- int n = ARR_LENGTH(arr);
- typedef BinaryHeap > HeapType;
- HeapType h;
- bool ok = h.heapify(arr, n);
- ASSERT_EQ(true, ok) << "heapify failed";
-
- // should be max-heap
- {
- /* heap:
- 25
- 20 10
- 5 15
- */
- SCOPED_TRACE("max-heap #1");
- //int newArr[] = { 25, 20, 10, 5, 15 };
- //checkHeapElements(&h, newArr, heapSize);
- string actual = strPurge(h.toStringBFS(), "| ");
- ASSERT_EQ("252010515", actual) << "bad max heap from heapify";
- }
-
- // add some more items
- {
- h.push(12);
- h.push(30);
- h.push(3);
- h.push(40);
- /* heap:
- 40
- 30 25
- 20 15 10 12
- 3 5
- */
- SCOPED_TRACE("max-heap #2");
- string actual = strPurge(h.toStringBFS(), "| ");
- ASSERT_EQ("4030252015101235", actual) << "bad max heap after add";
- }
-
-
- }
-
- // compare a heap made of numeric strings,
- // and the comparison will be done after turning them into numbers
- // creates a max heap with predicate NumericStringMaxHeapPredicate
- void customComparatorHeap(){
- const int heapSize = 5;
- typedef string HeapElement;
- HeapElement srcArr[] = {
- HeapElement("10"),
- HeapElement("5"),
- HeapElement("20"),
- HeapElement("15"),
- HeapElement("25")
- };
- int n = ARR_LENGTH(srcArr);
- // max heap with binary trees as elements
- typedef BinaryHeap HeapType;
- HeapType h;
- bool ok = h.heapify(srcArr, n);
- ASSERT_EQ(true, ok) << "heapify failed";
- // should be max-heap
- {
- /* heap:
- 25
- 20 10
- 5 15
- */
- SCOPED_TRACE("max-heap #1");
- string actual = strPurge(h.toStringBFS(), "| ");
- ASSERT_EQ("252010515", actual) << "bad max heap from heapify";
- }
-
- // add some more items
- {
- h.push("12");
- h.push("30");
- h.push("3");
- h.push("40");
- /* heap:
- 40
- 30 25
- 20 15 10 12
- 3 5
- */
- SCOPED_TRACE("max-heap #2");
- string actual = strPurge(h.toStringBFS(), "| ");
- ASSERT_EQ("4030252015101235", actual) << "bad max heap after add";
- }
-
-
- }
-
-};
-
-
-
-ADD_TEST_F(BinaryHeapTest, heapify);
-ADD_TEST_F(BinaryHeapTest, top);
-ADD_TEST_F(BinaryHeapTest, pop);
-ADD_TEST_F(BinaryHeapTest, insert);
-ADD_TEST_F(BinaryHeapTest, bubbleUp);
-ADD_TEST_F(BinaryHeapTest, selectChildForBubbleDown);
-ADD_TEST_F(BinaryHeapTest, bubbleDown);
-ADD_TEST_F(BinaryHeapTest, maxHeap);
-ADD_TEST_F(BinaryHeapTest, customComparatorHeap);
-
-
-//////////////////////////////////////////////
-//////////////// Mutable Heap ////////////////
-//////////////////////////////////////////////
-template
-class MutableHeap : public BinaryHeap < KVPair > {
- ////////// enable testing ///////////
- friend class MutableHeapTest;
- typedef KVPair HeapElement;
- typedef BinaryHeap Heap;
- typedef typename Heap::HeapNode Node;
-
-public:
- virtual ~MutableHeap(){}
- MutableHeap(){}
- MutableHeap(const HeapElement* pArr, const int numElems) : Heap(pArr, numElems){}
- void updateKey(Node* pNode, const Key newKey){
- if (pNode){
- HeapElement newElem(newKey);
- if (pNode->element != newElem){
- // need update
- if (newElem < pNode->element){
- // need bubble-up
- ((HeapElement*)& pNode->element)->key = newKey; // updated
- bubbleUp(pNode);
- }
- else{
- // need bubble-down
- ((HeapElement*)& pNode->element)->key = newKey; // updated
- bubbleDown(pNode);
- }
- }
- }
- }
-};
-
-class MutableHeapTest : public yasi::Test{
- typedef KVPair Pair;
- typedef MutableHeap MHeap;
-public:
- void updateKey(){
- MHeap h;
- MHeap::HeapNode* n[5];
- for (int i = 0; i < 5; i++){
- n[i] = h.insert(Pair(i)); // both key and value are i
- }
-
- string str = h.toStringBFS(); // should be 0 1 2 3 4
- string strBefore = strPurge(str, "| ");
- string expectedStrBefore = "01234";
- ASSERT_EQ(expectedStrBefore, strBefore) << "heap toString() mismatch";
-
- // now update key 3 to 9
- h.updateKey(n[3], 9);
- // heap: 0 1 2 9 4
- str = h.toStringBFS();
- string strAfter = strPurge(str, "| ");
- string expectedStrAfter = "01294";
- ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 3-->9";
-
- // now update key 2 to -8
- h.updateKey(n[2], -8);
- // heap: -8 1 0 9 4
- str = h.toStringBFS();
- strAfter = strPurge(str, "| ");
- expectedStrAfter = "-81094";
- ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 2-->-8";
-
- // now update key 9 to -9
- h.updateKey(n[3], -9);
- // heap: -9 -8 0 1 4
- str = h.toStringBFS();
- strAfter = strPurge(str, "| ");
- expectedStrAfter = "-9-8014";
- ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 9-->-9";
-
- }
-};
-
-ADD_TEST_F(MutableHeapTest, updateKey);
} // namespace yasi.ds
diff --git a/YASI_12/ds.binaryheap.test.h b/YASI_12/ds.binaryheap.test.h
new file mode 100644
index 0000000..c198b59
--- /dev/null
+++ b/YASI_12/ds.binaryheap.test.h
@@ -0,0 +1,418 @@
+#pragma once
+
+#if YASI_TEST_THIS_MODULE != 1
+#define YASI_TEST_THIS_MODULE 1
+#endif
+#include "ds.binaryheap.h"
+
+namespace yasi{
+ namespace ds{
+
+ // test the BinaryHeap class
+ class BinaryHeapTest : public yasi::Test{
+ protected:
+ typedef BinaryHeap::node_t node_t;
+
+ public:
+
+ template >
+ void checkHeapElements(HeapType* pHeap, const E* pElemsArr, const int numElems){
+ return ArrayBinaryTreeTest::checkElements(&pHeap->bt, pElemsArr, numElems);
+ }
+
+ void heapify(){
+ const int heapSize = 5;
+ int arr[] = { 10, 5, 20, 15, 25 };
+ int n = ARR_LENGTH(arr);
+ BinaryHeap h;
+ bool ok = h.heapify(arr, n);
+ ASSERT_EQ(true, ok) << "heapify failed";
+
+ // assuming min-heap
+ {
+ SCOPED_TRACE("heapify #1");
+ int newArr[] = { 5, 10, 20, 15, 25 };
+ checkHeapElements(&h, newArr, heapSize);
+ }
+
+ ok = h.heapify(arr, -1);
+ ASSERT_EQ(false, ok) << "heapify succeeded with negative size";
+
+ ok = h.heapify(NULL, 4);
+ ASSERT_EQ(false, ok) << "heapify succeeded with NULL array";
+
+ }
+
+ void top(){
+ int e;
+ bool ok = true;
+ BinaryHeap h;
+
+ h.insert(15);
+ h.insert(5);
+ h.insert(25);
+ h.insert(10);
+ h.insert(20);
+
+ // assuming min-heap
+ ASSERT_EQ(5, h.size()) << "heap size should have been 5";
+ e = h.top();
+ ASSERT_EQ(5, e) << "top should have been 5";
+ e = h.top();
+ ASSERT_EQ(5, e) << "top should still have been 5";
+ h.pop(); // pop 5
+ e = h.top();
+ ASSERT_EQ(10, e) << "top should still have been 10";
+ h.pop(); // pop 10
+ e = h.top();
+ ASSERT_EQ(15, e) << "top should have been 15";
+ h.pop(); // pop 15
+ e = h.top();
+ ASSERT_EQ(20, e) << "top should have been 20";
+ h.pop(); // pop 20
+ e = h.top();
+ ASSERT_EQ(25, e) << "top should have been 25";
+ h.pop(); // pop 25
+ ASSERT_EQ(0, h.size()) << "heap size should have been 0";
+
+
+ }
+
+ void bubbleUp(){
+ const int heapSize = 6;
+ int arr[] = { 5, 10, 15, 2, 30, 7 }; // 2 (child of 10) and 7 (child of 15), violate heap property
+ int n = ARR_LENGTH(arr);
+ BinaryHeap h;
+ h.setTree(arr, n);
+ // now the binary tree has heap-property violations
+
+ node_t* pNode = h.bt.nodeAt(4); // 2
+ h.bubbleUp(pNode);
+ // arr = {2, 5, 15, 10, 30, 7}
+ {
+ SCOPED_TRACE("bubbleUp(2)");
+ int newArr[] = { 2, 5, 15, 10, 30, 7 };
+ checkHeapElements(&h, newArr, heapSize);
+ }
+
+ pNode = h.bt.nodeAt(6); // 7
+ h.bubbleUp(pNode); // 7 should stop as a child of 2
+ // arr = {2, 5, 7, 10, 30, 15}
+ {
+ SCOPED_TRACE("bubbleUp(7)");
+ int newArr[] = { 2, 5, 7, 10, 30, 15 };
+ checkHeapElements(&h, newArr, heapSize);
+ }
+ }
+
+ void selectChildForBubbleDown(){
+ BinaryHeap h;
+ // case: bubbleDown along right child
+ int arr[] = { 10, 20, 30 }; // 35 (parent of 100 and 15) and 15 (parent of 7) violate heap property
+ h.setTree(arr, 3);
+ node_t* pNode = h.selectChildForBubbleDown(h.bt.root()); // should be NULL
+ ASSERT_EQ(0, (int)pNode) << "should not bubble down";
+
+ h.clear();
+ int arr2[] = { 10, 5, 8 };
+ h.setTree(arr2, 3);
+ pNode = h.selectChildForBubbleDown(h.bt.root()); // should be 5
+ ASSERT_EQ(5, pNode->element) << "should be 5";
+
+ h.clear();
+ int arr3[] = { 10, 15, 8 };
+ h.setTree(arr3, 3);
+ pNode = h.selectChildForBubbleDown(h.bt.root()); // should be 8
+ ASSERT_EQ(8, pNode->element) << "should be 8";
+
+ h.clear();
+ int arr4[] = { 5, 10, 10 };
+ h.setTree(arr4, 3);
+ pNode = h.selectChildForBubbleDown(h.bt.root()); // should be right child of root
+ ASSERT_EQ(0, (int)pNode) << "should not bubble down";
+
+ h.clear();
+ int arr5[] = { 10, 10, 10 };
+ h.setTree(arr5, 3);
+ pNode = h.selectChildForBubbleDown(h.bt.root()); // should not bubble down
+ ASSERT_EQ(0, (int)pNode) << "should not bubble down when all equal";
+ }
+
+ void bubbleDown(){
+ const int heapSize = 6;
+ // case: bubbleDown along right child
+ int arr[] = { 35, 100, 15, 50, 30, 7 }; // 35 (parent of 100 and 15) and 15 (parent of 7) violate heap property
+ int n = ARR_LENGTH(arr);
+ BinaryHeap h;
+ h.setTree(arr, n);
+ // now the binary tree has heap-property violations
+
+ node_t* pNode = h.bt.root(); // 35
+ h.bubbleDown(pNode);
+ // arr={15, 100, 7, 50, 30, 35}
+ {
+ SCOPED_TRACE("bubbleDown(35)");
+ int newArr[] = { 15, 100, 7, 50, 30, 35 };
+ checkHeapElements(&h, newArr, heapSize);
+ }
+
+ h.bubbleDown(h.bt.root()); // 15
+ // arr={7, 100, 15, 50, 30, 35}
+ {
+ SCOPED_TRACE("bubbleDown(15)");
+ int newArr[] = { 7, 100, 15, 50, 30, 35 };
+ checkHeapElements(&h, newArr, heapSize);
+ }
+
+ h.bubbleDown(h.bt.nodeAt(4)); // no effect: external
+ // arr={7, 100, 15, 50, 30, 35}
+ {
+ SCOPED_TRACE("bubbleDown(50)");
+ int newArr[] = { 7, 100, 15, 50, 30, 35 };
+ checkHeapElements(&h, newArr, heapSize);
+ }
+
+ // case: bubbleDown along left child
+ int arr2[] = { 35, 15, 100, 50, 30, 7 }; // 35 (parent of 100 and 15) and 100 (parent of 7) violate heap property
+ n = ARR_LENGTH(arr2);
+ BinaryHeap h2;
+ h2.setTree(arr2, n);
+ // now the binary tree has heap-property violations
+
+ pNode = h2.bt.root(); // 35
+ h2.bubbleDown(pNode);
+ // arr={15, 30, 100, 50, 35, 7}
+ {
+ SCOPED_TRACE("bubbleDown(35)");
+ int newArr[] = { 15, 30, 100, 50, 35, 7 };
+ checkHeapElements(&h2, newArr, heapSize);
+ }
+ }
+
+ void insert(){
+ BinaryHeap h;
+
+ // root
+ h.insert(5);
+ // arr={5}
+ {
+ SCOPED_TRACE("insert(5)");
+ int newArr[] = { 5 };
+ checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
+ }
+
+ // add a large element, should not bubble up
+ h.insert(10);
+ // arr={5, 10}
+ {
+ SCOPED_TRACE("insert(10)");
+ int newArr[] = { 5, 10 };
+ checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
+ }
+
+ // add a small element, should bubble up
+ h.insert(3);
+ // arr = {3, 10, 5}
+ {
+ SCOPED_TRACE("insert(3)");
+ int newArr[] = { 3, 10, 5 };
+ checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
+ }
+
+ // add another small element, should bubble up
+ h.insert(1);
+ // arr = {1, 3, 5, 10}
+ {
+ SCOPED_TRACE("insert(1)");
+ int newArr[] = { 1, 3, 5, 10 };
+ checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
+ }
+
+ h.insert(2);
+ // arr = {1, 2, 5, 10, 3}
+ {
+ SCOPED_TRACE("insert(2)");
+ int newArr[] = { 1, 2, 5, 10, 3 };
+ checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
+ }
+
+ }
+
+ void pop(){
+ const int heapSize = 6;
+ int arr[] = { 5, 10, 15, 20, 25, 30 }; // valid heap
+ int n = ARR_LENGTH(arr);
+ BinaryHeap h;
+ h.setTree(arr, n); // valid heap
+ int e;
+
+ e = h.top(); // e = 5
+ h.pop();
+ ASSERT_EQ(5, e) << "top elem should be 5";
+ // arr={10, 20, 15, 30, 25}
+ {
+ SCOPED_TRACE("pop #1");
+ int newArr[] = { 10, 20, 15, 30, 25 };
+ checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
+ }
+
+ e = h.top(); // e = 10
+ h.pop();
+ ASSERT_EQ(10, e) << "top elem should be 10";
+ // arr={15, 20, 25, 30}
+ {
+ SCOPED_TRACE("pop #2");
+ int newArr[] = { 15, 20, 25, 30 };
+ checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
+ }
+
+ e = h.top(); // e = 15
+ h.pop();
+ ASSERT_EQ(15, e) << "top elem should be 15";
+ // arr={20, 30, 25}
+ {
+ SCOPED_TRACE("pop #3");
+ int newArr[] = { 20, 30, 25 };
+ checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
+ }
+
+ e = h.top(); // e = 20
+ h.pop();
+ ASSERT_EQ(20, e) << "top elem should be 20";
+ // arr={25, 30}
+ {
+ SCOPED_TRACE("pop #4");
+ int newArr[] = { 25, 30 };
+ checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
+ }
+
+ e = h.top(); // e = 25
+ h.pop();
+ ASSERT_EQ(25, e) << "top elem should be 25";
+ // arr={30}
+ {
+ SCOPED_TRACE("pop #5");
+ int newArr[] = { 30 };
+ checkHeapElements(&h, newArr, ARR_LENGTH(newArr));
+ }
+
+ e = h.top(); // e = 30
+ h.pop();
+ ASSERT_EQ(30, e) << "top elem should be 30";
+ // arr={}
+ ASSERT_EQ(true, h.empty()) << "heap should have been empty";
+
+ }
+
+ void maxHeap(){
+ const int heapSize = 5;
+ int arr[] = { 10, 5, 20, 15, 25 };
+ int n = ARR_LENGTH(arr);
+ typedef BinaryHeap > HeapType;
+ HeapType h;
+ bool ok = h.heapify(arr, n);
+ ASSERT_EQ(true, ok) << "heapify failed";
+
+ // should be max-heap
+ {
+ /* heap:
+ 25
+ 20 10
+ 5 15
+ */
+ SCOPED_TRACE("max-heap #1");
+ //int newArr[] = { 25, 20, 10, 5, 15 };
+ //checkHeapElements(&h, newArr, heapSize);
+ string actual = strPurge(h.toStringBFS(), "| ");
+ ASSERT_EQ("252010515", actual) << "bad max heap from heapify";
+ }
+
+ // add some more items
+ {
+ h.push(12);
+ h.push(30);
+ h.push(3);
+ h.push(40);
+ /* heap:
+ 40
+ 30 25
+ 20 15 10 12
+ 3 5
+ */
+ SCOPED_TRACE("max-heap #2");
+ string actual = strPurge(h.toStringBFS(), "| ");
+ ASSERT_EQ("4030252015101235", actual) << "bad max heap after add";
+ }
+
+
+ }
+
+ // compare a heap made of numeric strings,
+ // and the comparison will be done after turning them into numbers
+ // creates a max heap with predicate NumericStringMaxHeapPredicate
+ void customComparatorHeap(){
+ const int heapSize = 5;
+ typedef string HeapElement;
+ HeapElement srcArr[] = {
+ HeapElement("10"),
+ HeapElement("5"),
+ HeapElement("20"),
+ HeapElement("15"),
+ HeapElement("25")
+ };
+ int n = ARR_LENGTH(srcArr);
+ // max heap with binary trees as elements
+ typedef BinaryHeap HeapType;
+ HeapType h;
+ bool ok = h.heapify(srcArr, n);
+ ASSERT_EQ(true, ok) << "heapify failed";
+ // should be max-heap
+ {
+ /* heap:
+ 25
+ 20 10
+ 5 15
+ */
+ SCOPED_TRACE("max-heap #1");
+ string actual = strPurge(h.toStringBFS(), "| ");
+ ASSERT_EQ("252010515", actual) << "bad max heap from heapify";
+ }
+
+ // add some more items
+ {
+ h.push("12");
+ h.push("30");
+ h.push("3");
+ h.push("40");
+ /* heap:
+ 40
+ 30 25
+ 20 15 10 12
+ 3 5
+ */
+ SCOPED_TRACE("max-heap #2");
+ string actual = strPurge(h.toStringBFS(), "| ");
+ ASSERT_EQ("4030252015101235", actual) << "bad max heap after add";
+ }
+
+
+ }
+
+ };
+
+
+ ADD_TEST_F(BinaryHeapTest, heapify);
+ ADD_TEST_F(BinaryHeapTest, top);
+ ADD_TEST_F(BinaryHeapTest, pop);
+ ADD_TEST_F(BinaryHeapTest, insert);
+ ADD_TEST_F(BinaryHeapTest, bubbleUp);
+ ADD_TEST_F(BinaryHeapTest, selectChildForBubbleDown);
+ ADD_TEST_F(BinaryHeapTest, bubbleDown);
+ ADD_TEST_F(BinaryHeapTest, maxHeap);
+ ADD_TEST_F(BinaryHeapTest, customComparatorHeap);
+
+
+
+
+ }
+}
\ No newline at end of file
diff --git a/YASI_12/ds.mutableheap.h b/YASI_12/ds.mutableheap.h
index 3c9342d..a20f48b 100644
--- a/YASI_12/ds.mutableheap.h
+++ b/YASI_12/ds.mutableheap.h
@@ -1,17 +1,22 @@
#pragma once
#include "ds.binaryheap.h"
-#include "gtest\gtest.h"
-#include "ds.kvpair.h"
-#include "utils.h"
+
+// enable-disable testing classes in this file
+#include "test.this.module.h"
namespace yasi{
namespace ds{
using namespace std;
+
+
+ //////////////////////////////////////////////
+ //////////////// Mutable Heap ////////////////
+ //////////////////////////////////////////////
template
- class MutableHeap : public BinaryHeap < KVPair > {
+ class MutableHeap : public BinaryHeap < KVPair > {
////////// enable testing ///////////
- friend class MutableHeapTest;
+ FRIEND_TEST_CLASS(MutableHeapTest);
typedef KVPair HeapElement;
typedef BinaryHeap Heap;
typedef typename Heap::HeapNode Node;
@@ -27,12 +32,12 @@ namespace yasi{
// need update
if (newElem < pNode->element){
// need bubble-up
- ((HeapElement*) & pNode->element)->key = newKey; // updated
+ ((HeapElement*)& pNode->element)->key = newKey; // updated
bubbleUp(pNode);
}
else{
// need bubble-down
- ((HeapElement*) & pNode->element)->key = newKey; // updated
+ ((HeapElement*)& pNode->element)->key = newKey; // updated
bubbleDown(pNode);
}
}
@@ -40,51 +45,7 @@ namespace yasi{
}
};
- class MutableHeapTest : public ::testing::Test{
- typedef KVPair Pair;
- typedef MutableHeap MHeap;
- public:
- void updateKey(){
- MHeap h;
- MHeap::HeapNode* n[5];
- for (int i = 0; i < 5; i++){
- n[i] = h.insert(Pair(i)); // both key and value are i
- }
-
- string str;
- h.toString(str); // should be 0 1 2 3 4
- string strBefore = strPurge(str, "| ");
- string expectedStrBefore = "01234";
- ASSERT_EQ(expectedStrBefore, strBefore) << "heap toString() mismatch";
-
- // now update key 3 to 9
- h.updateKey(n[3], 9);
- // heap: 0 1 2 9 4
- h.toString(str);
- string strAfter = strPurge(str, "| ");
- string expectedStrAfter = "01294";
- ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 3-->9";
-
- // now update key 2 to -8
- h.updateKey(n[2], -8);
- // heap: -8 1 0 9 4
- h.toString(str);
- strAfter = strPurge(str, "| ");
- expectedStrAfter = "-81094";
- ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 2-->-8";
-
- // now update key 9 to -9
- h.updateKey(n[3], -9);
- // heap: -9 -8 0 1 4
- h.toString(str);
- strAfter = strPurge(str, "| ");
- expectedStrAfter = "-9-8014";
- ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 9-->-9";
-
- }
- };
- ADD_TEST_F(MutableHeapTest, updateKey);
} // namespace ds
} // namespace yasi
\ No newline at end of file
diff --git a/YASI_12/ds.mutableheap.test.h b/YASI_12/ds.mutableheap.test.h
new file mode 100644
index 0000000..6a2898c
--- /dev/null
+++ b/YASI_12/ds.mutableheap.test.h
@@ -0,0 +1,57 @@
+#pragma once
+
+#if YASI_TEST_THIS_MODULE != 1
+#define YASI_TEST_THIS_MODULE 1
+#endif
+#include "ds.mutableheap.h"
+
+namespace yasi{
+ namespace ds{
+
+
+ class MutableHeapTest : public yasi::Test{
+ typedef KVPair Pair;
+ typedef MutableHeap MHeap;
+ public:
+ void updateKey(){
+ MHeap h;
+ MHeap::HeapNode* n[5];
+ for (int i = 0; i < 5; i++){
+ n[i] = h.insert(Pair(i)); // both key and value are i
+ }
+
+ string str = h.toStringBFS(); // should be 0 1 2 3 4
+ string strBefore = strPurge(str, "| ");
+ string expectedStrBefore = "01234";
+ ASSERT_EQ(expectedStrBefore, strBefore) << "heap toString() mismatch";
+
+ // now update key 3 to 9
+ h.updateKey(n[3], 9);
+ // heap: 0 1 2 9 4
+ str = h.toStringBFS();
+ string strAfter = strPurge(str, "| ");
+ string expectedStrAfter = "01294";
+ ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 3-->9";
+
+ // now update key 2 to -8
+ h.updateKey(n[2], -8);
+ // heap: -8 1 0 9 4
+ str = h.toStringBFS();
+ strAfter = strPurge(str, "| ");
+ expectedStrAfter = "-81094";
+ ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 2-->-8";
+
+ // now update key 9 to -9
+ h.updateKey(n[3], -9);
+ // heap: -9 -8 0 1 4
+ str = h.toStringBFS();
+ strAfter = strPurge(str, "| ");
+ expectedStrAfter = "-9-8014";
+ ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 9-->-9";
+
+ }
+ };
+
+ ADD_TEST_F(MutableHeapTest, updateKey);
+ }
+}
\ No newline at end of file
diff --git a/YASI_12/ds.mutablepriorityqueue.h b/YASI_12/ds.mutablepriorityqueue.h
new file mode 100644
index 0000000..075c436
--- /dev/null
+++ b/YASI_12/ds.mutablepriorityqueue.h
@@ -0,0 +1,104 @@
+#pragma once
+#include "ds.priorityqueue.h"
+#include "ds.BSTDictionary.h" // for mutable priority queue
+
+// enable-disable testing classes in this file
+#include "test.this.module.h"
+
+using namespace std;
+
+namespace yasi{
+ namespace ds{
+
+
+ ///////////////////////////////////
+ ////// mutable priority queue /////
+ ///////////////////////////////////
+ template
+ class MutablePriorityQueue {
+ /////////// enable testing ////////////
+ FRIEND_TEST_CLASS( MutablePriorityQueueTest);
+
+ typedef MutableHeap < Key, Value > HeapType;
+ typedef KVPair Pair;
+ public:
+ typedef typename HeapType::HeapNode Node;
+
+ protected:
+ // value-to-heapnode lookup
+ typedef Node* DictValue;
+ typedef Value DictKey;
+ typedef BSTDictionary Dict;
+ Dict d;
+
+ // the internal priority queue
+ PriorityQueue < Pair, HeapType > pq;
+ protected:
+ DictValue findNode(const Value& v) const {
+ DictValue* pValue = d.find(v); // d.find() returns a ptr to value, and NULL if not found
+ return pValue ? *pValue : NULL;
+ }
+
+ public:
+ typedef typename HeapType::HeapNode Node;
+
+ MutablePriorityQueue(){ }
+ virtual ~MutablePriorityQueue(){ pq.clear(); }
+
+ // modify existing priority queue methods to support key update
+ // input arg kv is an instance of the KVPair class
+ void push(const Key& k, const Value& v) {
+ insert(kv.key, kv.value);
+ }
+ void pop() {
+ if (!empty()){
+ removeTop();
+ }
+ }
+
+ // on empty queue, behavior undefined
+ Value removeTop() {
+ Pair kv;
+ if (!empty()){
+ kv = (Pair)pq.top();
+
+ // remove the element from dictionary
+ d.remove(kv.value);
+
+ // now pop from heap
+ pq.pop();
+
+ }
+ // done
+ return kv.value;
+ }
+
+ // undefined on empty queue
+ const Value& top() const { return pq.top(); }
+ int size() const { return pq.size(); }
+ bool empty() const { return pq.empty(); }
+ string toStringBFS(){ return pq.toStringBFS(); }
+
+
+ // new methods on top of PriorityQueue
+ Node* insert(const Key& k, const Value& v) {
+ Node* pNode = pq.heap().insert(Pair(k, v));
+ // add the node to dictionary
+ // with key = kv.value
+ d.insert(v, pNode);
+ return pNode;
+ }
+ Node* insert(const Key& k) { return insert(k, k); }
+ //Node* insert(const Pair& e) { return h.insert(e); }
+
+ // update the key in a HeapNode pointer
+ void updateKey(Node* pNode, const Key newKey){ if (pNode) pq.heap().updateKey(pNode, newKey); }
+ // update the key of a value; if values are not unique, behavior is undefined
+ void updateKey(const Value& v, const Key newKey){
+ Node* pNode = findNode(v);
+ if (pNode) updateKey(pNode, newKey);
+ }
+ };
+
+ }
+}
\ No newline at end of file
diff --git a/YASI_12/ds.mutablepriorityqueue.test.h b/YASI_12/ds.mutablepriorityqueue.test.h
new file mode 100644
index 0000000..388b45a
--- /dev/null
+++ b/YASI_12/ds.mutablepriorityqueue.test.h
@@ -0,0 +1,84 @@
+#pragma once
+
+#if YASI_TEST_THIS_MODULE != 1
+#define YASI_TEST_THIS_MODULE 1
+#endif
+#include "ds.mutablepriorityqueue.h"
+
+namespace yasi{
+ namespace ds{
+
+
+ class MutablePriorityQueueTest : public yasi::Test{
+ typedef MutablePriorityQueue MPQ;
+ typedef MPQ::Node Node;
+ public:
+ void dictionary(){
+ // insert key-values and check the dictionary
+ MPQ pq;
+ Node* n[5];
+ for (int i = 0; i < 5; i++){
+ n[i] = pq.insert(i, i * 10); // key i, value i*10
+ }
+ ASSERT_EQ(pq.size(), pq.d.size()) << "dictionary and pq size not same";
+
+ // now check dictionary
+ string strDictBfs = pq.d.toStringBFS();
+ string strDictPreorder = pq.d.toStringPreOrder();
+ for (int i = 0; i < 5; i++){
+ // lookup node by value
+ Node* pNode = pq.findNode(i * 10);
+ ASSERT_NE(0, (int)pNode) << "pq node NULL";
+ ASSERT_EQ(pNode, n[i]) << "dictionary entry mismatch";
+ }
+
+ // remove a node
+ int topValue = pq.removeTop();
+ ASSERT_EQ(0, (int)pq.findNode(topValue)) << "removed node still in dictionary";
+ ASSERT_EQ(pq.size(), pq.d.size()) << "dictionary and pq size not same";
+
+ }
+ void updateKey(){
+ MPQ pq;
+ MPQ::Node* n[5];
+ for (int i = 0; i < 5; i++){
+ n[i] = pq.insert(i); // both key and value are i
+ }
+
+ string str;
+ str = pq.toStringBFS(); // should be 0 1 2 3 4
+ string strBefore = strPurge(str, "| ");
+ string expectedStrBefore = "01234";
+ ASSERT_EQ(expectedStrBefore, strBefore) << "heap toString() mismatch";
+
+ // now update key 3 to 9
+ pq.updateKey(3, 9); // testing updateKey(value, key) method
+ // heap: 0 1 2 9 4
+ str = pq.toStringBFS();
+ string strAfter = strPurge(str, "| ");
+ string expectedStrAfter = "01294";
+ ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 3-->9";
+
+ // now update key 2 to -8
+ pq.updateKey(n[2], -8); // testing updateKey(node, key) method
+ // heap: -8 1 0 9 4
+ str = pq.toStringBFS();
+ strAfter = strPurge(str, "| ");
+ expectedStrAfter = "-81094";
+ ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 2-->-8";
+
+ // now update key 9 (which has value 3) to -9
+ pq.updateKey(3, -9); // testing updateKey(value, key) method
+ // heap: -9 -8 0 1 4
+ str = pq.toStringBFS();
+ strAfter = strPurge(str, "| ");
+ expectedStrAfter = "-9-8014";
+ ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 9-->-9";
+
+ }
+ };
+
+ ADD_TEST_F(MutablePriorityQueueTest, dictionary);
+ ADD_TEST_F(MutablePriorityQueueTest, updateKey);
+ }
+}
\ No newline at end of file
diff --git a/YASI_12/ds.priorityqueue.h b/YASI_12/ds.priorityqueue.h
index 0618db2..42a0749 100644
--- a/YASI_12/ds.priorityqueue.h
+++ b/YASI_12/ds.priorityqueue.h
@@ -1,13 +1,14 @@
#pragma once
#include "common.h"
-#include "gtest\gtest.h"
#include "utils.h"
#include "ds.list.h"
#include "ds.binaryheap.h"
#include "ds.aux.hastree.h"
-#include "ds.BSTDictionary.h" // for mutable priority queue
#include
+// enable-disable testing classes in this file
+#include "test.this.module.h"
+
using namespace std;
namespace yasi{
@@ -30,7 +31,7 @@ class IPriorityQueue {
template >
class PriorityQueue : public virtual IPriorityQueue < E >, public ds::aux::HasTree {
/////////// enable testing ////////////
- friend class PriorityQueueTest;
+ FRIEND_TEST_CLASS( PriorityQueueTest);
protected:
Heap h;
@@ -56,275 +57,6 @@ class PriorityQueue : public virtual IPriorityQueue < E >, public ds::aux::HasTr
};
- class PriorityQueueTest :public yasi::Test{
- typedef PriorityQueue pq_t;
- public:
- void all(){
- //PriorityQueue< stack > pqq;
- int t;
- pq_t pq;
-
- ASSERT_EQ(0, pq.size()) << "size not zero";
- ASSERT_EQ(true, pq.empty()) << "pq not empty";
-
- pq.push(t = 5);
- pq.push(t = 2);
- pq.push(t = 10);
- pq.push(t = 8);
- pq.push(t = 5);
- pq.push(t = 3);
-
- ASSERT_EQ(6, pq.size()) << "size not 6";
- ASSERT_EQ(false, pq.empty()) << "pq empty";
- ASSERT_EQ(2, pq.top()) << "top not 2";
-
- pq.pop();
- ASSERT_EQ(5, pq.size()) << "size not 5";
- ASSERT_EQ(3, pq.top()) << "top not 3";
-
- pq.pop();
- ASSERT_EQ(4, pq.size()) << "size not 4";
- ASSERT_EQ(5, pq.top()) << "top not 5";
-
- pq.pop();
- ASSERT_EQ(3, pq.size()) << "size not 3";
- ASSERT_EQ(5, pq.top()) << "top not 5";
-
- pq.push(7);
- pq.push(13);
- ASSERT_EQ(5, pq.size()) << "size not 5";
- ASSERT_EQ(5, pq.top()) << "top not 5";
-
- pq.pop();
- ASSERT_EQ(4, pq.size()) << "size not 4";
- ASSERT_EQ(7, pq.top()) << "top not 7";
-
- pq.pop();
- ASSERT_EQ(3, pq.size()) << "size not 3";
- ASSERT_EQ(8, pq.top()) << "top not 8";
-
- pq.pop();
- ASSERT_EQ(2, pq.size()) << "size not 2";
- ASSERT_EQ(10, pq.top()) << "top not 10";
-
- pq.pop();
- ASSERT_EQ(1, pq.size()) << "size not 1";
- ASSERT_EQ(13, pq.top()) << "top not 13";
-
- pq.pop();
- ASSERT_EQ(0, pq.size()) << "size not 0";
- ASSERT_EQ(true, pq.empty()) << "pq not empty";
- }
-
- void maxPriorityQueue(){
- // pq of numeric string, max-pq
- PriorityQueue > pq;
-
- pq.push("10");
- pq.push("5");
- pq.push("20");
- pq.push("15");
- pq.push("25");
- {
- /* heap:
- 25
- 20 10
- 5 15
- */
- SCOPED_TRACE("max-pq #1");
- string actual = strPurge(pq.toStringBFS(), "| ");
- ASSERT_EQ("252010515", actual) << "bad max pq";
- }
- // add some more items
- {
- pq.push("12");
- pq.push("30");
- pq.push("3");
- pq.push("40");
- /* pq:
- 40
- 30 25
- 20 15 10 12
- 3 5
- */
- SCOPED_TRACE("max-pq #2");
- string actual = strPurge(pq.toStringBFS(), "| ");
- ASSERT_EQ("4030252015101235", actual) << "bad max pq after add";
- }
- // now check by popping
- int actual[9];
- for (int i = 0; !pq.empty(); i++){
- actual[i] = atoi(pq.removeTop().c_str());
- }
- const int expected[] = {40, 30, 25, 20, 15, 12, 10, 5, 3};
- ASSERT_EQ(true, arrcmp(actual, expected, ARR_LENGTH(expected))) << "wrong pop sequence from max heap";
- }
- };
-
- ADD_TEST_F(PriorityQueueTest, all);
- ADD_TEST_F(PriorityQueueTest, maxPriorityQueue);
-
-
-///////////////////////////////////
-////// mutable priority queue /////
-///////////////////////////////////
-template
-class MutablePriorityQueue {
- /////////// enable testing ////////////
- friend class MutablePriorityQueueTest;
-
- typedef MutableHeap < Key, Value > HeapType;
- typedef KVPair Pair;
-public:
- typedef typename HeapType::HeapNode Node;
-
-protected:
- // value-to-heapnode lookup
- typedef Node* DictValue;
- typedef Value DictKey;
- typedef BSTDictionary Dict;
- Dict d;
-
- // the internal priority queue
- PriorityQueue < Pair, HeapType > pq;
-protected:
- DictValue findNode(const Value& v) const {
- DictValue* pValue = d.find(v); // d.find() returns a ptr to value, and NULL if not found
- return pValue ? *pValue : NULL;
- }
-
-public:
- typedef typename HeapType::HeapNode Node;
-
- MutablePriorityQueue(){ }
- virtual ~MutablePriorityQueue(){ pq.clear(); }
-
- // modify existing priority queue methods to support key update
- // input arg kv is an instance of the KVPair class
- void push(const Key& k, const Value& v) {
- insert(kv.key, kv.value);
- }
- void pop() {
- if (!empty()){
- removeTop();
- }
- }
-
- // on empty queue, behavior undefined
- Value removeTop() {
- Pair kv;
- if (!empty()){
- kv = (Pair)pq.top();
-
- // remove the element from dictionary
- d.remove(kv.value);
-
- // now pop from heap
- pq.pop();
-
- }
- // done
- return kv.value;
- }
-
- // undefined on empty queue
- const Value& top() const { return pq.top(); }
- int size() const { return pq.size(); }
- bool empty() const { return pq.empty(); }
- string toStringBFS(){ return pq.toStringBFS(); }
-
-
- // new methods on top of PriorityQueue
- Node* insert(const Key& k, const Value& v) {
- Node* pNode = pq.heap().insert(Pair(k, v));
- // add the node to dictionary
- // with key = kv.value
- d.insert(v, pNode);
- return pNode;
- }
- Node* insert(const Key& k) { return insert(k, k); }
- //Node* insert(const Pair& e) { return h.insert(e); }
-
- // update the key in a HeapNode pointer
- void updateKey(Node* pNode, const Key newKey){ if(pNode) pq.heap().updateKey(pNode, newKey); }
- // update the key of a value; if values are not unique, behavior is undefined
- void updateKey(const Value& v, const Key newKey){
- Node* pNode = findNode(v);
- if(pNode) updateKey(pNode, newKey);
- }
-};
-
-class MutablePriorityQueueTest : public yasi::Test{
- typedef MutablePriorityQueue MPQ;
- typedef MPQ::Node Node;
-public:
- void dictionary(){
- // insert key-values and check the dictionary
- MPQ pq;
- Node* n[5];
- for (int i = 0; i < 5; i++){
- n[i] = pq.insert(i, i*10); // key i, value i*10
- }
- ASSERT_EQ(pq.size(), pq.d.size()) << "dictionary and pq size not same";
-
- // now check dictionary
- string strDictBfs = pq.d.toStringBFS();
- string strDictPreorder = pq.d.toStringPreOrder();
- for (int i = 0; i < 5; i++){
- // lookup node by value
- Node* pNode = pq.findNode(i*10);
- ASSERT_NE(0, (int)pNode) << "pq node NULL";
- ASSERT_EQ(pNode, n[i]) << "dictionary entry mismatch";
- }
-
- // remove a node
- int topValue = pq.removeTop();
- ASSERT_EQ(0, (int) pq.findNode(topValue)) << "removed node still in dictionary";
- ASSERT_EQ(pq.size(), pq.d.size()) << "dictionary and pq size not same";
-
- }
- void updateKey(){
- MPQ pq;
- MPQ::Node* n[5];
- for (int i = 0; i < 5; i++){
- n[i] = pq.insert(i); // both key and value are i
- }
-
- string str;
- str = pq.toStringBFS(); // should be 0 1 2 3 4
- string strBefore = strPurge(str, "| ");
- string expectedStrBefore = "01234";
- ASSERT_EQ(expectedStrBefore, strBefore) << "heap toString() mismatch";
-
- // now update key 3 to 9
- pq.updateKey(3, 9); // testing updateKey(value, key) method
- // heap: 0 1 2 9 4
- str = pq.toStringBFS();
- string strAfter = strPurge(str, "| ");
- string expectedStrAfter = "01294";
- ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 3-->9";
-
- // now update key 2 to -8
- pq.updateKey(n[2], -8); // testing updateKey(node, key) method
- // heap: -8 1 0 9 4
- str = pq.toStringBFS();
- strAfter = strPurge(str, "| ");
- expectedStrAfter = "-81094";
- ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 2-->-8";
-
- // now update key 9 (which has value 3) to -9
- pq.updateKey(3, -9); // testing updateKey(value, key) method
- // heap: -9 -8 0 1 4
- str = pq.toStringBFS();
- strAfter = strPurge(str, "| ");
- expectedStrAfter = "-9-8014";
- ASSERT_EQ(expectedStrAfter, strAfter) << "bad heap after update 9-->-9";
-
- }
-};
-
-ADD_TEST_F(MutablePriorityQueueTest, dictionary);
-ADD_TEST_F(MutablePriorityQueueTest, updateKey);
} // namespace ds
diff --git a/YASI_12/ds.priorityqueue.test.h b/YASI_12/ds.priorityqueue.test.h
new file mode 100644
index 0000000..3ff495c
--- /dev/null
+++ b/YASI_12/ds.priorityqueue.test.h
@@ -0,0 +1,119 @@
+#pragma once
+
+#if YASI_TEST_THIS_MODULE != 1
+#define YASI_TEST_THIS_MODULE 1
+#endif
+#include "ds.priorityqueue.h"
+
+namespace yasi{
+ namespace ds{
+
+ class PriorityQueueTest :public yasi::Test{
+ typedef PriorityQueue pq_t;
+ public:
+ void all(){
+ //PriorityQueue< stack > pqq;
+ int t;
+ pq_t pq;
+
+ ASSERT_EQ(0, pq.size()) << "size not zero";
+ ASSERT_EQ(true, pq.empty()) << "pq not empty";
+
+ pq.push(t = 5);
+ pq.push(t = 2);
+ pq.push(t = 10);
+ pq.push(t = 8);
+ pq.push(t = 5);
+ pq.push(t = 3);
+
+ ASSERT_EQ(6, pq.size()) << "size not 6";
+ ASSERT_EQ(false, pq.empty()) << "pq empty";
+ ASSERT_EQ(2, pq.top()) << "top not 2";
+
+ pq.pop();
+ ASSERT_EQ(5, pq.size()) << "size not 5";
+ ASSERT_EQ(3, pq.top()) << "top not 3";
+
+ pq.pop();
+ ASSERT_EQ(4, pq.size()) << "size not 4";
+ ASSERT_EQ(5, pq.top()) << "top not 5";
+
+ pq.pop();
+ ASSERT_EQ(3, pq.size()) << "size not 3";
+ ASSERT_EQ(5, pq.top()) << "top not 5";
+
+ pq.push(7);
+ pq.push(13);
+ ASSERT_EQ(5, pq.size()) << "size not 5";
+ ASSERT_EQ(5, pq.top()) << "top not 5";
+
+ pq.pop();
+ ASSERT_EQ(4, pq.size()) << "size not 4";
+ ASSERT_EQ(7, pq.top()) << "top not 7";
+
+ pq.pop();
+ ASSERT_EQ(3, pq.size()) << "size not 3";
+ ASSERT_EQ(8, pq.top()) << "top not 8";
+
+ pq.pop();
+ ASSERT_EQ(2, pq.size()) << "size not 2";
+ ASSERT_EQ(10, pq.top()) << "top not 10";
+
+ pq.pop();
+ ASSERT_EQ(1, pq.size()) << "size not 1";
+ ASSERT_EQ(13, pq.top()) << "top not 13";
+
+ pq.pop();
+ ASSERT_EQ(0, pq.size()) << "size not 0";
+ ASSERT_EQ(true, pq.empty()) << "pq not empty";
+ }
+
+ void maxPriorityQueue(){
+ // pq of numeric string, max-pq
+ PriorityQueue > pq;
+
+ pq.push("10");
+ pq.push("5");
+ pq.push("20");
+ pq.push("15");
+ pq.push("25");
+ {
+ /* heap:
+ 25
+ 20 10
+ 5 15
+ */
+ SCOPED_TRACE("max-pq #1");
+ string actual = strPurge(pq.toStringBFS(), "| ");
+ ASSERT_EQ("252010515", actual) << "bad max pq";
+ }
+ // add some more items
+ {
+ pq.push("12");
+ pq.push("30");
+ pq.push("3");
+ pq.push("40");
+ /* pq:
+ 40
+ 30 25
+ 20 15 10 12
+ 3 5
+ */
+ SCOPED_TRACE("max-pq #2");
+ string actual = strPurge(pq.toStringBFS(), "| ");
+ ASSERT_EQ("4030252015101235", actual) << "bad max pq after add";
+ }
+ // now check by popping
+ int actual[9];
+ for (int i = 0; !pq.empty(); i++){
+ actual[i] = atoi(pq.removeTop().c_str());
+ }
+ const int expected[] = { 40, 30, 25, 20, 15, 12, 10, 5, 3 };
+ ASSERT_EQ(true, arrcmp(actual, expected, ARR_LENGTH(expected))) << "wrong pop sequence from max heap";
+ }
+ };
+
+ ADD_TEST_F(PriorityQueueTest, all);
+ ADD_TEST_F(PriorityQueueTest, maxPriorityQueue);
+ }
+}
\ No newline at end of file
diff --git a/YASI_12/main.cpp b/YASI_12/main.cpp
index ac4a420..cb3186a 100644
--- a/YASI_12/main.cpp
+++ b/YASI_12/main.cpp
@@ -1,8 +1,6 @@
#include "common.h"
-//#include "ds.arraybinarytree.h"
//#include "ds.binaryheap.h"
-//#include "ds.binarytree.h"
//#include "ds.binarysearchtree.h"
//#include "ds.priorityqueue.h"
//#include "ds.BSTDictionary.h"
@@ -31,6 +29,10 @@ using namespace std;
#include "ds.doublylinkedlist.test.h"
#include "ds.binarytree.test.h"
#include "ds.arraybinarytree.test.h"
+#include "ds.binaryheap.test.h"
+#include "ds.mutableheap.test.h"
+#include "ds.priorityqueue.test.h"
+#include "ds.mutablepriorityqueue.test.h"
int testAll(int* argc, char** argv){