infinite copy list loop with copy constructor and pointers - c++
i am having an infinite loop after it tries to insert "b" into the list.
based on my output when i run "make test | more", it inserts "a" just fine, but when it reaches "b" and tries to call the copy constructor again, thats when it gets into an infinite loop
here is my header file
#define DLIST_HEADER
#include <string>
struct DListNodeT;
class DListT{
public:
DListT();
DListT(const DListT & src);
~DListT();
DListT & operator = (const DListT & rhs);
void Home();
void Left();
void Right();
std::string Data() const;
size_t Size() const;
void Insert(std::string newData);
void InsertAfter(std::string newData);
void Delete();
private:
DListNodeT* head;
DListNodeT* current;
size_t nodeCount;
};
#endif
here is my cpp file
#include "DListT.h"
using namespace std;
void DeleteList(DListNodeT * list);
DListNodeT * CopyList(DListNodeT * src);
void AdjustCurrent(DListNodeT * srcList, DListNodeT * destList, DListNodeT * srcCurrent, DListNodeT * & destCurrent);
struct DListNodeT
{
string data;
DListNodeT * next{nullptr};
DListNodeT * prev{nullptr};
};
DListT::DListT()
{
//DListNodeT * tmp{nullptr};
//tmp.data = "hi";
//tmp = new DListNodeT;
head = nullptr;
current = nullptr;
nodeCount = 0;
}
DListT::DListT(const DListT & src)
{
cout << "calling copy constructor" << endl;
//this was added after this was graded
nodeCount = src.nodeCount;
head = CopyList(src.head);
AdjustCurrent(src.head, head, src.current, current);
cout << "exiting copy constructor" << endl;
/*DListNodeT * travel{nullptr};
DListNodeT * tmp{nullptr};
DListNodeT * tail{nullptr};
head = nullptr;
travel = src.head;
while (travel != nullptr)
{
tmp = new DListNodeT;
tmp->data = travel->data;
tmp->next = nullptr;
//tmp->prev = nullptr;
if (head == nullptr)
{
head = tmp;
}
else
{
tail->next = tmp;
//tail->prev = tmp;
}
tail = tmp;
travel = travel->next;
//travel = travel->prev;
}
nodeCount = src.nodeCount;*/
}
DListT::~DListT()
{
DeleteList(head);
}
DListT & DListT::operator = (const DListT & rhs)
{
if (this != &rhs)
{
DeleteList(head);
head = CopyList(rhs.head);
nodeCount = rhs.nodeCount;
AdjustCurrent(rhs.head, head, rhs.current, current);
}
return *this;
}
void DeleteList(DListNodeT * list)
{
DListNodeT * tmp{nullptr};
DListNodeT * garbage{nullptr};
if (list != nullptr)
{
tmp = list;
do
{
garbage = tmp;
tmp = garbage->next;
delete garbage;
} while (tmp != list);
}
}
DListNodeT * CopyList(DListNodeT * src)
{
DListNodeT * head{nullptr};
DListNodeT * trace1{nullptr};
DListNodeT * trace2{nullptr};
DListNodeT * tmp{nullptr};
if (src == nullptr)
{
head = nullptr;
}
else
{
//set up head pointer
cout << "setting up new head" << endl;
head = new DListNodeT;
cout << "set new head" << endl;
cout << "setting head's data to src's data" << endl;
head->data = src->data;
cout << "set head's data to src's data" << endl;
cout << "setting head's next to head" << endl;
head->next = head;
cout << "set head's next to head" << endl;
cout << "setting head's prev to head" << endl;
head->prev = head;
cout << "set head's prev to head" << endl;
//copy rest of list
cout << "setting trace1 to src's next" << endl;
trace1 = src->next;
cout << "set trace1 to src's next" << endl;
cout << "setting trace2 to head" << endl;
trace2 = head;
cout << "set trace2 to head" << endl;
while (/*trace1 != head*/ trace1 != src)
{
cout << "in copylist while loop" << endl;
//build new nodes
cout << "creating a new tmp node" << endl;
tmp = new DListNodeT;
cout << "created the tmp node" << endl;
cout << "setting tmp's data to trace1's data" << endl;
tmp->data = trace1->data;
cout << "set tmp's data to trace1's data" << endl;
cout << "setting tmp's next to null" << endl;
tmp->next = nullptr;
cout << "set tmp's next to null" << endl;
cout << "data is: " << tmp->data << endl;
//link into list
cout << "setting trace2's next to tmp" << endl;
trace2->next = tmp;
cout << "set trace2's next to tmp" << endl;
cout << "settings tmp's prev to trace2" << endl;
tmp->prev = trace2;
cout << "set tmp's prev to trace2" << endl;
cout << "data is: " << tmp->data << endl;
//make it circular
cout << "setting tmp's next to head" << endl;
tmp->next = head;
cout << "set tmp's next to head" << endl;
cout << "setting head's prev to tmp" << endl;
head->prev = tmp;
cout << "set head's prev to tmp" << endl;
cout << "data is: " << tmp->data << endl;
//advance next two pointers
cout << "setting trace2 to tmp" << endl;
trace2 = tmp;
cout << "set trace2 to tmp" << endl;
cout << "setting trace1 to trace1's next" << endl;
trace1 = trace1->next;
cout << "set trace1 to trace1's next" << endl;
cout << "data is: " << tmp->data << endl;
//cout << "nodecount is: " << nodeCount << endl;
}
}
return head;
}
void AdjustCurrent(DListNodeT * srcList, DListNodeT * destList, DListNodeT * srcCurrent, DListNodeT * & destCurrent)
{
DListNodeT * tmp{nullptr};
if (srcCurrent == nullptr)
{
destCurrent = nullptr;
}
else
{
tmp = srcList;
destCurrent = destList;
while (tmp != nullptr and tmp != srcCurrent)
{
tmp = tmp->next;
destCurrent = destCurrent->next;
}
}
}
void DListT::Insert(string newData)
{
cout << "entering insert function" << endl;
DListNodeT * tmp{nullptr};
DListNodeT * tail{nullptr};
tmp = new(DListNodeT);
tmp->data = newData;
tmp->next = nullptr;
tmp->prev = nullptr;
cout << "inserting an element into list" << endl;
nodeCount++;
// ASSUME
// INVARIANT: (head == nullptr) == (current == nullptr)
// if head is null, current is null.
// if head is NOT null, current is NOT null
if (head == nullptr)
{
cout << "entering if statement for empty list" << endl;
// we have an empty list, there are no nodes.
// the node we just created becomes the head/tail/current
tmp->next = tmp;
tmp->prev = tmp;
current = tmp;
head = tmp;
cout << "exiting if statment for empty list" << endl;
}
else if (current == head)
{
cout << "enterting if state where current is equal to the head of the list" << endl;
// this is a special case: when current points to the head,
// we will insert the new node _before_ the current one (head of the list)
tmp->next = head;
tmp->prev = head->prev;
head->prev = tmp;
current = tmp;
head = tmp;
cout << "exiting if statement where current is equal to the head of the list" << endl;
}
else
{
cout << "entering else statment from insert function" << endl;
// we have a non-empty list and we want to append to the end
// so we insert the new node at the current node
tail = current->prev;
tmp->prev = tail;
tmp->next = current;
tail->next = tmp;
current->prev = tmp;
current = tmp;
cout << "exiting else statement from insert function" << endl;
}
cout << "exiting insert function" << endl;
}
void DListT::Delete()
{
DListNodeT * tmp{nullptr};
DListNodeT * next{nullptr};
DListNodeT * prior{nullptr};
if (current == nullptr)
{
cout << "Error: Attempt to delete in an Empty List.";
}
else if (nodeCount == 1)
{
//USELESS current = tmp;
current = nullptr;
head = nullptr;
delete tmp;
}
else
{
// the node we're about to delete is also the head...
// reposition the head to the node after; otherwise it would
// point to the node we just deleted.
if (current == head) {
head = current->next;
}
// unlink the current node
prior = current->prev;
next = current->next;
prior->next = next;
next->prev = prior;
tmp = current;
current = prior;
delete tmp;
}
}
size_t DListT::Size() const
{
return nodeCount;
}
void DListT::Home()
{
if (head != nullptr)
{
current = head;
}
}
void DListT::Right()
{
if (current != nullptr)
{
current = current->next;
}
}
void DListT::Left()
{
if (current != nullptr)
{
current = current->prev;
}
}
void DListT::InsertAfter(string newData)
{
DListNodeT * tmp{nullptr};
DListNodeT * seek{nullptr};
tmp = new(DListNodeT);
tmp->data = newData;
tmp->next = nullptr;
tmp->prev = nullptr;
nodeCount++;
if (head == nullptr)
{
tmp->next = tmp;
tmp->prev = tmp;
current = tmp;
head = tmp;
}
else
{
// node after current; will now be after tmp
seek = current->next;
tmp->next = seek;
tmp->prev = current;
current->next = tmp;
seek->prev = tmp;
current = tmp;
}
}
string DListT::Data() const
{
string data;
if (current != nullptr)
{
data = current->data;
}
else
{
cout << "Error: Attempt to access Empty List.";
data = "NO DATA";
}
return data;
}
here is my professor's test code
#include<boost/test/included/unit_test.hpp>
#include<boost/test/unit_test.hpp>
#include <boost/test/output_test_stream.hpp>
#include <vector>
#include "DListT.h"
using namespace std;
using boost::test_tools::output_test_stream;
void Header(string s) {
cout << endl;
cout << "******* Running " << s << " *******" << endl;
}
void Footer(string s) {
cout << "******* Finished with " << s << " *******" << endl;
cout << endl;
}
BOOST_AUTO_TEST_SUITE( DListTTest )
BOOST_AUTO_TEST_CASE(constructor_test) {
DListT list;
Header("Constructor Test");
BOOST_CHECK_MESSAGE(list.Size() == 0, "Constructor Test, Size not 0");
Footer ("Constructor Test");
}
void Compare(DListT list, vector<string> check) {
size_t i;
cout << "in compare" << endl;
if (list.Size() != check.size()) {
BOOST_FAIL("Sizes not the same in Compare");
} else {
for(i = 0; i < check.size(); i++) {
BOOST_CHECK(list.Data() == check[i]);
list.Right();
}
}
cout << "exiting compare" << endl;
return;
}
void CompareHome(DListT list, vector<string> check) {
// we don't know that current is pointing to the right thing.
list.Home();
cout << "entering comparehome" << endl;
Compare(list, check);
cout << "exiting comparehome" << endl;
}
// not really checking current directly.
// since both are at the "same" value of current, they should be the same.
// this will not work if the pattern repeats and the current pointer is at
// a offset
//
void CompareLists(DListT & a, DListT & b) {
size_t i;
if (a.Size() != b.Size()) {
BOOST_FAIL("Sizes not the same in CompareLists");
} else {
for(i = 0; i < a.Size(); i++) {
BOOST_CHECK(a.Data() == b.Data());
a.Right();
b.Right();
}
BOOST_CHECK(a.Data() == b.Data());
}
}
BOOST_AUTO_TEST_CASE(insert_test) {
DListT list;
vector<string> check;
Header("Insert Test");
CompareHome(list, check);
// head->A
list.Insert("A");
cout << "inserting a" << endl;
check = {"A"};
CompareHome(list, check);
// head->B<->A
list.Insert("B");
cout << "inserting b" << endl;
for (size_t i = 0; i <= list.Size(); i++)
{
cout << "list has: " << list.Data() << endl;
cout << "i is: " << i << endl;
list.Right();
}
list.Home();
check = {"B","A"};
CompareHome(list, check);
// head->B<->C<->A
list.Home();
list.Right();
list.Insert("C");
check = {"B","C","A"};
CompareHome(list, check);
// head->D<->B<->C<->A
list.Home();
list.Insert("D");
check = {"D","B","C","A"};
CompareHome(list, check);
// head->D<->B<->C<->E<->A
list.Home();
list.Left();
list.Insert("E");
check = {"D","B","C","E","A"};
CompareHome(list, check);
// head->D<->B<->C<->E<->A
list.Home();
list.Left();
list.Left();
list.Left();
list.Insert("F");
check = {"D","B","F","C","E","A"};
CompareHome(list, check);
Footer("Insert Test");
}
BOOST_AUTO_TEST_CASE(copy_test) {
DListT list1, list2;
Header("Copy-Copy Constructor Test");
// check empty lists
// the first case should have an output error for now. Just supress it
output_test_stream output;
streambuf * old = cout.rdbuf(output.rdbuf());
CompareLists(list1, list2);
cout.rdbuf(old);
// check list with single element
list1.Insert("A");
list2 = list1;
CompareLists(list1, list2);
DListT list3(list1);
CompareLists(list1, list3);
// check lists with two elements
list1.Insert("B");
list2 = list1;
CompareLists(list1, list2);
DListT list4(list1);
CompareLists(list1, list4);
// let's try a handful of elements.
list1.Insert("C");
list1.Insert("D");
list1.Insert("E");
list2 = list1;
CompareLists(list1, list2);
DListT list5(list1);
CompareLists(list1, list5);
// did we get the current pointer right?
list1.Right();
list1.Right();
list1.Right();
list2 = list1;
CompareLists(list1, list2);
DListT list6(list1);
CompareLists(list1, list6);
Footer("Copy-Copy Constructor Test");
}
BOOST_AUTO_TEST_CASE(empty_data_access_test) {
DListT list;
Header("Empty Data Access Test");
// set up a stream buffer to capture the output
output_test_stream output;
// cause output to occur.
streambuf * old = cout.rdbuf(output.rdbuf());
string x = list.Data();
// restore the stdout buffer
cout.rdbuf(old);
BOOST_CHECK( !output.is_empty( false ) );
BOOST_CHECK( output.is_equal( "Error: Attempt to access Empty List.\n" ) );
BOOST_CHECK( x == "NO DATA");
Footer("Empty Data Access Test");
}
BOOST_AUTO_TEST_CASE(left_right_home_test) {
Header("Movement Test");
DListT list, listCopy;
vector<string> check;
list.Insert("D");
list.Insert("C");
list.Insert("B");
list.Insert("A");
list.Home();
check = {"A","B","C","D"};
listCopy = list;
Compare(listCopy,check);
list.Right();
check = {"B","C","D","A"};
listCopy = list;
Compare(listCopy,check);
list.Right();
check = {"C","D","A","B"};
listCopy = list;
Compare(listCopy,check);
list.Right();
check = {"D","A","B","C"};
listCopy = list;
Compare(listCopy,check);
list.Right();
check = {"A","B","C","D"};
listCopy = list;
Compare(listCopy,check);
list.Home();
list.Left();
check = {"D", "A","B","C"};
Compare(list,check);
list.Left();
check = {"C", "D", "A","B"};
Compare(list,check);
list.Left();
check = {"B", "C", "D", "A"};
Compare(list,check);
list.Left();
check = {"A", "B", "C", "D"};
Compare(list,check);
Footer("Movement Test");
}
BOOST_AUTO_TEST_CASE(delete_test) {
Header("Delete Test");
DListT list;
vector<string> check;
list.Insert("G");
list.Insert("F");
list.Insert("E");
list.Insert("D");
list.Insert("C");
list.Insert("B");
list.Insert("A");
check = {"A","B","C","D","E","F","G"};
CompareHome(list,check);
// delete the head of the list
list.Home();
list.Delete();
// delete the last item in the list;
list.Home();
list.Left();
list.Delete();
check = {"B","C","D","E","F"};
CompareHome(list,check);
// delete the second to last item
list.Home();
list.Left();
list.Left();
list.Delete();
check = {"B","C","D","F"};
CompareHome(list,check);
// delete the second item
list.Home();
list.Right();
list.Delete();
check = {"B","D","F"};
CompareHome(list,check);
list.Home();
list.Delete();
check = {"D","F"};
CompareHome(list,check);
list.Home();
list.Delete();
check = {"F"};
CompareHome(list,check);
list.Delete();
check = {};
CompareHome(list,check);
Footer("Delete Test");
}
BOOST_AUTO_TEST_SUITE_END()
here is my makefile
CXXFLAGS = -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion -Werror -std=c++17
OBJS = DListTTest
all: ${OBJS}
test: DListTTest
./DListTTest
memcheck: DListTTest
valgrind --leak-check=summary ./DListTTest
DListTTest: DListT.o
clean:
rm -f ${OBJS} *.o
Related
C++ How do I fix Exception thrown: write access violation. this was nullptr. on Line 20
*Create a simple linked list program to create a class list containing class node { void *info; node *next; public: node (void *v) {info = v; next = 0; } void put_next (node *n) {next = n;} node *get_next ( ) {return next;} void *get_info ( ) {return info;} }; Be able to initially fill the list. Provide functions to insert/append nodes and remove nodes from the linked list. Be able to display the contents of the list. Write a little driver program with at least 5 values passed in (so that 5 nodes are created) as you insert/append, delete and display data, showing the programs operation. Output: While displaying the data, make sure you use an informational label–using the terms “insert”, “append”, “remove” and any other term which displays the action. All data that is displayed must be displayed in a way in which the mentor can easily read and understand.* My code runs but it throws Exception thrown: write access violation. this was nullptr. on Line 20 when I debug it. In the output it also stops at Delete 04 of my list and outputs no further data after line 156. I am not sure how to fix this. I tried to force it to output the new list with another cout statement but that did not work. Any assistance would be appreciated. Entire code below. #include <iostream> #include <iomanip> using namespace std; class Node { void* info; Node* next; public: Node(void* v) { info = v; next = 0; } void put_next(Node* n) { next = n; } Node* get_next() { return next; } void* get_info() { return info; } }; class List { Node* head; public: List() { head = NULL; }; void PRINT(); void APPEND(void* info); void DELETE(void* info); }; void List::PRINT() { Node* temp = head; if (temp == NULL) { cout << "Enter Values" << endl; return; } if (temp->get_next() == NULL) { cout << *(int*)temp->get_info(); cout << " => "; cout << "Invalid" << endl; } else { while (temp != NULL) { cout << *(int*)temp->get_info(); cout << " --> "; temp = temp->get_next(); } cout << "Invalid" << endl; } } void List::APPEND(void* info) { Node* newNode = new Node(info); newNode->put_next(NULL); Node* temp = head; if (temp != NULL) { while (temp->get_next() != NULL) { temp = temp->get_next(); } temp->put_next(newNode); } else { head = newNode; } } void List::DELETE(void* info) { Node* temp = head; if (temp == NULL) { cout << "Enter Values" << endl; return; } if (temp->get_next() == NULL) { if ((int*)(temp->get_info()) == info) { delete temp; head = NULL; } } else { Node* previous = NULL; while (temp != NULL) { if ((int*)(temp->get_info()) == info) break; previous = temp; temp = temp->get_next(); } previous->put_next(temp->get_next()); delete temp; } } int main() { List list; int a = 04; int b = 11; int c = 12; int d = 15; int e = 29; int* Node1 = &a; int* Node2 = &b; int* Node3 = &c; int* Node4 = &d; int* Node5 = &e; cout << "Append: 04" << endl; list.APPEND(Node1); cout << "Append: 11" << endl; list.APPEND(Node2); cout << "Append: 12" << endl; list.APPEND(Node3); cout << "Append: 15" << endl; list.APPEND(Node4); cout << "Append: 29" << endl; list.APPEND(Node5); cout << endl << "Print List" << endl; list.PRINT(); cout << endl << "Delete 04" << endl; list.DELETE(Node1); list.PRINT(); cout << "Start New List" << endl; cout << endl << "Delete 12" << endl; list.DELETE(Node3); list.PRINT(); return 0; } SOLUTION: //Node.h #pragma once class Node { void* info; Node* next; public: Node(void* v) { info = v; next = 0; } void put_next(Node* n) { next = n; } Node* get_next() { return next; } void* get_info() { return info; } }; //List.h #pragma once #include "Node.h" #include <iomanip> class List { Node* head; public: List() { head = NULL; }; void PRINT(); void APPEND(void* info); void DELETE(void* info); }; //List.cpp #include <iostream> #include "List.h" using namespace std; void List::PRINT() { Node* temp = head; if (temp == NULL) { cout << "Enter Values" << endl; return; } if (temp->get_next() == NULL) { cout << *(int*)temp->get_info(); cout << " => "; cout << "Invalid" << endl; } else { while (temp != NULL) { cout << *(int*)temp->get_info(); cout << " --> "; temp = temp->get_next(); } cout << "Invalid" << endl; } } void List::APPEND(void* info) { Node* newNode = new Node(info); newNode->put_next(NULL); Node* temp = head; if (temp != NULL) { while (temp->get_next() != NULL) { temp = temp->get_next(); } temp->put_next(newNode); } else { head = newNode; } } void List::DELETE(void* info) { Node* temp = head; if (temp == NULL) { cout << "Enter Values" << endl; return; } if (temp->get_next() == NULL) { if ((int*)(temp->get_info()) == info) { delete temp; head = NULL; } } else { Node* previous = NULL; while (temp != NULL) { if ((int*)(temp->get_info()) == info) { // if node is head then changing the head if (temp == head) head = temp->get_next(); break; } previous = temp; temp = temp->get_next(); } // skip this operation if node is head if (temp->get_next() != head) previous->put_next(temp->get_next()); delete temp; } } //Main.cpp #include <iostream> #include "List.h" using namespace std; int main() { List list; int a = 04; int b = 11; int c = 12; int d = 15; int e = 29; int* Node1 = &a; int* Node2 = &b; int* Node3 = &c; int* Node4 = &d; int* Node5 = &e; cout << "Append: 04" << endl; list.APPEND(Node1); cout << "Append: 11" << endl; list.APPEND(Node2); cout << "Append: 12" << endl; list.APPEND(Node3); cout << "Append: 15" << endl; list.APPEND(Node4); cout << "Append: 29" << endl; list.APPEND(Node5); cout << endl << "Print List" << endl; list.PRINT(); cout << endl << "Delete 04" << endl; list.DELETE(Node1); list.PRINT(); cout << "Start New List" << endl; cout << endl << "Delete 12" << endl; list.DELETE(Node3); list.PRINT(); return 0; }
So whenever you are deleting first node, you missed to set the head to the next node of head. Commented at the parts which are modified in the else statement of DELETE function Code: else { Node* previous = NULL; while (temp != NULL) { if ((int*)(temp->get_info()) == info){ // if node is head then changing the head if (temp == head) head = temp->get_next(); break; } previous = temp; temp = temp->get_next(); } // skip this operation if node is head if (temp->get_next() != head) previous->put_next(temp->get_next()); delete temp; }
finding min value with sorted list in c++
I'm making a program with sorted list that has a variety of functions I'm supposed to build in the header source file. So far I have everything working perfectly but when I ask for the min value the first time it gives me the second highest value, 1, instead of the lowest which is 0. It gives me the lowest number the second time I ask, but I assume it's because it's not reaching the end of the linked list, but I'm not sure what to change. Here's the header #include <iostream> using std::cout; using std::endl; #ifndef LINKEDLIST_H #define LINKEDLIST_H class LinkedList { private: struct Node { int data; Node *next; }; int size; Node *head, *tail; public: LinkedList(); ~LinkedList(); // misc void display(); // sorting and searching // reverse --> sorting in descending int linearSearch(int key); void sort(); void reverse(); // various math int min(); int max(); int mean(); // adding void append(int num); void insert(int num, int pos); // removing void pop(); void remove(int pos); }; #endif // LINKEDLIST_H source file #include "linkedlist.h" // GIVEN TO STUDENTS LinkedList::LinkedList() { head = nullptr; tail = nullptr; size = 0; } LinkedList::~LinkedList() { if(head != nullptr) { Node *temp; while(head != nullptr) { temp = head->next; // deletes head delete head; // goes to next element head = temp; } } } void LinkedList::display() { Node *temp = head; for(int i = 0; i < size; i++) { cout << temp->data << "\t"; temp = temp->next; } cout << endl; } void LinkedList::append(int num) { // list is empty if(head == nullptr) { head = new Node; head->data = num; head->next = nullptr; // sets tail to head tail = head; } else { // creates new node Node *temp = new Node; // sets new node data temp->data = num; temp->next = nullptr; // sets previous tail link to new node tail->next = temp; // sets this node to new tail tail = temp; } // increments size size++; } void LinkedList::pop() { if(size > 1) { Node *temp = head; // loops to node before tail while(temp->next->next != nullptr) { temp = temp->next; } // deletes tail delete tail; // sets new tail tail = temp; tail->next = nullptr; } // if there's only one item else if(size == 1) { Node *temp = tail; // head and tail are now null head = nullptr; tail = nullptr; // deletes node delete temp; } size--; } // END GIVEN TO STUDENTS void LinkedList::insert(int num, int pos) { if(pos ==0) { Node *temp=new Node; temp->data=num; temp->next=head; head=temp; } if(pos>1) { Node *pre=new Node; Node *cur=new Node; Node *temp=new Node; cur=head; for(int i=1;i<pos+1;i++) { pre=cur; cur=cur->next; } temp->data=num; pre->next=temp; temp->next=cur; } size++; } int LinkedList::linearSearch(int key) { Node *temp = head; for(int i = 0; i < size; i++) { if(temp->data == key) { return i; } temp = temp->next; } return -1; } void LinkedList::reverse() { Node* temp = head; // Traverse the List while (temp) { Node* min = temp; Node* r = temp->next; // Traverse the unsorted sublist while (r) { if (min->data < r->data) min = r; r = r->next; } // Swap Data int x = temp->data; temp->data = min->data; min->data = x; temp = temp->next; } } void LinkedList::remove(int pos) { Node *temp = head; if(pos ==0) { head = temp->next; free(temp); } if(pos>1) { Node *current=new Node; Node *previous=new Node; current=head; for(int i=1;i<pos+1;i++) { previous=current; current=current->next; } previous->next=current->next; } size--; } void LinkedList::sort() { Node* temp = head; // Traverse the List while (temp) { Node* min = temp; Node* r = temp->next; // Traverse the unsorted sublist while (r) { if (min->data > r->data) min = r; r = r->next; } // Swap Data int x = temp->data; temp->data = min->data; min->data = x; temp = temp->next; } } int LinkedList::min() { int min = INT_MAX; for(Node* temp = head; temp != nullptr; temp = temp->next) { if (head->data < min) { min = temp->data; } } return min; } int LinkedList::max() { int max = INT_MIN; for (Node* temp = head; temp != nullptr; temp = temp->next) { if (temp->data > max) { max = temp->data; } } return max; } int LinkedList::mean() { if (!head) return -1; int count = 0; // Initialize count int sum = 0; float avg = 0.0; struct Node* current = head; // Initialize current while (current != NULL) { count++; sum += current->data; current = current->next; } // calculate average avg = (double)sum / count; return avg; } and main #include <iostream> #include "linkedlist.h" using namespace std; int main() { LinkedList nums; // adding through append nums.append(8); nums.append(6); nums.append(7); nums.append(8); nums.append(0); nums.append(9); // displays list cout << "List after append: " << endl; nums.display(); cout << endl; // adding through insert nums.insert(1, 0); nums.insert(5, 4); nums.insert(3, 7); // displays list cout << "List after inserting: " << endl; nums.display(); cout << endl; // testing searching cout << "Testing linear search:" << endl; int pres = nums.linearSearch(7); if(pres < 0) { cout << "7 is not present in the list." << endl; } else { cout << "7 can be found at location " << pres << endl; } pres = nums.linearSearch(5); if(pres < 0) { cout << "5 is not present in the list." << endl; } else { cout << "5 can be found at location " << pres << endl; } cout << endl; // does math cout << "Minimum, maximum, and average before removing any items: " << endl; cout << "Min: " << nums.min() << endl; cout << "Max: " << nums.max() << endl; cout << "Mean: " << nums.mean() << endl << endl; // displays items reversed cout << "Items reversed: " << endl; nums.reverse(); nums.display(); cout << endl; // removing through pop nums.pop(); nums.pop(); // displays list cout << "List after popping: " << endl; nums.display(); cout << endl; // removing through remove nums.remove(0); nums.remove(2); nums.remove(4); // displays list cout << "List after removing: " << endl; nums.display(); cout << endl; // displays items sorted cout << "Items sorted: " << endl; nums.sort(); nums.display(); cout << endl; // does math cout << "Minimum, maximum, and average after removing items: " << endl; cout << "Min: " << nums.min() << endl; cout << "Max: " << nums.max() << endl; cout << "Mean: " << nums.mean() << endl << endl; // testing searching cout << "Testing linear search:" << endl; pres = nums.linearSearch(7); if(pres < 0) { cout << "7 is not present in the list." << endl; } else { cout << "7 can be found at location " << pres << endl; } pres = nums.linearSearch(5); if(pres < 0) { cout << "5 is not present in the list." << endl; } else { cout << "5 can be found at location " << pres << endl; } return 0; }
I think you have a typo in your min function, it always compares head-data to the min instead of the temp node. Try this: int LinkedList::min() { int min = INT_MAX; for(Node* temp = head; temp != nullptr; temp = temp->next) { min = temp->data < min ? temp->data : min; } return min; }
C++ Sorted Doubly Linked List: Problems inserting in middle of list
below is my current in-progress code converting a singly linked to a doubly linked list. I haven't touched the delete function yet. I've gotten insert in empty list, end of list, and beginning of list apparently working. However nodes inserting in the middle seemingly fail to create a link to the previous node. My debugging lines I inserted seem to show both the n->next and n-> prev with the correct memory address, but when I go to reverseprint, any nodes inserted in the middle are missed and the links are gone. Where am I going wrong in regards to this? Code below: #include <iostream> #include <string> using namespace std; // define a node for storage and linking class node { public: string name; node *next; node *prev; }; class linkedList { public: linkedList() :top(NULL) {} bool empty() { return top == NULL; } node *getTop() { return top; } node *getEnd() { return end; } void setTop(node *n) { top = n; } void setEnd(node *p) { end = p; } void add(string); int menu(); void remove(string); ~linkedList(); void reversePrint(); friend ostream& operator << (ostream&, const linkedList&); // default output is in-order print. private: node *top; node *end; }; void main() { linkedList l; cout << l.empty() << endl; int option = 0; string s; bool go = true; while (go) { option = l.menu(); switch (option) { case 1: cout << "enter a name: "; cin >> s; l.add(s); break; case 2: cout << "enter name to be deleted: "; cin >> s; l.remove(s); break; case 3: cout << l; break; //case 4: cout << "can not be done with a singly linked list" << endl; case 4: l.reversePrint(); break; case 5: cout << "exiting" << endl; go = false; break; } } system("pause"); } void linkedList::remove(string s) { bool found = false; node *curr = getTop(), *prev = NULL; while (curr != NULL) { // match found, delete if (curr->name == s) { found = true; // found at top if (prev == NULL) { node *temp = getTop(); setTop(curr->next); delete(temp); // found in list - not top } else { prev->next = curr->next; delete(curr); } } // not found, advance pointers if (!found) { prev = curr; curr = curr->next; } // found, exit loop else curr = NULL; } if (found)cout << "Deleted " << s << endl; else cout << s << " Not Found " << endl; } void linkedList::add(string s) { node *n = new node(); n->name = s; n->next = NULL; n->prev = NULL; // take care of empty list case if (empty()) { top = n; end = n; // take care of node belongs at beginning case } else if (getTop()->name > s) { n->next = getTop(); n->prev = NULL; setTop(n); node *temp; temp = n->next; temp->prev = n; // take care of inorder and end insert } else { // insert in order case node *curr = getTop(), *prev = curr; while (curr != NULL) { if (curr->name > s)break; prev = curr; curr = curr->next; } if (curr != NULL) { // search found insert point n->next = curr; cout << n->name << " " << n << " prev " << prev << " " << prev->name << endl; n->prev = prev; prev->next = n; cout << "n->prev is: " << n->prev << " " << n->prev->name << endl; cout << "n->next is: " << n->next << " " << n->next->name << endl; } // take care of end of list insertion else if (curr == NULL) {// search did not find insert point prev->next = n; n->prev = prev; cout << "n->prev is: " << n->prev << " " << n->prev->name << endl; setEnd(n); } } } ostream& operator << (ostream& os, const linkedList& ll) { //linkedList x = ll; // put this in and the code blows up - why? node *n = ll.top; if (n == NULL)cout << "List is empty." << endl; else while (n != NULL) { os << n->name << endl; os << n << endl; if (n->next != NULL) { os << "next is " << n->next << endl; } n = n->next; } return os; } void linkedList::reversePrint() { node *n = end; if (n == NULL)cout << "List is empty." << endl; else while (n != NULL) { //cout << n->name << endl; cout << "memory address of " << n->name << " is " << n << endl; if (n->prev != NULL) { cout << "prev is " << n->prev << endl; } n = n->prev; } return; } // return memory to heap linkedList::~linkedList() { cout << "~linkedList called." << endl; node *curr = getTop(), *del; while (curr != NULL) { del = curr; curr = curr->next; delete(del); } } int linkedList::menu() { int choice = 0; while (choice < 1 || choice > 5) { cout << "\nEnter your choice" << endl; cout << " 1. Add a name." << endl; cout << " 2. Delete a name." << endl; cout << " 3. Show list." << endl; cout << " 4. Show reverse list. " << endl; cout << " 5. EXIT " << endl; cin >> choice; } return choice; }
You are not setting the prev of the current in insertion into middle, just do: n->next = curr; curr->prev = n; // <-- this
Seg Fault 11 when creating NodeQueues
void NodeQueue::push(const DataType & value){ m_back = m_back->m_next = new Node(value, NULL); } Hello, I am working with Node Queues and I am getting a seg fault 11 which I have narrowed down to my push function. I have been tweaking it for a while and cannot figure out what is wrong. Any suggestions? This is the driver class: NodeQueue nQueue; cout << "Default Constructor: " << nQueue << endl; DataType nParameter(1, 0); NodeQueue nparameter(6, nParameter); cout << "Paramaterized Constructor: " << nparameter << endl; NodeQueue nCopier(nparameter); cout << "Copy Constructor: " << nCopier << endl; nCopier.pop(); cout << "Pop Function: " << nCopier << endl; DataType nPushable(2,1); nCopier.push(nPushable); cout << "Push Function: " << nCopier << endl; nQueue = nCopier; cout << "Assignment Operator: " << nQueue << endl; NodeQueue constructors below: NodeQueue::NodeQueue() { m_front = NULL; m_back = NULL; } NodeQueue::NodeQueue(size_t size, const DataType & value) { if(size <= 0) { m_front = NULL; } else { m_front = new Node(value, NULL); Node *temp = m_front; for(size_t i = 0; i < (size); i++) { temp->m_next = new Node(value, NULL); temp = temp->m_next; } temp->m_next = NULL; } } NodeQueue::NodeQueue(const NodeQueue & other) { if(other.m_front != NULL) { m_front = new Node(other.m_front->data(), NULL); Node *newN = m_front; Node *tempN = other.m_front; while(tempN->m_next != NULL) { tempN = tempN->m_next; newN->m_next = new Node(tempN->data(), NULL); newN = newN->m_next; } newN->m_next = NULL; } else { m_front = NULL; } }
Swap first 2 nodes only in a doubly linked list
In the reverse function, I'm trying to swap the first 2 nodes only in a doubly linked list without swapping the data. It runs but it's not swapping the first 2 nodes in the list. Can someone point me in the right direction as to what I'm doing wrong? struct node { int data; node * p; // FORWARD LINK node * rp; // REVERSE LINK }; ostream & operator<<(ostream &, const node *); void addFront(node * & start, int); void cleanUp(node *); void reverse(node * &); void main() { node * a = NULL; cout << "EMPTY LIST CASE:\n"; cout << "BEFORE a is\n" << a << endl; reverse(a); cout << "AFTER a is\n" << a << endl; cleanUp(a); a = NULL; addFront(a, 10); cout << "\nONE ELEMENT LIST CASE:\n"; cout << "BEFORE a is\n" << a << endl; reverse(a); cout << "AFTER a is\n" << a << endl; cleanUp(a); a = NULL; addFront(a, 30); addFront(a, 20); cout << "\nTWO ELEMENT LIST CASE:\n"; cout << "BEFORE a is\n" << a << endl; reverse(a); cout << "AFTER a is\n" << a << endl; cleanUp(a); a = NULL; addFront(a, 60); addFront(a, 50); addFront(a, 40); cout << "\nTHREE ELEMENT LIST CASE:\n"; cout << "BEFORE a is\n" << a << endl; reverse(a); cout << "AFTER a is\n" << a << endl; cleanUp(a); a = NULL; addFront(a, 400); addFront(a, 300); addFront(a, 200); addFront(a, 100); cout << "\nFOUR ELEMENT LIST CASE:\n"; cout << "BEFORE a is\n" << a << endl; reverse(a); cout << "AFTER a is\n" << a << endl; cleanUp(a); } void reverse(node * & s) { node * n1 = s; node * n2 = s; if (n1 == NULL) return; node * temp = new node; temp->rp = n1->rp; temp->p = n1->p; n1->rp = n2->rp; n1->p = n2->p; n2->rp = temp->rp; n2->p = temp->p; if (n1->p != NULL) n1->p->rp = n1; if (n1->rp != NULL) n1->rp->p = n1; if (n2->p != NULL) n2->p->rp = n2; if (n2->rp != NULL) n2->rp->p = n2; delete temp; } void addFront(node * & start, int x) { node * t = new node; t->data = x; if (start != NULL) { t->p = start; t->rp = NULL; start->rp = t; } else { t->p = NULL; t->rp = NULL; } start = t; } void cleanUp(node * s) { node * walker, *prev; walker = s; while (walker != NULL) { prev = walker; walker = walker->p; delete prev; } } ostream & operator<<(ostream & w, const node * s) { const node * walker = s; const node * trailer = walker; w << "Forward Print " << endl; if (s == NULL) { w << "EMPTY LIST"; } else { while (walker != NULL) { w << walker->data << ' '; trailer = walker; walker = walker->p; } } w << endl << "Reverse Print " << endl; if (trailer == NULL) { w << "EMPTY LIST"; return w; } while (trailer != NULL) { w << trailer->data << ' '; trailer = trailer->rp; } return w; } Updated with complete program.
Here's an updated reverse: void reverse(node * & s) { node * n1 = s; if (n1 == NULL) return; node * n2 = n1->p; if (n2 == NULL) return; node *temp; node *n3; n3 = n2->p; temp = n1->rp; n1->p = n3; n1->rp = n2; n2->rp = temp; n2->p = n1; if (n3 != NULL) n3->rp = n1; s = n2; } NOTE: even if temp had to remain as you defined it, there was no need to allocate and delete it. I would have used node temp and replaced temp->blah with temp.blah