I am wanting to insert nodes according to their location year and month. So basically all locations are clumped together and then they are sorted according to the year and the months. Below is the code in my linkedlist.cpp file. My insert function I believe is the main cause of my issues. When I use the overload operator to print the list and then the copied list, it is only printing one of the inserted nodes.
#include <iostream>
#include <string>
#include <vector>
#include "linkedlist.h"
using namespace std;
LinkedList::LinkedList() : head(nullptr), tail(nullptr){
// Implement this function
}
LinkedList::~LinkedList() {
// Implement this function
this->clear();
}
LinkedList::LinkedList(const LinkedList& source) {
// Implement this function
head = nullptr;
tail = nullptr;
Node* tempNode = source.head;
while(tempNode != nullptr) {
insert(tempNode->loc, tempNode->yr, tempNode->mo, tempNode->temp);
tempNode = tempNode->next;
}
}
LinkedList& LinkedList::operator=(const LinkedList& source) {
if (this != &source) {
this->clear();
Node* tempNode = source.head;
while(tempNode != nullptr){
insert(tempNode->loc, tempNode->yr, tempNode->mo, tempNode->temp);
tempNode = tempNode->next;
}
}
return *this;
}
void LinkedList::insert(int location, int year, int month, double temperature) {
// Implement this function
Node* newNode = new Node();
newNode->loc = location;
newNode->yr = year;
newNode->mo = month;
newNode->temp = temperature;
Node* tempNode = head;
if(tail == nullptr & head == nullptr){
newNode = head;
}
while(tempNode != nullptr){
if((tempNode->loc == newNode->loc) && (tempNode->yr == newNode->yr)){
if(tempNode->mo > newNode->mo){
newNode->next = tempNode->next;
tempNode->next = newNode;
}
if(tempNode->mo < newNode->mo){
newNode->next = tempNode;
}
}
if(tempNode->loc > newNode->loc){
newNode->next = tempNode->next;
tempNode->next = newNode;
}
if(tempNode->loc < newNode->loc){
newNode->next = tempNode->next;
tempNode->next = newNode;
}
tempNode = tempNode->next;
}
}
void LinkedList::clear() {
// Implement this function
Node* current = head;
while (current != nullptr) {
Node* deleteNode = current;
current = current->next;
delete deleteNode;
}
head = nullptr;
tail = nullptr;
}
void LinkedList::print() const {
/* Do not modify this function */
print(cout);
}
void LinkedList::print(ostream& os) const {
/* Do not modify this function */
os << *this;
}
ostream& operator<<(ostream& os, const LinkedList& ll) {
// Implement this function
Node* tempNode = ll.head;
if (tempNode == nullptr) {
os << " <Empty List>";
}
while (tempNode != nullptr) {
if (tempNode != ll.head)
cout << " " << tempNode->loc << " " << tempNode->yr << " " << tempNode->mo << " " << tempNode->temp << endl;
}
tempNode = tempNode->next;
return os;
}
Related
I want to save the number of element inside an instance of linked list class object. From the code below everytime I call addNodeFront() or addNodeBack() function, member variable len should be incremented by 1. But, when I run the code, the getLen function only return 1, while the linked list has 2 element. What should I fix from the my code?
#include <iostream>
class Node {
public:
int value;
Node* next;
Node(int value, Node* next) {
this->value = value;
this->next = next;
}
};
class LinkedList {
public:
Node* head;
Node* tail;
int len = 0;
LinkedList() {
this->head = nullptr;
this->tail = nullptr;
}
LinkedList(Node* node) {
this->head = node;
this->tail = node;
}
int getLen() {
return len;
}
void addNodeFront(Node* node) {
if(head==nullptr && tail==nullptr) {
this->head = node;
this->tail = node;
return;
}
Node* secondFirst = this->head;
this->head = node;
node->next = secondFirst;
this->len++;
}
void addNodeBack(Node* node) {
if(head==nullptr && tail==nullptr) {
this->head = node;
this->tail = node;
return;
}
this->tail->next = node;
this->tail = node;
this->len++;
}
void addNodeAfterNode(Node* prevNode, Node* node) {
if(prevNode == this->tail) {
this->tail = node;
prevNode->next = node;
return;
}
node->next = prevNode->next;
prevNode->next = node;
}
bool searchVal(int val) const {
Node* s = this->head;
while(s != nullptr) {
if(s->value == val) return true;
s = s->next;
}
return false;
}
void deleteNodeFront() {
if(this->head==this->tail) {
this->head = nullptr;
this->tail = nullptr;
return;
}
this->head = this->head->next;
}
void deleteNodeBack() {
Node* secondLast = this->head;
if(this->head==this->tail) {
this->head = nullptr;
this->tail = nullptr;
return;
}
while(secondLast->next != this->tail) {
secondLast = secondLast->next;
}
secondLast->next = nullptr;
this->tail = secondLast;
}
void deleteNodeMiddle(Node* node) {
if(node==this->head || node==this->tail) return;
Node* prevNode = this->head;
while(prevNode->next != node) {
prevNode = prevNode->next;
}
prevNode->next = prevNode->next->next;
}
void traverseLinkedList() {
Node* t = this->head;
if(head==nullptr && tail==nullptr) std::cout << "Empty Linked List";
while(t != nullptr) {
std::cout << t->value << "->";
t = t->next;
}
std::cout << "\n";
}
};
int main() {
Node node1(2,nullptr);
Node node4(4,nullptr);
LinkedList ls;
ls.addNodeFront(&node1);
ls.addNodeFront(&node4);
std::cout << ls.getLen() << std::endl;
ls.traverseLinkedList();
}
In the following function:
LinkedList(Node* node)
{
this->head = node;
this->tail = node;
}
Just add one of the following lines:
len++; //1
len = 1; //2
So the updated function:
LinkedList(Node* node)
{
this->head = node;
this->tail = node;
len++; //1
len = 1; //2
}
This is because as the head node and the tail node = node now, that means there is a node in the linked list, so we should add 1 to len.
I'm trying to make a const_iterator but I have some trouble understanding it. I try to change stuff to make it work but it won't compile. Can somebody please help me understand what am I doing wrong?
My code looks like that -
#include <iostream>
#include <cstring>
#include <string>
#include <functional>
#include "dummy.h"
using namespace std;
#ifndef SORT_H
#define SORT_H
template <class T>
class LinkedList {
struct Node {
Node(const T &in) : data(in) {}
T data;
Node * next;
};
Node * head;
public:
LinkedList() {
head = nullptr;
}
LinkedList(T value) {
head = new Node(value);
}
~LinkedList() {
while(head != nullptr) {
Node * curr = head -> next;
delete head;
head = curr;
}
}
class const_iterator
{
Node* m_ptr; // pointer to current node in the list
bool operator != (const const_iterator other) const {
return m_ptr != other.m_ptr;
}
public:
const_iterator() {
m_ptr = nullptr;
}
const_iterator(Node * node) {
m_ptr = node;
}
const_iterator(const const_iterator &it){
m_ptr = it.m_ptr;
}
const_iterator& operator =(const_iterator it) {
std::swap(it.m_ptr, m_ptr);
return *this;
}
const_iterator& operator ++ () {
if (m_ptr == nullptr) {
throw out_of_range("out of range");
}
m_ptr = m_ptr -> next;
return *this;
}
const_iterator operator ++ (T) {
if (m_ptr == nullptr) {
throw out_of_range("out of range");
}
const_iterator temp(*this);
m_ptr = m_ptr -> next;
return temp;
}
bool operator == (const const_iterator other) const {
return m_ptr == other.m_ptr;
}
T& operator*() const {
return *m_ptr;
}
operator bool() {
return m_ptr != nullptr;
};
bool is_in_list(LinkedList<T>::const_iterator it){
Node * curr = head;
while(curr != nullptr) {
if (curr == it){
return true;
} else {
curr = curr->next;
}
}
return false;
}
LinkedList& operator =(LinkedList list) {
std::swap(list.head, head);
return *this;
}
Node * nodeCopy(Node * head) {
if (head == nullptr) {
return nullptr;
}
Node * copied_node = new Node(head -> data);
copied_node -> data = head -> data;
copied_node -> next = nodeCopy(head -> next);
return copied_node;
}
LinkedList(const LinkedList &list){
head = nodeCopy(list.head);
}
template<typename B>
LinkedList filter(LinkedList &list, B pred) {
LinkedList <T> new_list(list);
Node * curr = list.head;
while (curr) {
if (!(pred(curr -> data))) {
new_list.remove(curr -> data);
}
curr = curr -> next;
}
std::cout << "Getting out of filter" << std::endl;
return new_list;
}
template<typename A>
LinkedList apply(A func) {
LinkedList <T> new_list;
Node * curr = head;
while (curr) {
new_list.insert(func(curr -> data));
std::cout << "Putting into new list: " << func(curr -> data) << std::endl;
curr = curr -> next;
}
std::cout << "Getting out of apply" << std::endl;
return new_list;
}
int length() {
// std::cout << "DEBUG length 1" << std::endl;
int counter = 0;
Node * tmp = head;
// std::cout << "DEBUG length 2" << std::endl;
while( tmp != nullptr ) {
// std::cout << "DEBUG length 3" << std::endl;
counter++;
tmp = tmp -> next;
}
return counter;
}
void insert(T value) {
// Add first node
if (head == nullptr) {
std::cout << "Add first node" << std::endl;
head = new Node(value);
head->next = nullptr;
return;
}
Node *curr = head;
// check if should be new head (when new value smaller than current head) -> add new head
if (value <= head->data) {
// add new head
std::cout << "add new head" << std::endl;
Node * new_head = new Node(value);
new_head -> next = head;
head = new_head;
return;
}
while (curr != nullptr) {
if (curr->next == nullptr && value >= curr->data) {
// add new tail
std::cout << "add new tail" << std::endl;
Node * new_node = new Node(value);
curr -> next = new_node;
new_node -> next = nullptr;
return;
} else if (value >= curr->data && value <= curr->next->data) {
// add new node between those two
std::cout << "add new node between those two" << std::endl;
Node * new_node = new Node(value);
Node * temp_ptr = curr -> next;
curr -> next = new_node;
new_node -> next = temp_ptr;
return;
} else {
curr = curr->next;
}
}
}
void remove(const_iterator it) {
// TODO: Check if delete all accurancies
if (!is_in_list(it)){
return;
}
// handle the head
if (head == it) {
if (head->next != nullptr) {
// head is not single node
Node * temp_ptr = head->next;
delete head;
head = temp_ptr;
return;
} else {
// head is single node
delete head;
head = nullptr;
return;
}
}
Node * curr = head;
Node * prev = head;
while (curr != nullptr){
if (curr == it){
// as we are already handled the head case,
// at this point we know that curr != head.
prev->next = curr->next;
delete curr;
return;
} else {
prev=curr;
curr=curr->next;
}
}
}
void print() {
Node * curr = head;
while (curr != nullptr) {
cout << curr -> data << endl;
curr = curr -> next;
}
}
Node * begin() const {
return head;
}
Node * end() const {
Node * curr = head;
while (curr->next != nullptr){
curr = curr->next;
}
return curr;
}
};
#endif
and my main looks like that-
#include <iostream>
#include "sortedList.h"
#include "dummy.h"
bool func(Dummy num) {
int number = num.get();
if (number % 2 != 0) {
return false;
}
return true;
}
string getLen(string str)
{
return std::to_string(str.length());
}
using std::string;
int main() {
std::cout << "Hello, World!" << std::endl;
LinkedList<string> lst1 = LinkedList<string>();
lst1.insert("Charlie");
lst1.insert("Bob");
lst1.insert("Alice");
lst1.insert("Donald");
lst1.print();
LinkedList<string> lst2 = lst1;
lst2 = lst2.apply(getLen);
lst2.print();
LinkedList<string>::const_iterator it = lst2.begin();
cout << *it << endl << endl;
++it;
lst2.remove(it);
lst2.print();
return 0;
}
The error message I'm getting is-
(Not all of it is here because it is too long)
In file included from C:\Users\User\CLionProjects\ex2.2\main.cpp:2:
C:\Users\User\CLionProjects\ex2.2\sortedList.h: In instantiation of 'class LinkedList<std::__cxx11::basic_string<char> >::const_iterator':
C:\Users\User\CLionProjects\ex2.2\main.cpp:40:44: required from here
C:\Users\User\CLionProjects\ex2.2\sortedList.h:79:24: error: postfix 'LinkedList<T>::const_iterator LinkedList<T>::const_iterator::operator++(T) [with T = std::__cxx11::basic_string<char>]' must have 'int' as its argument
const_iterator operator ++ (T) {
^~~~~~~~
C:\Users\User\CLionProjects\ex2.2\sortedList.h: In instantiation of 'T& LinkedList<T>::const_iterator::operator*() const [with T = std::__cxx11::basic_string<char>]':
C:\Users\User\CLionProjects\ex2.2\main.cpp:41:18: required from here
C:\Users\User\CLionProjects\ex2.2\sortedList.h:92:21: error: invalid initialization of reference of type 'std::__cxx11::basic_string<char>&' from expression of type 'LinkedList<std::__cxx11::basic_string<char> >::Node'
return *m_ptr;
what am I doing wrong?
self_type operator++() { self_type i = *this; ptr_++; return i; }
This cannot work. ptr_++ will move the pointer to the next element of the array... except there is no array in this case. You aren't writing an iterator for an array, you're writing an iterator for a linked list.
Instead of a pointer to element, you need a pointer to a node. And to move to the next node, you need ptr = ptr->next.
As for the compilation errors, look at the error message, and where the error is. You haven't shown where return *head;, but let's look at the other one:
Node * head;
...
LinkedList<T>::const_iterator it
...
if (head == it) {
You're comparing a pointer to node with an iterator. Why do you think that would work? What do you expect the result to be? The solution to the error is to not do that.
Right now, I'm trying to write a reverse method for a Doubly Linked List. It's not just one of the methods where you reverse from start to finish, but specifically a part of the list starting from one point and ending at a point after the start. The method takes in ListNode pointer references called startPoint and endPoint, and they should point at the new start and end of the chain in the linked memory. The next member of the ListNode before the start of the sequence (so startPoint->prev) should point at the new start, and the prev member of the ListNode after the end of the sequence (so endPoint->next) should point to the new end.
A key aspect I should point out is that we may NOT allocate any new ListNodes.
In my List.h file, I have a private class ListNode. I provided that along with the rest of my List class:
template <class T>
class List {
private:
class ListNode {
public:
ListNode();
ListNode(const T & ndata);
ListNode* next;
ListNode* prev;
const T data;
};
public:
List();
List(const List<T>& other);
List<T>& operator=(const List<T>& rhs);
int size() const;
void print(ostream& os = std::cout) const;
bool empty() const;
~List();
void insertFront(const T& ndata);
void insertBack(const T& ndata);
void reverse();
void tripleRotate();
List<T> split(int splitPoint);
private:
ListNode* head_;
ListNode* tail_;
int length_;
void _copy(const List<T>& other);
void _destroy();
/**
* Helper function to reverse a sequence of linked memory inside a
* List, starting at startPoint and ending at endPoint. You are
* responsible for updating startPoint and endPoint to point to the
* new starting and ending points of the rearranged sequence of
* linked memory in question.
*
* #param startPoint A pointer reference to the first node in the
* sequence to be reversed.
* #param endPoint A pointer reference to the last node in the
* sequence to be reversed.
*/
void reverse(ListNode*& startPoint, ListNode*& endPoint);
};
In my List.hpp file, I have the reverse method itself. I am lost on how exactly to write it. Here's what I have so far (it obviously doesn't work):
template <typename T>
void List<T>::reverse(ListNode *& startPoint, ListNode *& endPoint) {
if (startPoint == endPoint) {
return;
}
//startPoint should point at the new start, endPoint should point at the new end.
ListNode* current = startPoint;
ListNode* before_start_point = startPoint->prev;
ListNode* after_end_point = endPoint->next;
while (current != after_end_point) {
ListNode* temp = current->next;
current->next = current->prev;
current->prev = temp;
if (temp == endPoint) {
endPoint = startPoint;
startPoint = current;
}
current = temp;
}
}
The rest of the List.hpp file:
template <class T>
List<T>::List() {
head_ = NULL;
tail_ = NULL;
length_ = 0;
}
template <typename T>
void List<T>::_destroy() {
ListNode* current = head_;
while (current != NULL) {
ListNode* temp = current->next;
delete current;
current = temp;
}
}
template <typename T>
void List<T>::insertFront(T const & ndata) {
ListNode* newNode = new ListNode(ndata);
//Case where there the list is empty
if (head_ == NULL) {
head_ = newNode;
tail_ = newNode;
newNode->next = NULL;
newNode->prev = NULL;
}
else {
newNode->next = head_;
newNode->prev = NULL;
head_->prev = newNode;
head_ = newNode;
}
length_++;
}
template <typename T>
void List<T>::insertBack(const T & ndata) {
ListNode* newNode = new ListNode(ndata);
if (tail_ == NULL) {
head_ = newNode;
tail_ = newNode;
newNode->next = NULL;
newNode->prev = NULL;
}
else {
newNode->prev = tail_;
newNode->next = NULL;
tail_->next = newNode;
tail_ = newNode;
}
length_++;
}
template <typename T>
typename List<T>::ListNode* List<T>::split(ListNode* start, int splitPoint) {
//There will be splitPoint number of nodes remaining in the current list
ListNode* curr = start;
if (splitPoint == 0) {
return curr;
}
//Takes you to the start of the new list
for (int i = 0; i < splitPoint && curr != NULL; i++) {
curr = curr->next;
}
if (curr != NULL) {
curr->prev->next = NULL;
curr->prev = NULL;
}
//Return the head of the new sublist
return curr;
}
template <typename T>
void List<T>::tripleRotate() {
if (length_ < 3) {
return;
}
else {
int third_element_counter = 1;
bool first_rotation = true;
int divisible_by_three = length_ % 3;
ListNode* current = head_;
while (current != NULL) {
if (third_element_counter != 3) {
third_element_counter++;
}
else {
ListNode* first = current->prev->prev;
ListNode* temp_first_prev = first->prev;
ListNode* second = current->prev;
ListNode* temp_current = current;
ListNode* temp_current_next = current->next;
second->prev = temp_first_prev;
if (temp_first_prev != NULL) {
temp_first_prev->next = second;
}
if (temp_current_next != NULL) {
temp_current_next->prev = first;
}
current->next = first;
first->next = temp_current_next;
first->prev = temp_current;
if (first_rotation) {
head_ = second;
first_rotation = false;
}
if (divisible_by_three == 0) {
tail_ = first;
}
current = first;
third_element_counter = 1;
}
current = current->next;
}
}
}
template <typename T>
void List<T>::reverse() {
reverse(head_, tail_);
}
Any sort of help is appreciated.
Given your code, I manually created a list of ten integers:
List<int> my_list;
for(int i = 0; i < 10; i++) {
my_list.insertBack(i);
}
Then, I printed the list:
std::cout << "Before reverse:" << std::endl;
my_list.print();
The output was:
Before reverse:
Node: 0
Node: 1
Node: 2
Node: 3
Node: 4
Node: 5
Node: 6
Node: 7
Node: 8
Node: 9
Then, I ran a slightly modified version of your reverse function:
template <typename T>
void List<T>::reverse(ListNode *& startPoint, ListNode *& endPoint) {
if (startPoint == endPoint) {
return;
}
//startPoint should point at the new start, endPoint should point at the new end.
ListNode* current = startPoint;
ListNode* before_start_point = startPoint->prev;
ListNode* after_end_point = endPoint->next;
while (current != after_end_point) {
std::cout << "Working with current node " << current->data << std::endl;
ListNode* temp = current->next;
std::cout << "Temp is " << (temp ? temp->data : 0) << std::endl;
current->next = current->prev;
std::cout << current->data << "'s new next is now " << (current->next ? current->next->data : 0) << std::endl;
current->prev = temp;
std::cout << current->data << "'s new prev is now " << (current->prev ? current->prev->data : 0) << std::endl;
if (temp == endPoint) {
endPoint = startPoint;
startPoint = temp;
}
current = temp;
}
}
And printed again:
std::cout << "After reverse:" << std::endl;
my_list.print();
The output was:
After reverse:
Node: 9
Node: 8
Node: 7
Node: 6
Node: 5
Node: 4
Node: 3
Node: 2
Node: 1
Node: 0
So it seems the only problem was in the if block at the end of the while loop, where you were assigning startPoint = current when instead it should be either startPoint = endPoint or startPoint = temp (because when the if is true, temp is equal to endPoint).
This is the complete code (also available in https://godbolt.org/z/nad7vT):
#include <iostream>
template <class T>
class List {
private:
class ListNode {
public:
ListNode();
ListNode(const T & ndata) : data{ndata} {};
ListNode* next;
ListNode* prev;
const T data;
};
public:
List();
List(const List<T>& other);
List<T>& operator=(const List<T>& rhs);
int size() const;
void print(std::ostream& os = std::cout) const;
bool empty() const;
~List() {};
void insertFront(const T& ndata);
void insertBack(const T& ndata);
void reverse();
void reverseNth(int n);
void tripleRotate();
List<T> split(int splitPoint);
private:
ListNode* head_;
ListNode* tail_;
int length_;
void _copy(const List<T>& other);
void _destroy();
/**
* Helper function to reverse a sequence of linked memory inside a
* List, starting at startPoint and ending at endPoint. You are
* responsible for updating startPoint and endPoint to point to the
* new starting and ending points of the rearranged sequence of
* linked memory in question.
*
* #param startPoint A pointer reference to the first node in the
* sequence to be reversed.
* #param endPoint A pointer reference to the last node in the
* sequence to be reversed.
*/
void reverse(ListNode*& startPoint, ListNode*& endPoint);
};
template <typename T>
void List<T>::reverse(ListNode *& startPoint, ListNode *& endPoint) {
if (startPoint == endPoint) {
return;
}
//startPoint should point at the new start, endPoint should point at the new end.
ListNode* current = startPoint;
ListNode* before_start_point = startPoint->prev;
ListNode* after_end_point = endPoint->next;
while (current != after_end_point) {
std::cout << "Working with current node " << current->data << std::endl;
ListNode* temp = current->next;
std::cout << "Temp is " << (temp ? temp->data : 0) << std::endl;
current->next = current->prev;
std::cout << current->data << "'s new next is now " << (current->next ? current->next->data : 0) << std::endl;
current->prev = temp;
std::cout << current->data << "'s new prev is now " << (current->prev ? current->prev->data : 0) << std::endl;
if (temp == endPoint) {
endPoint = startPoint;
startPoint = temp;
}
current = temp;
}
}
template <class T>
List<T>::List() {
head_ = NULL;
tail_ = NULL;
length_ = 0;
}
template <typename T>
void List<T>::_destroy() {
ListNode* current = head_;
while (current != NULL) {
ListNode* temp = current->next;
delete current;
current = temp;
}
}
template <typename T>
void List<T>::insertFront(T const & ndata) {
ListNode* newNode = new ListNode(ndata);
//Case where there the list is empty
if (head_ == NULL) {
head_ = newNode;
tail_ = newNode;
newNode->next = NULL;
newNode->prev = NULL;
}
else {
newNode->next = head_;
newNode->prev = NULL;
head_->prev = newNode;
head_ = newNode;
}
length_++;
}
template <typename T>
void List<T>::insertBack(const T & ndata) {
ListNode* newNode = new ListNode(ndata);
if (tail_ == NULL) {
head_ = newNode;
tail_ = newNode;
newNode->next = NULL;
newNode->prev = NULL;
}
else {
newNode->prev = tail_;
newNode->next = NULL;
tail_->next = newNode;
tail_ = newNode;
}
length_++;
}
template <typename T>
void List<T>::print(std::ostream& os) const {
for(const ListNode *it = head_; it != nullptr; it = it->next) {
os << "Node: " << it->data << std::endl;
}
}
template <typename T>
void List<T>::reverse() {
reverse(head_, tail_);
}
int main() {
List<int> my_list;
for(int i = 0; i < 10; i++) {
my_list.insertBack(i);
}
std::cout << "Before reverse:" << std::endl;
my_list.print();
my_list.reverse();
std::cout << "After reverse:" << std::endl;
my_list.print();
return 0;
}
I decided to practice my linked-list knowledge, and decided to create one in C++!
I ran this code on two different online compilers - one worked, and the other is giving me a segfault. I cannot figure out what the problem is within my code, and am wondering if you can help me.
#include <iostream>
using namespace std;
struct Node {
int val;
Node *next;
Node(int val){
this->val = val;
this->next = NULL;
}
};
class LinkedList {
public:
Node *head;
void insertAtHead(Node *temp)
{
if (head == NULL)
{
head = temp;
}
else
{
temp->next = head;
head = temp;
}
}
void printList()
{
Node *temp = head;
while (temp != NULL)
{
cout << temp->val << endl;
temp = temp->next;
}
}
void insertAtBack(Node *temp)
{
if (head == NULL)
{
head = temp;
return;
}
Node *current = head;
while (current->next != NULL){
current = current->next;
}
current->next = temp;
}
void deleteNode(Node *temp)
{
if (head == NULL)
{
cout << "Empty List";
return;
}
if (head->val == temp->val)
{
head = head->next;
return;
}
Node *current = head;
while (current->next != NULL)
{
if (current->next->val == temp->val)
{
current->next = current->next->next;
return;
}
current = current->next;
}
}
};
int main()
{
Node *temp = new Node(10);
Node *temp2 = new Node(4);
Node *temp3 = new Node(17);
Node *temp4 = new Node(22);
Node *temp5 = new Node(1);
LinkedList x;
x.insertAtHead(temp);
x.insertAtHead(temp2);
x.insertAtBack(temp3);
// x.insertAtBack(temp4);
// x.insertAtBack(temp5);
// x.deleteNode(temp);
x.printList();
return 0;
}
The problem I am encountering is when I use the insertAtBack() method. It gives me a segfault, but I do not see what's wrong with the logic. It is pretty straight forward. The insertAtFront() method works, but once I call insertAtBack() my code fails.
make sure to initialize Node *head to NULL.
After insert temp(which is value 10), temp->next value becomes undefined value, because Node *head is undefined value.
Your LinkedList class is not initializing its head member. You need to add a constructor to initialize head to NULL.
Also, the class is leaking memory, as there is no destructor to free the nodes when a LinkedList instance is destroyed, and deleteNode() doesn't free the node being removed, either.
Try something more like this:
#include <iostream>
using namespace std;
struct Node
{
int val;
Node *next;
Node(int val) : val(val), next(NULL) { }
};
class LinkedList
{
private:
Node *head;
// if you are NOT using C++11 or later, add these
// until you are reading to tackle copy semantics!
/*
LinkedList(const LinkedList &);
LinkedList& operator=(const LinkedList &);
*/
public:
LinkedList() : head(NULL) {} // <-- add this!
~LinkedList() // <-- add this!
{
Node *current = head;
while (current)
{
Node *next = current->next;
delete current;
current = next;
}
}
void insertAtHead(Node *temp)
{
if (!head)
{
head = temp;
}
else
{
temp->next = head;
head = temp;
}
}
void printList()
{
Node *current = head;
while (current)
{
cout << current->val << endl;
current = current->next;
}
}
void insertAtBack(Node *temp)
{
if (!head)
{
head = temp;
return;
}
Node *current = head;
while (current->next) {
current = current->next;
}
current->next = temp;
}
void deleteNode(Node *temp)
{
if (!head)
{
cout << "Empty List";
return;
}
if (head == temp)
{
head = temp->next;
delete temp;
return;
}
Node *current = head;
while (current->next)
{
if (current->next == temp)
{
current->next = temp->next;
delete temp;
return;
}
current = current->next;
}
}
// if you ARE using C++11 or later, add these until
// you are reading to tackle copy and move semantics!
/*
LinkedList(const LinkedList &) = delete;
LinkedList(LinkedList &&) = delete;
LinkedList& operator=(const LinkedList &) = delete;
LinkedList& operator=(LinkedList &&) = delete;
*/
};
int main()
{
Node *temp = new Node(10);
Node *temp2 = new Node(4);
Node *temp3 = new Node(17);
Node *temp4 = new Node(22);
Node *temp5 = new Node(1);
LinkedList x;
x.insertAtHead(temp);
x.insertAtHead(temp2);
x.insertAtBack(temp3);
// x.insertAtBack(temp4);
// x.insertAtBack(temp5);
// x.deleteNode(temp);
x.printList();
return 0;
}
Which can then be simplified further:
#include <iostream>
using namespace std;
struct Node
{
int val;
Node *next;
Node(int val, Node *next = NULL) : val(val), next(next) { }
};
class LinkedList
{
private:
Node *head;
// if you are NOT using C++11 or later, add these
// until you are reading to tackle copy semantics!
/*
LinkedList(const LinkedList &);
LinkedList& operator=(const LinkedList &);
*/
public:
LinkedList() : head(NULL) {} // <-- add this!
~LinkedList() // <-- add this!
{
Node *current = head;
while (current)
{
Node *next = current->next;
delete current;
current = next;
}
}
Node* insertAtHead(int value)
{
Node *temp = new Node(value, head);
if (!head)
head = temp;
return temp;
}
void printList()
{
Node *current = head;
while (current)
{
cout << current->val << endl;
current = current->next;
}
}
Node* insertAtBack(int value)
{
Node **current = &head;
while (*current)
current = &((*current)->next);
*current = new Node(value);
return *current;
}
/*
void deleteNode(Node *temp)
{
Node *current = head, *previous = NULL;
while (current)
{
if (current == temp)
{
if (previous)
previous->next = temp->next;
if (head == temp)
head = temp->next;
delete temp;
return true;
}
previous = current;
current = current->next;
}
cout << "Not found" << endl;
return false;
}
*/
bool deleteValue(int value)
{
Node *current = head, *previous = NULL;
while (current)
{
if (current->val == value)
{
if (previous)
previous->next = temp->next;
if (head == temp)
head = temp->next;
delete temp;
return true;
}
previous = current;
current = current->next;
}
cout << "Not found" << endl;
return false;
}
// if you ARE using C++11 or later, add these until
// you are reading to tackle copy and move semantics!
/*
LinkedList(const LinkedList &) = delete;
LinkedList(LinkedList &&) = delete;
LinkedList& operator=(const LinkedList &) = delete;
LinkedList& operator=(LinkedList &&) = delete;
*/
};
int main()
{
LinkedList x;
x.insertAtHead(10);
x.insertAtHead(4);
x.insertAtBack(17);
// x.insertAtBack(22);
// x.insertAtBack(1);
// x.deleteValue(10);
x.printList();
return 0;
}
this is my lab and I work all of it. After long time of debugging, fixing errors, finally it can compile. But when it run, it didn't give me the correct answer. It just kept saying : did not find y (may be x was added) and it was 4 line with the same answer.
please look at my code and tell me why it didn't work.
Thanks a lot.
Here is my code:
LinkedList.h:
#ifndef _LINKED_LIST_
#define _LINKED_LIST_
#include <ostream>
class LinkedList
{
public:
LinkedList();
LinkedList(char ch);
LinkedList(const LinkedList& List);
~LinkedList();
void add(const char& ch);
bool find(char ch);
bool del(char ch);
friend std::ostream& operator<<(std::ostream& out, LinkedList& list);
private:
struct node
{
char item;
node * next;
};
node * head;
int size;
};
#endif // _LINKED_LIST_
Linkedlist.cpp
#include "linkedlist.h"
#include <iostream>
#include <fstream>
#include <cassert>
#include <cstring>
using namespace std;
LinkedList::LinkedList() : head(NULL)
{
}
LinkedList::LinkedList(char ch):head(NULL)
{
char currData;
currData = ch;
add(currData);
}
LinkedList::~LinkedList()
{
node * curr = head;
while(head)
{
curr = head->next;
delete head;
head = curr;
}
}
LinkedList::LinkedList(const LinkedList& List)
{
if(List.head == NULL)
head = NULL;
else
{
//copy first node
head = new node;
assert(head != NULL);
head->item = List.head->item;
//copy the rest of the list
node * destNode = head; //points to the last node in new list
node * srcNode = List.head->next; //points to node in aList
while(srcNode != NULL) //or while (srcNode)
{
destNode->next = new node;
assert(destNode->next != NULL); //check allocation
destNode = destNode->next;
destNode->item = srcNode->item;
srcNode = srcNode->next;
}
destNode->next = NULL;
}
}
ostream& operator<<(std::ostream& out, LinkedList& list)
{
while(list.head)
{
out << list.head->item << endl;
list.head = list.head->next;
}
return out;
}
void LinkedList::add(const char& ch)
{
node * prev = NULL;
node * curr = head;
while (curr != NULL && curr->item < ch)
{
prev = curr;
curr = curr->next;
}
if (curr && curr->item != ch)
{
node * newNode = new node;
newNode->item = ch;
newNode->next = NULL;
newNode->next = curr;
if (prev == NULL)
head = newNode;
else
prev->next = newNode;
size++;
}
}
bool LinkedList::del(char ch)
{
char a;
node * prev = NULL;
node * curr = head;
while (curr)
{
a = curr->item;
if ( a == ch)
{
if(!prev)
head = curr->next;
else
prev->next = curr->next;
delete curr;
size--;
return true;
}
prev = curr;
curr = curr->next;
}
return false;
}
bool LinkedList::find(char ch)
{
char a;
node * prev = NULL;
node * curr = head;
while (curr)
{
a = curr->item;
if ( a == ch)
{
return true;
}
prev = curr;
curr = curr->next;
}
return false;
}
app.cpp
#include <iostream>
#include "linkedlist.h"
using namespace std;
void find(LinkedList& list, char ch)
{
if (list.find(ch))
cout << "found ";
else
cout << "did not find ";
cout << ch << endl;
}
int main()
{
LinkedList list;
list.add('x');
list.add('y');
list.add('z');
cout << list;
find(list, 'y');
list.del('y');
cout << list;
find(list, 'y');
list.del('x');
cout << list;
find(list, 'y');
list.del('z');
cout << list;
find(list, 'y');
return 0;
}
Your add method doesn't work, if the item to insert goes at the end it is not inserted (because you are checking for curr == NULL before inserting). Since head is set to NULL when you create the list if(curr && ...) won't ever be true and no item will be inserted.