6.23 Lab*: Doubly-Linked Lists (Park) - Templates

This commit is contained in:
Iurii Tatishchev 2024-04-28 13:51:08 -07:00
parent 274e3025b1
commit ef6762ad57
Signed by: CaZzzer
GPG Key ID: 9A156B7DA6398968
6 changed files with 317 additions and 19 deletions

View File

@ -6,4 +6,6 @@ set(CMAKE_CXX_STANDARD 20)
add_executable(04_dl_lists main.cpp
StudentList.cpp
LinkedList.cpp
Park.cpp)
Park.cpp
ListNodeADT.h
LinkedListADT.h)

219
04-dl-lists/LinkedListADT.h Normal file
View File

@ -0,0 +1,219 @@
// Specification file for the LinkedList class
// Written By: Iurii Tatishchev
// Reviewed & Modified by: Iurii Tatishchev
// IDE: CLion
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
#include "ListNodeADT.h"
template<class T>
class LinkedList {
private:
ListNode<T> *head;
int length;
public:
LinkedList(); // constructor
~LinkedList(); // destructor
// Linked list operations
int getLength() const { return length; }
bool isEmpty() const { return length == 0; }
void insertNode(const T &);
bool deleteNode(const T &);
void displayListForw() const;
void displayListBack() const;
bool searchList(const T &, T &) const;
};
// **************************************************
// Constructor
// This function allocates and initializes a sentinel node
// A sentinel (or dummy) node is an extra node added before the first data record.
// This convention simplifies and accelerates some list-manipulation algorithms,
// by making sure that all links can be safely dereferenced and that every list
// (even one that contains no data elements) always has a "first" node.
// **************************************************
template<class T>
LinkedList<T>::LinkedList() {
head = new ListNode<T>; // head points to the sentinel node
head->setNext(head);
head->setPrev(head);
length = 0;
}
// **************************************************
// The insertNode function inserts a new node in a
// sorted linked list
// **************************************************
template<class T>
void LinkedList<T>::insertNode(const T &dataIn) {
ListNode<T> *newNode; // A new node
ListNode<T> *pCur; // To traverse the list
ListNode<T> *pPre; // The previous node
// Allocate a new node and store dataIn there.
newNode = new ListNode<T>(dataIn);
// Initialize pointers
pCur = head->getNext();
// Find location: skip all nodes whose code is less than dataIn's code
// while (pCur != head && newNode->getData().getCode() > pCur->getData().getCode())
while (pCur != head && newNode->getData() > pCur->getData()) {
pCur = pCur->getNext();
}
// Insert the new node between pPre and pCur
pPre = pCur->getPrev();
pPre->setNext(newNode);
newNode->setNext(pCur);
newNode->setPrev(pPre);
pCur->setPrev(newNode);
// Update the counter
length++;
}
// **************************************************
// The deleteNode function searches for a node
// in a sorted linked list; if found, the node is
// deleted from the list and from memory.
// **************************************************
//bool LinkedList::deleteNode(string target)
template<class T>
bool LinkedList<T>::deleteNode(const T &target) {
ListNode<T> *pCur; // To traverse the list
ListNode<T> *pPre; // To point to the previous node
bool deleted = false;
// Initialize pointers
pCur = head->getNext();
// Find node containing the target: Skip all nodes whose gpa is less than the target
while (pCur != head && pCur->getData() < target) {
pCur = pCur->getNext();
}
// If found, delete the node
if (pCur->getData() == target) {
pPre = pCur->getPrev();
pPre->setNext(pCur->getNext()); // Set next of prev
pCur->getNext()->setPrev(pPre); // Set prev of next
delete pCur;
deleted = true;
length--;
}
return deleted;
}
// **************************************************
// displayList shows the value
// stored in each node of the linked list
// pointed to by head, except the sentinel node
// **************************************************
template<class T>
void LinkedList<T>::displayListForw() const {
ListNode<T> *pCur; // To move through the list
// Position pCur: skip the head of the list.
pCur = head->getNext();
// While pCur points to a node, traverse the list.
while (pCur != head) {
// Display the value in this node.
std::cout << pCur->getData();
// Move to the next node.
pCur = pCur->getNext();
}
std::cout << std::endl;
}
// **************************************************
// displayList shows the value
// stored in each node of the linked list
// pointed to by head, except the sentinel node
// **************************************************
template<class T>
void LinkedList<T>::displayListBack() const {
ListNode<T> *pCur; // To move through the list
// Position pCur: skip the head of the list.
pCur = head->getPrev();
// While pCur points to a node, traverse the list.
while (pCur != head) {
// Display the value in this node.
std::cout << pCur->getData();
// Move to the next node.
pCur = pCur->getPrev();
}
std::cout << std::endl;
}
// **************************************************
// The searchList function looks for a target college
// in the sorted linked list: if found, returns true
// and copies the data in that node to the output parameter
// **************************************************
template<class T>
bool LinkedList<T>::searchList(const T &target, T &dataOut) const {
bool found = false; // assume target not found
ListNode<T> *pCur; // To move through the list
// Position pCur: skip the head of the list.
pCur = head->getNext();
// Find location: skip all nodes whose code is less than target
while (pCur != head && pCur->getData() < target) {
pCur = pCur->getNext();
}
// If found, copy data to the output parameter, and change the flag to true
if (pCur != head && pCur->getData() == target) {
dataOut = pCur->getData();
found = true;
}
return found;
}
// **************************************************
// Destructor
// This function deletes every node in the list.
// **************************************************
template<class T>
LinkedList<T>::~LinkedList() {
ListNode<T> *pCur; // To traverse the list
ListNode<T> *pNext; // To hold the address of the next node
// Position nodePtr: skip the head of the list
pCur = head->getNext();
// While pCur is not at the end of the list...
while (pCur != head) {
// Save a pointer to the next node.
pNext = pCur->getNext();
// Delete the current node.
delete pCur;
// Position pCur at the next node.
pCur = pNext;
}
delete head; // delete the sentinel node
}
#endif

47
04-dl-lists/ListNodeADT.h Normal file
View File

@ -0,0 +1,47 @@
// Specification file for the ListNode class
// Written by: Iurii Tatishchev
// Reviewed & Modified by: Iurii Tatishchev
// IDE: CLion
#ifndef LISTNODE_H
#define LISTNODE_H
#include <iostream>
// #include "Park.h"
// ^^^ not included here anymore
template<class T>
class ListNode {
private:
T data; // store data
ListNode *forw; // a pointer to the next node in the list
ListNode *back; // a pointer to the previous node in the list
public:
//Constructor
ListNode() { forw = back = nullptr; }
ListNode(const T &dataIn, ListNode *forw = nullptr, ListNode *back = nullptr) {
data = dataIn;
this->forw = forw;
this->back = back;
}
// setters
// set the data
void setData(const T &dataIn) { data = dataIn; }
// set the forw pointer
void setNext(ListNode *nextPtr) { forw = nextPtr; }
// set the back pointer
void setPrev(ListNode *prevPtr) { back = prevPtr; }
// getters
// return data object in the listnode
T& getData() { return data; }
// return pointer in the next node
ListNode *getNext() const { return forw; }
// return pointer in the previous node
ListNode *getPrev() const { return back; }
};
#endif

View File

@ -3,9 +3,7 @@
// Reviewed By: Iurii Tatishchev
// IDE: CLion
#include <iostream>
#include <iomanip>
#include <string>
#include "Park.h"
@ -56,5 +54,16 @@ void Park::vDisplay() const {
cout << description << endl;
cout << state << endl;
cout << year << endl;
}
/* overloaded operators
* - the stream insertion operator ( << ) based on hDisplay
*/
ostream &operator<<(ostream &out, const Park &park) {
out << park.code << " ";
out << park.state << " ";
out << park.year << " ";
out << park.name << " \n";
return out;
}

View File

@ -59,6 +59,18 @@ public:
void hDdisplay() const;
void vDisplay() const;
/* overloaded operators
- the stream insertion operator ( << )
- the relational operators (<, >, == )
*/
friend std::ostream &operator<<(std::ostream &out, const Park &park);
bool operator<(const Park &park) const { return code < park.code; }
bool operator>(const Park &park) const { return code > park.code; }
bool operator==(const Park &park) const { return code == park.code; }
};
#endif

View File

@ -1,35 +1,40 @@
/*
Sorted Circular Doubly-Linked List with Sentinel Node
CIS 22C: Homework 4
Sorted Circular Doubly-Linked List ADT with Sentinel Node
Build and procees a sorted linked list of Park objects.
The list is sorted in ascending order by the Park code, a unique identifier.
*/
// Written by: Iurii Tatishchev
// Reviewed & Modified by: Iurii Tatishchev
// IDE: CLion
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cctype> // toupper()
#include "LinkedList.h"
#include "LinkedListADT.h"
#include "Park.h"
using namespace std;
void buildList(const string &filename, LinkedList &list);
void buildList(const string &filename, LinkedList<Park> &list);
void deleteManager(LinkedList &list);
void deleteManager(LinkedList<Park> &list);
void searchManager(const LinkedList &list);
void searchManager(const LinkedList<Park> &list);
void displayManager(const LinkedList &list);
void displayManager(const LinkedList<Park> &list);
int main() {
string inputFileName = "national_parks.txt";
LinkedList list;
LinkedList<Park> list;
buildList(inputFileName, list);
displayManager(list);
@ -43,7 +48,7 @@ int main() {
This function reads data about national parks from a file and inserts them
into a sorted linked list. The list is sorted in ascending order by code.
*/
void buildList(const string &filename, LinkedList &list) {
void buildList(const string &filename, LinkedList<Park> &list) {
ifstream inputFile(filename);
cout << "Reading data from \"" << filename << "\"" << endl;
@ -76,9 +81,9 @@ void buildList(const string &filename, LinkedList &list) {
/*
Delete manager: delete items from the list until the user enters Q to quit
deleting
Input Parameter: list
Input & Output Parameter: list
*/
void deleteManager(LinkedList &list) {
void deleteManager(LinkedList<Park> &list) {
string targetCode;
cout << endl << " Delete" << endl;
@ -89,7 +94,9 @@ void deleteManager(LinkedList &list) {
getline(cin, targetCode);
targetCode[0] = toupper(targetCode[0]);
if (targetCode != "Q") {
if (list.deleteNode(targetCode))
Park target;
target.setCode(targetCode);
if (list.deleteNode(target))
cout << " " << targetCode << " has been deleted!" << endl;
else
cout << "Park \"" << targetCode << "\" was not found in this list." << endl;
@ -102,7 +109,7 @@ void deleteManager(LinkedList &list) {
Search manager: search the list until the user enters Q to quit searching
Input Parameter: list
*/
void searchManager(const LinkedList &list) {
void searchManager(const LinkedList<Park> &list) {
string targetCode = "";
Park aPark;
@ -114,7 +121,9 @@ void searchManager(const LinkedList &list) {
getline(cin, targetCode);
targetCode[0] = toupper(targetCode[0]);
if (targetCode != "Q") {
if (list.searchList(targetCode, aPark))
Park target;
target.setCode(targetCode);
if (list.searchList(target, aPark))
aPark.vDisplay();
else
cout << "Park \"" << targetCode << "\" was not found in this list." << endl;
@ -129,7 +138,7 @@ Display manager:
- calls the displayListForw()/displayListBack() function upon request
Input Parameter: list
*/
void displayManager(const LinkedList &list) {
void displayManager(const LinkedList<Park> &list) {
string action;
cout << "Number of National Parks in this list: " << list.getLength() << endl;