Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

C++ format, if you can complete the extra credit functions that would be nice. B

ID: 3703854 • Letter: C

Question

C++ format, if you can complete the extra credit functions that would be nice. Below are the starter codes.

LList.h

#ifndef LLIST_H
#define LLIST_H

/*
Linked List class that store integers, with [] operator.
Uses head pointer.
*/
#include <ostream>
#include <stdexcept>

#define int int

using namespace std;

struct node_t {
int data;
node_t* next;
};

// This implementation will use a head pointer,
// allowing O(1) insertion on the front,
// and O(n) on the end.
class LList {

public:
LList(){
head = NULL;
}

~LList(){
clear();
}

LList(const LList& other){
// Do the same as the default constructor
head = NULL;
// Check if the other LList is empty
if(other.head == NULL){
return;
}
// Not empty? Iterate through the other list
// and push_back on myself.
node_t* temp = other.head;
while(temp){
push_back(temp->data);
temp = temp->next;
}
}

// Similar to copy constructor, but check for self
// assignment, if not, clear and copy all data.
LList& operator= (const LList& other){
if(this == &other){
return *this;
}
clear();
if(other.head == NULL){
return *this;
}
node_t* temp = other.head;
while(temp){
push_back(temp->data);
temp = temp->next;
}
return *this;
}


bool empty() const {
// TODO: Fill me in
}

unsigned int size() const {
// TODO: Fill me in
}

void push_back(int value){
// TODO: Fill me in
}

void push_front(int value){
// Empty list?
if(head == NULL){
head = new node_t;
head->data = value;
head->next = NULL;
}else{ // Not empty
node_t* temp = new node_t;
temp->data = value;
temp->next = head;
head = temp;
}
}

void pop_front(){
if(head == NULL) return;
node_t* temp = head;
head = head->next;
delete temp;
}

void pop_back(){
// TODO: Fill me in
}


// Overload [] operator
// Return logic error if index out of bounds
int& operator[](unsigned pos){
node_t* temp = head;
while(temp != NULL && pos > 0){
temp = temp->next;
pos--;
}
// As long as I don't have a null pointer, assign.
if(pos == 0 && temp != NULL){
return temp->data;
}
throw logic_error("Index invalid");
}

LList reverse() const {
// TODO: Fill me in
return LList(); // Remove me!
}

bool operator==(const LList& other) const {
}

bool operator!=(const LList& other) const {
return !operator==(other);
}

void clear(){
node_t* last = head;
while(head){
head = head->next;
delete last;
last = head;
}
// Normaly you never want to change head or you'll orphan part
// of the list, but in this case we are wiping the list,
// so it is ok to so and saves us a variable.
head = NULL;
}

private:
node_t* head;

};

// Note this function is O(n^2) because getAt is O(n) and we are
// doing it n times.

ostream& operator<<(ostream& out, const LList other){
out << "[";
for(unsigned int i = 1; i < other.size(); i++){
out << other.getAt(i-1) << ", ";
}
if(other.size() > 0){
out << other.getAt(other.size() - 1);
}
out << "]";
return out;
}

#endif

#ifndef LLIST_H
#define LLIST_H

/*
Linked List class that store integers, with [] operator.
Uses head pointer.
*/
#include <ostream>
#include <stdexcept>

#define int int

using namespace std;

struct node_t {
int data;
node_t* next;
};

// This implementation will use a head pointer,
// allowing O(1) insertion on the front,
// and O(n) on the end.
class LList {

public:
LList(){
head = NULL;
}

~LList(){
clear();
}

LList(const LList& other){
// Do the same as the default constructor
head = NULL;
// Check if the other LList is empty
if(other.head == NULL){
return;
}
// Not empty? Iterate through the other list
// and push_back on myself.
node_t* temp = other.head;
while(temp){
push_back(temp->data);
temp = temp->next;
}
}

// Similar to copy constructor, but check for self
// assignment, if not, clear and copy all data.
LList& operator= (const LList& other){
if(this == &other){
return *this;
}
clear();
if(other.head == NULL){
return *this;
}
node_t* temp = other.head;
while(temp){
push_back(temp->data);
temp = temp->next;
}
return *this;
}


bool empty() const {
// TODO: Fill me in
}

unsigned int size() const {
// TODO: Fill me in
}

void push_back(int value){
// TODO: Fill me in
}

void push_front(int value){
// Empty list?
if(head == NULL){
head = new node_t;
head->data = value;
head->next = NULL;
}else{ // Not empty
node_t* temp = new node_t;
temp->data = value;
temp->next = head;
head = temp;
}
}

void pop_front(){
if(head == NULL) return;
node_t* temp = head;
head = head->next;
delete temp;
}

void pop_back(){
// TODO: Fill me in
}


// Overload [] operator
// Return logic error if index out of bounds
int& operator[](unsigned pos){
node_t* temp = head;
while(temp != NULL && pos > 0){
temp = temp->next;
pos--;
}
// As long as I don't have a null pointer, assign.
if(pos == 0 && temp != NULL){
return temp->data;
}
throw logic_error("Index invalid");
}

LList reverse() const {
// TODO: Fill me in
return LList(); // Remove me!
}

bool operator==(const LList& other) const {
}

bool operator!=(const LList& other) const {
return !operator==(other);
}

void clear(){
node_t* last = head;
while(head){
head = head->next;
delete last;
last = head;
}
// Normaly you never want to change head or you'll orphan part
// of the list, but in this case we are wiping the list,
// so it is ok to so and saves us a variable.
head = NULL;
}

private:
node_t* head;

};

// Note this function is O(n^2) because getAt is O(n) and we are
// doing it n times.

ostream& operator<<(ostream& out, const LList other){
out << "[";
for(unsigned int i = 1; i < other.size(); i++){
out << other.getAt(i-1) << ", ";
}
if(other.size() > 0){
out << other.getAt(other.size() - 1);
}
out << "]";
return out;
}

#endif

list-sandbox.cpp

/*
Fill me in
*/

#include <iostream>
#include <vector>

#include "LList.h"

using namespace std;

int main(){
LList a;
for(int i = 0; i < 50; i++){
a.push_front(45);
}

return 0;
}

Part B: Linked Lists Task1: Modify LList.h to implement the functions or operator overloading listed below. Most of the functions are stubbed out so you just need to add the proper logic. You will be editing the LList.h file and compiling the sandbox file. Here is a list of the required methods you must fill in: LList.h push back (int) - Place the given value on the end of the linked-list reverse() const - Return a new linked-list which is the current one reversed » » · size ( ) -Returns the size (length) of the linked-list * pop_back () - Removes the last element of the linked-list. If the list is empty · operator-= (LL1 st R) -Return true if the current linked-list contains » Overload the plus (+) operator to add two lists together » emptyO - Return true if the list is empty otherwise return false. do nothing identical values to the passed one Extra Credit: 10-Points Eaclh getAt (unsigned) -Return the value at the given position, or throw a logic error if the index is invalid. See the overloaded [] operator for hints on how to throw an exception · . setAt (int, unsigned) Assign the given value to the given position (0-based). Throw a logic error if the index is invalid You can use list-sandbox. cpp to experiment with the linked-list classes. Compile list-sandbox.cpp toa list-sandbox executable. List-sandbox.cpp will not be graded Tip for Testing: Use the list-sandbox.cpp to create linked list objects and also test out your various list modifying functions. LList.h has a definition for overloaded

Explanation / Answer

Given below is the modified code for the question.
Please do rate the answer if it was helpful. Thank you

LList.h
=======
#ifndef LLIST_H
#define LLIST_H

/*
Linked List class that store integers, with [] operator.
Uses head pointer.
*/
#include <ostream>
#include <stdexcept>

#define int int

using namespace std;

struct node_t {
int data;
node_t* next;
};

// This implementation will use a head pointer,
// allowing O(1) insertion on the front,
// and O(n) on the end.
class LList {

public:
LList(){
head = NULL;
}

~LList(){
clear();
}

LList(const LList& other){
// Do the same as the default constructor
head = NULL;
// Check if the other LList is empty
if(other.head == NULL){
return;
}
// Not empty? Iterate through the other list
// and push_back on myself.
node_t* temp = other.head;
while(temp){
push_back(temp->data);
temp = temp->next;
}
}

// Similar to copy constructor, but check for self
// assignment, if not, clear and copy all data.
LList& operator= (const LList& other){
if(this == &other){
return *this;
}
clear();
if(other.head == NULL){
return *this;
}
node_t* temp = other.head;
while(temp){
push_back(temp->data);
temp = temp->next;
}
return *this;
}


bool empty() const {
return head == NULL;
}

unsigned int size() const {
node_t* temp = head;
int sz = 0;
while(temp != NULL)
{
sz++;
temp = temp->next;
}
return sz;
}

void push_back(int value){
node_t* n = new node_t;
n->data = value;
n->next = NULL;
if(head == NULL)
head = n;
else
{
node_t *last = head;
while(last->next != NULL)
last = last->next;

last->next = n;
}

}

void push_front(int value){
// Empty list?
if(head == NULL){
head = new node_t;
head->data = value;
head->next = NULL;
}else{ // Not empty
node_t* temp = new node_t;
temp->data = value;
temp->next = head;
head = temp;
}
}

void pop_front(){
if(head == NULL) return;
node_t* temp = head;
head = head->next;
delete temp;
}

void pop_back(){
node_t *prev2Last = NULL, *last = head;

if(empty())
return;

while(last->next != NULL)
{
prev2Last = last;
last = last->next;
}

if(prev2Last != NULL)
prev2Last->next = NULL;
else
head = NULL;

delete last;
}


// Overload [] operator
// Return logic error if index out of bounds
int& operator[](unsigned pos){
node_t* temp = head;
while(temp != NULL && pos > 0){
temp = temp->next;
pos--;
}
// As long as I don't have a null pointer, assign.
if(pos == 0 && temp != NULL){
return temp->data;
}
throw logic_error("Index invalid");
}

LList reverse() const {

node_t* temp = head;
LList rev;
while(temp != NULL)
{
rev.push_front(temp->data);
temp = temp->next;
}
return rev;
}

bool operator==(const LList& other) const {

node_t *n1 = head, *n2 = other.head;

while(n1 != NULL && n2 != NULL)
{
if(n1->data != n2->data)
return false;

n1 = n1->next;
n2 = n2->next;
}
if(n1 == NULL && n2 == NULL)
return true;
else
return false;
}

bool operator!=(const LList& other) const {
return !operator==(other);
}

int getAt(unsigned pos) const
{
node_t* temp = head;
while(temp != NULL && pos > 0){
temp = temp->next;
pos--;
}
// As long as I don't have a null pointer, assign.
if(pos == 0 && temp != NULL){
return temp->data;
}
throw logic_error("Index invalid");
}

void clear(){
node_t* last = head;
while(head){
head = head->next;
delete last;
last = head;
}
// Normaly you never want to change head or you'll orphan part
// of the list, but in this case we are wiping the list,
// so it is ok to so and saves us a variable.
head = NULL;
}

private:
node_t* head;

};

// Note this function is O(n^2) because getAt is O(n) and we are
// doing it n times.

ostream& operator<<(ostream& out, const LList &other){
out << "[";
for(unsigned int i = 1; i < other.size(); i++){
out << other.getAt(i-1) << ", ";
}
if(other.size() > 0){
out << other.getAt(other.size() - 1);
}
out << "]";
return out;
}

#endif

listsandbox.cpp
=========

#include <iostream>
#include <vector>

#include "LList.h"

using namespace std;

int main(){
LList a;

cout << "a.size() = " << a.size() << endl;
cout << "a.empty() = " << a.empty() << endl;

cout << "pushing to front 1 to 5 " << endl;
for(int i = 1; i <= 5; i++)
a.push_front(i);

cout << "list a: " << a << endl;

cout << "pushing to back 6 to 10 " << endl;
for(int i = 6; i <= 10; i++)
a.push_back(i);

cout << "list a: " << a << endl;
cout << "a.size() = " << a.size() << endl;
cout << "a.empty() = " << a.empty() << endl;

LList b = a;
cout << "list b: " << b << endl;

if(a == b)
cout << "list a and b are equal" << endl;
else
cout << "list a and b are NOT equal" << endl;

LList c = a.reverse();
cout << "list c = reverse of a: " << c << endl;

if(a != c)
cout << "list a and c are NOT equal" << endl;
else
cout << "list a and c are equal" << endl;

cout << "adding 2 to each element of list c, using [] operator" << endl;
for(int i = 0 ; i< c.size(); i++)
c[i] = c[i] + 2;

cout << "list c: " << c << endl;

cout << "popping back all elements in list c" << endl;
while(!c.empty())
c.pop_back();

cout << "list c: " << c << endl;
return 0;
}


output
======
a.size() = 0
a.empty() = 1
pushing to front 1 to 5
list a: [5, 4, 3, 2, 1]
pushing to back 6 to 10
list a: [5, 4, 3, 2, 1, 6, 7, 8, 9, 10]
a.size() = 10
a.empty() = 0
list b: [5, 4, 3, 2, 1, 6, 7, 8, 9, 10]
list a and b are equal
list c = reverse of a: [10, 9, 8, 7, 6, 1, 2, 3, 4, 5]
list a and c are NOT equal
adding 2 to each element of list c, using [] operator
list c: [12, 11, 10, 9, 8, 3, 4, 5, 6, 7]
popping back all elements in list c
list c: []

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote