Question: The DoublyLinkedList begin() method: This should create a temporary iterator object. Then set the temp's atRightEnd to false (unless the list is empty, then set

The DoublyLinkedList begin() method: This should create a temporary iterator object. Then set the temp's atRightEnd to false (unless the list is empty, then set it to true), and temp's current should be assigned to the list's first. Then the temp object is returned.

The DoublyLinkedList end() method: This should create a temporary iterator object. Then set the temp's atRightEnd to true, and temp's current should be assigned to the list's last. Then the temp object is returned.

overloaded * operator: This just returns the data that is in the node that current is pointing to. A one-liner. Make sure the return type is a T& and not a T.

overloaded != operator: This checks to see if both objects have the same atRightEnd and the same current values. If both objects have the same values, then return false. Otherwise just return true.

overloaded ++ prefix operator: The return type needs to be Iterator. The iterator should be moved forward one node, if possible. If moving it forward would mean it would become empty/nullptr, don't move it forward, and instead set the boolean atRightEnd to true. If atRightEnd is already true, you don't need to do anything. You need a return type, you need to return a copy of the iterator, and you can do that with return *this.

overloaded ++ postfix operator: The return type needs to be Iterator. You can overload the postfix operator by having a single (int) in the parameter section. Very similar to the prefix operator with one change. You first must make a copy of itself (Iterator copy = *this;). Increment the object pointed to by this. Return the copy you previously made.

overloaded -- prefix operator: The return type needs to be Iterator. Somewhat like to the operator++ prefix, but going backwards. You need to return a copy of the iterator, and you can do that with return *this. Note that operator-- doesnt have any corresponding atLeftEnd. The behavior of going off the left side of the collection is undefined, or in other words, dont worry about supporting it.

You must also complete an ourSort() method. This method passes in two iterators. You may only use knowledge obtained from iterators to complete this section. The most helpful tool will be iter_swap() which takes any two iterators and swaps the values they point to. Along with iter_swap(), you will likely want to use prefix ++, prefix --, !=, and making temporary copies of iterators to complete your logic. You definitely can't use linked list methods or access Node data members in ourSort(), or in other words, you can't write code that attempts to move begin forward with begin = begin->forward, rather, you should use ++begin. The logic you can follow mirrors this follwing psuedo code:

if the collection isnt empty

make a curr which tracks the start of the list

make an ahead which is one item ahead of curr

create a finished boolean initialized to false

while finished is false

set finished to true (assume we are done, but we may find we are not done)

set curr at the start of the collection

set ahead to be one item ahead of curr

while ahead is still pointing to a valid item

if the data at ahead is less than the data at curr

swap the data values being pointed to by both ahead and curr

set finished to false (we made a swap, we arent done)

increment curr

increment ahead

// The rightmost item is sorted (of those values considered)

// You can move end back one item as this item is sorted and no longer needs

// to be checked again

Now here is the code created by the Instructor in which we need to finish his "TODO" sections and uncomment his tests and pass each test.

#include

#include

#include

#include

#include

#include

//To prevent those using g++ from trying to use a library

//they don't have

#ifndef __GNUC__

#include

#else

#include

#endif

#include

template class DoublyLinkedList;

using std::cout;

using std::endl;

using std::string;

using std::vector;

using std::shared_ptr;

using std::make_shared;

using std::stringstream;

//************************************************************************

//A class I designed to help keep track of how much memory you allocate

//Do not modify, this is not part of your assignment, it just helps test it.

//For this to work, a class needs to inherit off of this one.

//Then this does the rest of the work, since it

//overloads new, new[], delete, and delete[].

//************************************************************************

class ManageMemory {

public:

static std::size_t getTotalSize() {

std::size_t total = 0;

std::map::iterator iter;

for (iter = mapOfAllocations.begin(); iter != mapOfAllocations.end(); ++iter) {

total += iter->second;

}

return total;

}

//I overloaded the new and delete keywords so I could manually track allocated memory.

void* operator new(std::size_t x){

void *ptr = ::operator new(x);

mapOfAllocations[ptr] = x;

return ptr;

}

void* operator new[](std::size_t x) {

void *ptr = ::operator new[](x);

mapOfAllocations[ptr] = x;

return ptr;

}

void operator delete(void* x) {

mapOfAllocations.erase(x);

::operator delete(x);

}

void operator delete[](void* x) {

mapOfAllocations.erase(x);

::operator delete[](x);

}

private:

static std::map mapOfAllocations;

};

std::map ManageMemory::mapOfAllocations;

//******************

//The node class

//******************

template

struct Node {

T data{};

shared_ptr< Node > forward;

shared_ptr< Node > backward;

};

//******************

//The Iterator class

//******************

template

class Iterator : public ManageMemory, public std::iterator {

friend class DoublyLinkedList;

public:

//TODO: Complete these operator overloads:

//operator*

//operator++ prefix return *this;

//operator++ postfix auto temp = *this; move the "this"...; return temp;

//operator-- prefix

//operator!=

//operator==

private:

//TODO: supply two data members

//You need a shared pointer to a node (if you want, an even better approach would be to use a weak pointer)

//You need a boolean atRightEnd (see lecture video)

};

//***********************************

//The Iterator class methods

//***********************************

//TODO, code the definitions for all the iterator methods.

//****************************

//The DoublyLinkedList class

//****************************

template

class DoublyLinkedList : public ManageMemory {

public:

//public members of the DoublyLinkedList class

DoublyLinkedList();

~DoublyLinkedList();

string getStringFromList();

void insertFirst(const T&);

void insertLast(const T&);

void deleteFirst();

void deleteLast();

//TODO: Implement a begin() and end() method with return types of Iterator

protected:

shared_ptr< Node > first;

shared_ptr< Node > last;

unsigned int count;

};

template

DoublyLinkedList::DoublyLinkedList() {

count = 0;

first = nullptr;

last = nullptr;

}

template

DoublyLinkedList::~DoublyLinkedList() {

while (first) {

first->backward.reset();

first = first->forward;

}

last.reset();

}

template

void DoublyLinkedList::insertLast(const T& item) {

if (!first) {

//Scenario #1 - The list is empty

first = make_shared< Node >();

first->data = item;

last = first;

}

else {

//Scenario #2 - The list has at least one item

shared_ptr< Node > tempPtr = make_shared< Node >();

tempPtr->data = item;

last->forward = tempPtr;

tempPtr->backward = last;

last = tempPtr;

}

count++;

}

template

void DoublyLinkedList::insertFirst(const T& item) {

if (!first) {

//Scenario #1 The list is empty

first = make_shared< Node >();

first->data = item;

last = first;

}

else {

//Scenario #2 The list has at least one item in it

shared_ptr< Node > tempPtr = make_shared< Node >();

tempPtr->data = item;

tempPtr->forward = first;

first->backward = tempPtr;

first = tempPtr;

}

count++;

}

template

void DoublyLinkedList::deleteFirst() {

//Empty list

if (!first) {

cout << "List is already empty" << endl;

return;

}

//Scenario 1 or more nodes

first = first->forward;

if (!first) {

//Must have been only 1 node in the list

last.reset();

}

else {

//first->backward = nullptr;

first->backward.reset();

}

count--;

}

template

void DoublyLinkedList::deleteLast() {

if (!first) {

//empty list scenario

cout << "The list is empty" << endl;

}

else {

last = last->backward;

if (!last) {

//1 node scenario

first.reset();

}

else {

//2 or more node scenario

last->forward.reset();

}

count--;

}

}

//This method helps return a string representation of all nodes in the linked list

template

string DoublyLinkedList::getStringFromList() {

stringstream ss;

if (first == nullptr) {

ss << "The list is empty.";

}

else {

shared_ptr< Node > currentNode = first;

ss << currentNode->data;

currentNode = currentNode->forward;

while (currentNode != nullptr) {

ss << " " << currentNode->data;

currentNode = currentNode->forward;

}

}

return ss.str();

}

//***********************************

//The DoublyLinkedList class methods

//***********************************

//TODO, implement the the definitions for the begin() and end() methods

//***********************************

// TODO, complete the ourSort function.

// Note that begin and end here are are iterators (The T is just saying it can be any kind of iterator).

// Our iterator tools are ***ONLY***

// ++, --, !=, *, ==.

// To create a copy of iterators:

// T copyOfBeging = begin;

// To swap the data being pointed at by two iterators:

// iter_swap(begin, end);

template

void ourSort(T begin, T end) {

}

//----------------------------------------------------------------------------------------------------------------------------------------

//This helps with testing, do not modify.

bool checkTest(string testName, string whatItShouldBe, string whatItIs) {

if (whatItShouldBe == whatItIs) {

cout << "Passed " << testName << endl;

return true;

}

else {

cout << "****** Failed test " << testName << " ****** " << endl << " Output was " << whatItIs << endl << " Output should have been " << whatItShouldBe << endl;

return false;

}

}

//This helps with testing, do not modify.

bool checkTest(string testName, int whatItShouldBe, int whatItIs) {

if (whatItShouldBe == whatItIs) {

cout << "Passed " << testName << endl;

return true;

}

else {

cout << "****** Failed test " << testName << " ****** " << endl << " Output was " << whatItIs << endl << " Output should have been " << whatItShouldBe << endl;

return false;

}

}

//This helps with testing, do not modify.

bool checkTestMemory(string testName, int whatItShouldBe, int whatItIs) {

if (whatItShouldBe == whatItIs) {

cout << "Passed " << testName << endl;

return true;

}

else {

cout << "***Failed test " << testName << " *** " << endl << " There are " << whatItIs << " bytes of memory yet to be reclaimed!" << endl;

return false;

}

}

//This helps with testing, do not modify.

void testIteratorFundamentals() {

cout << "|||### You need to comment in testIteratorFundamentals() when it's ready and remove this###|||" << endl;

/*

DoublyLinkedList d;

//Our test data should have all even numbers from 2 to 20

for (int i = 2; i <= 20; i += 2) {

d.insertLast(i);

}

//Get an iterator which points at the beginning of the list

Iterator iter = d.begin();

//Test the operator* operator

checkTest("testIteratorFundamentals #1", 2, *iter);

//Test the ++ prefix increment opreator

++iter;

checkTest("testIteratorFundamentals #2", 4, *iter);

//Test the != operator

//reset them back to the start

iter = d.begin();

Iterator anotherIter = d.begin();

if (iter != anotherIter) {

cout << "****** Failed testIteratorFundamentals #3 ****** " << endl << " The two iteraters held the same data." << endl;

}

else {

cout << "Passed testIteratorFundamentals #3" << endl;

}

//Again test the != operator

++iter;

if (iter != anotherIter) {

cout << "Passed testIteratorFundamentals #4" << endl;

}

else {

cout << "****** Failed testIteratorFundamentals #4 ****** " << endl << " The two iteraters held different data." << endl;

}

//Test the ++postfix increment

iter = d.begin(); //reset it back to the start

anotherIter = iter++; //anotherIter should be at the data 2

checkTest("testIteratorFundamentals #5", 4, *iter);

checkTest("testIteratorFundamentals #6", 2, *anotherIter);

checkTest("testIteratorFundamentals #7", "2 4 6 8 10 12 14 16 18 20", d.getStringFromList());

*/

}

//This helps with testing, do not modify.

void testIteratorIncrement() {

cout << "|||### You need to comment in testIteratorIncrement() when it's ready and remove this ###|||" << endl;

/* DoublyLinkedList *d = new DoublyLinkedList;

//Our test data should have all even numbers from 2 to 20

for (int i = 2; i <= 20; i += 2) {

d->insertLast(i);

}

//Get an iterator which points at the beginning of the list

Iterator iter = d->begin();

//Test that it does point to the first

checkTest("testIteratorsIncrement #1", 2, *iter);

//Test that our Iterator can move forward;

++iter; checkTest("testIteratorsIncrement #2", 4, *iter);

//Test that our Iterator can move forward again;

++iter;

checkTest("testIteratorsIncrement #3", 6, *iter);

//move it some more

for (int i = 0; i < 6; i++) {

++iter;

}

checkTest("testIteratorsIncrement #4", 18, *iter);

//Hit the end

++iter;

checkTest("testIteratorsIncrement #5", 20, *iter);

//Verify we move the iterator past the end without crashing

++iter;

checkTest("testIteratorsIncrement #6", "did not crash", "did not crash");

delete d;

*/

}

//This helps with testing, do not modify.

void testIteratorDecrement() {

cout << "|||### You need to comment in testIteratorDecrement() when it's ready and remove this###|||" << endl;

/*

DoublyLinkedList *d = new DoublyLinkedList;

//Our test data should have all even numbers from 2 to 20

for (int i = 2; i <= 20; i += 2) {

d->insertLast(i);

}

//Get an Iterator which points at the end of the list

Iterator iter = d->end();

--iter; //We have to do a decrement otherwise it crashes

//Test that it does point to the first

checkTest("testIteratorsDecrement #1", 20, *iter);

//Test that our Iterator can move forward;

--iter;

checkTest("testIteratorsDecrement #2", 18, *iter);

//move it some more

for (int i = 0; i < 7; i++) {

--iter;

}

checkTest("testIteratorsDecrement #3", 4, *iter);

//Hit the end

--iter;

checkTest("testIteratorsDecrement #4", 2, *iter);

//Now go back forward

++iter;

checkTest("testIteratorsDecrement #5", 4, *iter);

delete d;

*/

}

//This helps with testing, do not modify.

void testIterationTricky() {

cout << "|||### You need to comment in testIterationTricky() when it's ready and remove this###|||" << endl;

/*

DoublyLinkedList myListOneNode;

myListOneNode.insertLast(42);

cout << "TestIterationTricky test #1, the next line should display 42" << endl;

stringstream ss;

//see if we can just iterator through one item.

for (auto i : myListOneNode) {

cout << i << " ";

ss << i << " ";

}

cout << endl;

checkTest("TestIterationTricky test #1", "42 ", ss.str());

ss.str("");

DoublyLinkedList myListEmpty;

cout << "TestIterationTricky test #2, the next line shouldn't display anything" << endl;

//see if we can just iterator through one item.

for (auto i : myListEmpty) {

cout << i << " ";

ss << i << " ";

}

cout << endl;

checkTest("TestIterationTricky test #2", "", ss.str());

ss.str("");

*/

}

//This helps with testing, do not modify.

void testAlgorithms() {

cout << "|||### You need to comment in testAlgorithms() when it's ready and remove this###|||" << endl;

/*

DoublyLinkedList myList;

//Our test data should have all even numbers from 2 to 20

for (int i = 2; i <= 6; i += 2) {

myList.insertLast(i);

}

myList.insertLast(100);

for (int i = 8; i <= 12; i += 2) {

myList.insertLast(i);

}

myList.insertLast(100);

for (int i = 14; i <= 20; i += 2) {

myList.insertLast(i);

}

stringstream ss;

for (auto i : myList) {

ss << i << " ";

}

cout << endl;

checkTest("testAlgorithms test #1", "2 4 6 100 8 10 12 100 14 16 18 20 ", ss.str());

ss.str("");

//Now sort it using our algorithm

ourSort(myList.begin(), myList.end());

for (auto i : myList) {

ss << i << " ";

}

cout << endl;

checkTest("testAlgorithms test #2", "2 4 6 8 10 12 14 16 18 20 100 100 ", ss.str());

ss.str("");

DoublyLinkedList manyNines;

manyNines.insertLast(9);

manyNines.insertLast(9);

manyNines.insertLast(4);

manyNines.insertLast(2);

manyNines.insertLast(9);

manyNines.insertLast(9);

manyNines.insertLast(5);

manyNines.insertLast(1);

manyNines.insertLast(9);

manyNines.insertLast(2);

manyNines.insertLast(9);

manyNines.insertLast(9);

ourSort(manyNines.begin(), manyNines.end());

for (auto i : manyNines) {

ss << i << " ";

}

cout << endl;

checkTest("testAlgorithms test #3", "1 2 2 4 5 9 9 9 9 9 9 9 ", ss.str());

ss.str("");

DoublyLinkedList oneItem;

oneItem.insertLast(42);

ourSort(oneItem.begin(), oneItem.end());

for (auto i : oneItem) {

ss << i << " ";

}

cout << endl;

checkTest("testAlgorithms test #4", "42 ", ss.str());

ss.str("");

DoublyLinkedList noItems;

oneItem.insertLast(42);

ourSort(noItems.begin(), noItems.end());

for (auto i : noItems) {

ss << i << " ";

}

cout << endl;

checkTest("testAlgorithms test #5", "", ss.str());

ss.str("");

//while (beginIter != endIter) {

// cout << *beginIter << " ";

// ss << *beginIter << " ";

// ++beginIter;

//}

//cout << endl;

//checkTest("testAlgorithms test #6", "4 2 5 1 2 ", ss.str());

//ss.str("");

*/

}

void pressAnyKeyToContinue() {

cout << "Press any key to continue...";

//Linux and Mac users with g++ don't need this

//But everyone else will see this message.

#ifndef __GNUC__

_getch();

#else

int c;

fflush(stdout);

do c = getchar(); while ((c != ' ') && (c != EOF));

#endif

cout << endl;

}

int main() {

cout << "This first test can run forever until you get operators *, != and ++ implemented." << endl;

pressAnyKeyToContinue();

testIteratorFundamentals();

checkTestMemory("Memory Leak/Allocation Test #1", 0, ManageMemory::getTotalSize());

pressAnyKeyToContinue();

testIteratorIncrement();

checkTestMemory("Memory Leak/Allocation Test #2", 0, ManageMemory::getTotalSize());

pressAnyKeyToContinue();

testIteratorDecrement();

checkTestMemory("Memory Leak/Allocation Test #3", 0, ManageMemory::getTotalSize());

pressAnyKeyToContinue();

testIterationTricky();

checkTestMemory("Memory Leak/Allocation Test #4", 0, ManageMemory::getTotalSize());

pressAnyKeyToContinue();

testAlgorithms();

checkTestMemory("Memory Leak/Allocation Test #5", 0, ManageMemory::getTotalSize());

pressAnyKeyToContinue();

return 0;

}

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!