1. #ifndef LINKED_LIST_
#define LINKED_LIST_
template
class LinkedList {
private:
std::shared_ptr> headPtr; // Pointer to first node in the chain;
// (contains the first entry in the list)
int itemCount; // Current count of list items
std::shared_ptr> getNodeAt(int position) const;
public:
LinkedList();
LinkedList(const LinkedList& aList);
virtual ~LinkedList();
bool isEmpty() const;
int getLength() const;
bool insert(int newPosition, const ItemType& newEntry);
bool remove(int position);
void clear();
/** throw PrecondViolatedExcept if position < 1 or
position > getLength(). */
ItemType getEntry(int position) const throw(PrecondViolatedExcept);
/** throw PrecondViolatedExcept if position < 1 or
position > getLength(). */
void replace(int position, const ItemType& newEntry)
throw(PrecondViolatedExcept);
// Operator Overloading
void operator = (const LinkedList& arg);
friend std::ostream& operator << (std::ostream& os, const LinkedList& arg)
{
os << "There are " << arg.getLength() << " values in the list:" << std::endl;
for (int i{ 1 }; i <= arg.getLength(); i++) {
2. os << arg.getEntry(i) << std::endl;
}
os << std::endl << std::endl << std::endl << std::endl;
return os;
}
};
// Returns a pointer to the Node at the given position.
template
std::shared_ptr> LinkedList::getNodeAt (int position) const {
std::shared_ptr> currPtr{ headPtr };
for (int i{ 1 }; i < position; i++)
currPtr = currPtr->getNext();
return currPtr;
}
// Default constructor.
template
LinkedList::LinkedList() {
headPtr = nullptr;
itemCount = 0;
}
// Copy constructor.
template
LinkedList::LinkedList(const LinkedList& aList) {
itemCount = aList.getLength();
auto currPtr{ aList.headPtr };
auto newNodePtr{ headPtr = std::make_shared>(currPtr->getItem()) };
auto prevNodePtr{ newNodePtr };
currPtr = currPtr->getNext();
for (int i{ 2 }; i <= itemCount; i++) {
newNodePtr = std::make_shared>(currPtr->getItem());
prevNodePtr->setNext(newNodePtr);
prevNodePtr = newNodePtr;
currPtr = currPtr->getNext();
}
}
// Destructor.
3. template
LinkedList::~LinkedList() {
headPtr = nullptr;
itemCount = 0;
}
// Accessor/Info Functions.
template
bool LinkedList::isEmpty() const {
return (itemCount > 0)?0:1;
}
template
int LinkedList::getLength() const {
return itemCount;
}
// Places a Node at a given position (element at the same position is now pos+1).
template
bool LinkedList::insert(const int newPosition,
const ItemType& newEntry)
{
bool ableToInsert{ (newPosition >= 1) &&
(newPosition <= itemCount + 1) };
if (ableToInsert)
{
// Create a new node containing the new entry
auto newNodePtr{ std::make_shared>(newEntry) };
// Attach new node to chain
if (newPosition == 1)
{
// Insert new node at beginning of chain
newNodePtr->setNext(headPtr);
headPtr = newNodePtr;
}
else
{
// Find node that will be before new node
4. auto prevPtr{ getNodeAt(newPosition - 1) };
// Insert new node after node to which prevPtr points
newNodePtr->setNext(prevPtr->getNext());
prevPtr->setNext(newNodePtr);
} // end if
itemCount++; // Increase count of entries
} // end if
return ableToInsert;
} // end insert
// Removes the Node at the given position.
template
bool LinkedList::remove(const int position)
{
bool ableToRemove = (position >= 1) && (position <= itemCount);
if (ableToRemove)
{
if (position == 1)
{
// Remove the first node in the chain
headPtr = headPtr->getNext();
}
else
{
// Find node that is before the one to delete
auto prevPtr{ getNodeAt(position - 1) };
// Point to node to delete
auto curPtr{ prevPtr->getNext() };
// Disconnect indicated node from chain by connecting the
// prior node with the one after
prevPtr->setNext(curPtr->getNext());
} // end if
5. itemCount--; // Decrease count of entries
} // end if
return ableToRemove;
} // end remove
// Replaces the Entry in the given Node with the new Entry.
template
void LinkedList::replace(const int position, const ItemType& newEntry)
throw(PrecondViolatedExcept)
{
if (position > this->getLength() || position < 1)
throw PrecondViolatedExcept("replace() called with a position out of bounds.");
else
getNodeAt(position)->setItem(newEntry);
}
template
void LinkedList::clear()
{
headPtr = nullptr;
itemCount = 0;
} // end clear
template
ItemType LinkedList::getEntry(int position) const throw(PrecondViolatedExcept)
{
if (position > this->getLength() || position < 1)
throw PrecondViolatedExcept("getEntry() called with a position out of bounds.");
else
return getNodeAt(position)->getItem();
}
// Makes the calling Linked List's entries the same as the given Linked List.
template
void LinkedList::operator = (const LinkedList& arg) {
if (arg.isEmpty())
return;
// First section copies the given list into the calling list's existing nodes.
6. bool isThisLarger{ this->itemCount >= arg.itemCount };
auto currThisPtr{ this->headPtr };
auto currArgPtr{ arg.headPtr };
if (!this->isEmpty())
{
currThisPtr->setItem(currArgPtr->getItem());
for (int i = 2; i <= ((isThisLarger) ? arg.itemCount : this->itemCount); i++) {
currThisPtr = currThisPtr->getNext();
currArgPtr = currArgPtr->getNext();
currThisPtr->setItem(currArgPtr->getItem());
}
// If the calling list is larger then tidy up the end.
if (isThisLarger) {
this->itemCount = arg.itemCount;
currThisPtr->setNext(nullptr);
}
}
// Create new nodes and/or finish copying the entries.
if (!isThisLarger) {
currArgPtr = currArgPtr->getNext();
auto newNodePtr{ std::make_shared>(currArgPtr->getItem()) };
auto prevNodePtr{ currThisPtr };
prevNodePtr->setNext(newNodePtr);
if (this->isEmpty())
this->headPtr = newNodePtr;
for (int i = this->itemCount+1; i <= arg.itemCount; i++) {
newNodePtr = std::make_shared>(currArgPtr->getItem());
prevNodePtr->setNext(newNodePtr);
prevNodePtr = newNodePtr;
currArgPtr = currArgPtr->getNext();
}
this->itemCount = arg.itemCount;
7. }
}
#endif
Solution
#ifndef LINKED_LIST_
#define LINKED_LIST_
template
class LinkedList {
private:
std::shared_ptr> headPtr; // Pointer to first node in the chain;
// (contains the first entry in the list)
int itemCount; // Current count of list items
std::shared_ptr> getNodeAt(int position) const;
public:
LinkedList();
LinkedList(const LinkedList& aList);
virtual ~LinkedList();
bool isEmpty() const;
int getLength() const;
bool insert(int newPosition, const ItemType& newEntry);
bool remove(int position);
void clear();
/** throw PrecondViolatedExcept if position < 1 or
position > getLength(). */
ItemType getEntry(int position) const throw(PrecondViolatedExcept);
/** throw PrecondViolatedExcept if position < 1 or
position > getLength(). */
void replace(int position, const ItemType& newEntry)
throw(PrecondViolatedExcept);
// Operator Overloading
8. void operator = (const LinkedList& arg);
friend std::ostream& operator << (std::ostream& os, const LinkedList& arg)
{
os << "There are " << arg.getLength() << " values in the list:" << std::endl;
for (int i{ 1 }; i <= arg.getLength(); i++) {
os << arg.getEntry(i) << std::endl;
}
os << std::endl << std::endl << std::endl << std::endl;
return os;
}
};
// Returns a pointer to the Node at the given position.
template
std::shared_ptr> LinkedList::getNodeAt (int position) const {
std::shared_ptr> currPtr{ headPtr };
for (int i{ 1 }; i < position; i++)
currPtr = currPtr->getNext();
return currPtr;
}
// Default constructor.
template
LinkedList::LinkedList() {
headPtr = nullptr;
itemCount = 0;
}
// Copy constructor.
template
LinkedList::LinkedList(const LinkedList& aList) {
itemCount = aList.getLength();
auto currPtr{ aList.headPtr };
auto newNodePtr{ headPtr = std::make_shared>(currPtr->getItem()) };
auto prevNodePtr{ newNodePtr };
currPtr = currPtr->getNext();
for (int i{ 2 }; i <= itemCount; i++) {
newNodePtr = std::make_shared>(currPtr->getItem());
prevNodePtr->setNext(newNodePtr);
9. prevNodePtr = newNodePtr;
currPtr = currPtr->getNext();
}
}
// Destructor.
template
LinkedList::~LinkedList() {
headPtr = nullptr;
itemCount = 0;
}
// Accessor/Info Functions.
template
bool LinkedList::isEmpty() const {
return (itemCount > 0)?0:1;
}
template
int LinkedList::getLength() const {
return itemCount;
}
// Places a Node at a given position (element at the same position is now pos+1).
template
bool LinkedList::insert(const int newPosition,
const ItemType& newEntry)
{
bool ableToInsert{ (newPosition >= 1) &&
(newPosition <= itemCount + 1) };
if (ableToInsert)
{
// Create a new node containing the new entry
auto newNodePtr{ std::make_shared>(newEntry) };
// Attach new node to chain
if (newPosition == 1)
{
// Insert new node at beginning of chain
newNodePtr->setNext(headPtr);
10. headPtr = newNodePtr;
}
else
{
// Find node that will be before new node
auto prevPtr{ getNodeAt(newPosition - 1) };
// Insert new node after node to which prevPtr points
newNodePtr->setNext(prevPtr->getNext());
prevPtr->setNext(newNodePtr);
} // end if
itemCount++; // Increase count of entries
} // end if
return ableToInsert;
} // end insert
// Removes the Node at the given position.
template
bool LinkedList::remove(const int position)
{
bool ableToRemove = (position >= 1) && (position <= itemCount);
if (ableToRemove)
{
if (position == 1)
{
// Remove the first node in the chain
headPtr = headPtr->getNext();
}
else
{
// Find node that is before the one to delete
auto prevPtr{ getNodeAt(position - 1) };
// Point to node to delete
auto curPtr{ prevPtr->getNext() };
11. // Disconnect indicated node from chain by connecting the
// prior node with the one after
prevPtr->setNext(curPtr->getNext());
} // end if
itemCount--; // Decrease count of entries
} // end if
return ableToRemove;
} // end remove
// Replaces the Entry in the given Node with the new Entry.
template
void LinkedList::replace(const int position, const ItemType& newEntry)
throw(PrecondViolatedExcept)
{
if (position > this->getLength() || position < 1)
throw PrecondViolatedExcept("replace() called with a position out of bounds.");
else
getNodeAt(position)->setItem(newEntry);
}
template
void LinkedList::clear()
{
headPtr = nullptr;
itemCount = 0;
} // end clear
template
ItemType LinkedList::getEntry(int position) const throw(PrecondViolatedExcept)
{
if (position > this->getLength() || position < 1)
throw PrecondViolatedExcept("getEntry() called with a position out of bounds.");
else
return getNodeAt(position)->getItem();
}
// Makes the calling Linked List's entries the same as the given Linked List.
12. template
void LinkedList::operator = (const LinkedList& arg) {
if (arg.isEmpty())
return;
// First section copies the given list into the calling list's existing nodes.
bool isThisLarger{ this->itemCount >= arg.itemCount };
auto currThisPtr{ this->headPtr };
auto currArgPtr{ arg.headPtr };
if (!this->isEmpty())
{
currThisPtr->setItem(currArgPtr->getItem());
for (int i = 2; i <= ((isThisLarger) ? arg.itemCount : this->itemCount); i++) {
currThisPtr = currThisPtr->getNext();
currArgPtr = currArgPtr->getNext();
currThisPtr->setItem(currArgPtr->getItem());
}
// If the calling list is larger then tidy up the end.
if (isThisLarger) {
this->itemCount = arg.itemCount;
currThisPtr->setNext(nullptr);
}
}
// Create new nodes and/or finish copying the entries.
if (!isThisLarger) {
currArgPtr = currArgPtr->getNext();
auto newNodePtr{ std::make_shared>(currArgPtr->getItem()) };
auto prevNodePtr{ currThisPtr };
prevNodePtr->setNext(newNodePtr);
if (this->isEmpty())
this->headPtr = newNodePtr;
for (int i = this->itemCount+1; i <= arg.itemCount; i++) {
newNodePtr = std::make_shared>(currArgPtr->getItem());