6.23 Lab*: Doubly-Linked Lists (Park) - Templates
This commit is contained in:
parent
274e3025b1
commit
ef6762ad57
@ -6,4 +6,6 @@ set(CMAKE_CXX_STANDARD 20)
|
|||||||
add_executable(04_dl_lists main.cpp
|
add_executable(04_dl_lists main.cpp
|
||||||
StudentList.cpp
|
StudentList.cpp
|
||||||
LinkedList.cpp
|
LinkedList.cpp
|
||||||
Park.cpp)
|
Park.cpp
|
||||||
|
ListNodeADT.h
|
||||||
|
LinkedListADT.h)
|
||||||
|
219
04-dl-lists/LinkedListADT.h
Normal file
219
04-dl-lists/LinkedListADT.h
Normal 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
47
04-dl-lists/ListNodeADT.h
Normal 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
|
@ -3,9 +3,7 @@
|
|||||||
// Reviewed By: Iurii Tatishchev
|
// Reviewed By: Iurii Tatishchev
|
||||||
// IDE: CLion
|
// IDE: CLion
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Park.h"
|
#include "Park.h"
|
||||||
@ -56,5 +54,16 @@ void Park::vDisplay() const {
|
|||||||
cout << description << endl;
|
cout << description << endl;
|
||||||
cout << state << endl;
|
cout << state << endl;
|
||||||
cout << year << 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;
|
||||||
|
}
|
||||||
|
@ -59,6 +59,18 @@ public:
|
|||||||
void hDdisplay() const;
|
void hDdisplay() const;
|
||||||
|
|
||||||
void vDisplay() 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
|
#endif
|
||||||
|
@ -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.
|
Build and procees a sorted linked list of Park objects.
|
||||||
The list is sorted in ascending order by the Park code, a unique identifier.
|
The list is sorted in ascending order by the Park code, a unique identifier.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
// Written by: Iurii Tatishchev
|
// Written by: Iurii Tatishchev
|
||||||
// Reviewed & Modified by: Iurii Tatishchev
|
// Reviewed & Modified by: Iurii Tatishchev
|
||||||
// IDE: CLion
|
// IDE: CLion
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cctype> // toupper()
|
#include <cctype> // toupper()
|
||||||
#include "LinkedList.h"
|
|
||||||
|
#include "LinkedListADT.h"
|
||||||
|
#include "Park.h"
|
||||||
|
|
||||||
using namespace std;
|
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() {
|
int main() {
|
||||||
|
|
||||||
string inputFileName = "national_parks.txt";
|
string inputFileName = "national_parks.txt";
|
||||||
LinkedList list;
|
LinkedList<Park> list;
|
||||||
|
|
||||||
buildList(inputFileName, list);
|
buildList(inputFileName, list);
|
||||||
displayManager(list);
|
displayManager(list);
|
||||||
@ -43,7 +48,7 @@ int main() {
|
|||||||
This function reads data about national parks from a file and inserts them
|
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.
|
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);
|
ifstream inputFile(filename);
|
||||||
cout << "Reading data from \"" << filename << "\"" << endl;
|
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
|
Delete manager: delete items from the list until the user enters Q to quit
|
||||||
deleting
|
deleting
|
||||||
Input Parameter: list
|
Input & Output Parameter: list
|
||||||
*/
|
*/
|
||||||
void deleteManager(LinkedList &list) {
|
void deleteManager(LinkedList<Park> &list) {
|
||||||
string targetCode;
|
string targetCode;
|
||||||
|
|
||||||
cout << endl << " Delete" << endl;
|
cout << endl << " Delete" << endl;
|
||||||
@ -89,7 +94,9 @@ void deleteManager(LinkedList &list) {
|
|||||||
getline(cin, targetCode);
|
getline(cin, targetCode);
|
||||||
targetCode[0] = toupper(targetCode[0]);
|
targetCode[0] = toupper(targetCode[0]);
|
||||||
if (targetCode != "Q") {
|
if (targetCode != "Q") {
|
||||||
if (list.deleteNode(targetCode))
|
Park target;
|
||||||
|
target.setCode(targetCode);
|
||||||
|
if (list.deleteNode(target))
|
||||||
cout << " " << targetCode << " has been deleted!" << endl;
|
cout << " " << targetCode << " has been deleted!" << endl;
|
||||||
else
|
else
|
||||||
cout << "Park \"" << targetCode << "\" was not found in this list." << endl;
|
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
|
Search manager: search the list until the user enters Q to quit searching
|
||||||
Input Parameter: list
|
Input Parameter: list
|
||||||
*/
|
*/
|
||||||
void searchManager(const LinkedList &list) {
|
void searchManager(const LinkedList<Park> &list) {
|
||||||
string targetCode = "";
|
string targetCode = "";
|
||||||
Park aPark;
|
Park aPark;
|
||||||
|
|
||||||
@ -114,7 +121,9 @@ void searchManager(const LinkedList &list) {
|
|||||||
getline(cin, targetCode);
|
getline(cin, targetCode);
|
||||||
targetCode[0] = toupper(targetCode[0]);
|
targetCode[0] = toupper(targetCode[0]);
|
||||||
if (targetCode != "Q") {
|
if (targetCode != "Q") {
|
||||||
if (list.searchList(targetCode, aPark))
|
Park target;
|
||||||
|
target.setCode(targetCode);
|
||||||
|
if (list.searchList(target, aPark))
|
||||||
aPark.vDisplay();
|
aPark.vDisplay();
|
||||||
else
|
else
|
||||||
cout << "Park \"" << targetCode << "\" was not found in this list." << endl;
|
cout << "Park \"" << targetCode << "\" was not found in this list." << endl;
|
||||||
@ -129,7 +138,7 @@ Display manager:
|
|||||||
- calls the displayListForw()/displayListBack() function upon request
|
- calls the displayListForw()/displayListBack() function upon request
|
||||||
Input Parameter: list
|
Input Parameter: list
|
||||||
*/
|
*/
|
||||||
void displayManager(const LinkedList &list) {
|
void displayManager(const LinkedList<Park> &list) {
|
||||||
string action;
|
string action;
|
||||||
|
|
||||||
cout << "Number of National Parks in this list: " << list.getLength() << endl;
|
cout << "Number of National Parks in this list: " << list.getLength() << endl;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user