Swap first 2 nodes only in a doubly linked list - c++

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

Related

infinite copy list loop with copy constructor and pointers

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

I m not getting correct output for pre and post order

// in this code I first created nodes stored them in a que and keep on removing them as I entered their left and right children. To make a node have no further children I entered -1 while entering data. Here I am not able to understand what is wrong with my code , I am getting wrong output for preorder and postorder traversals. It would be really great if you guys could help me out.
I made a class que for queue ds and inherited it in tree class in protected mode.
#include <iostream>
#include <math.h>
using namespace std;
struct node
{
int data;
struct node *left;
struct node *right;
};
class que
{
protected:
int start;
int end;
struct node **arr;
int n;
public:
que(int x)
{
n = x;
arr = new struct node *[n];
start = -1;
end = -1;
}
void isfull()
{
if (end == n)
cout << "Queue is full !!!" << endl;
return;
}
int isempty()
{
if (start == end)
{
start = -1;
end = -1;
cout << "Queue is empty !!!" << endl;
return 1;
}
return 0;
}
void enqu(struct node *x)
{
if (end == n)
{
cout << "called" << endl;
isfull();
return;
}
end++;
arr[end] = x;
}
struct node *dequ(void)
{
struct node *q = 0;
if (start == end)
{
isempty();
return q;
}
start++;
cout << "Element removed is ->" << arr[start] << endl;
return arr[start];
}
};
class tree : protected que
{
public:
struct node *head;
struct node *ptr;
tree(int n) : que(n)
{
head = 0;
ptr = 0;
enter();
}
void create(void)
{
ptr = new struct node;
ptr->left = 0;
ptr->right = 0;
}
void enter(void)
{
struct node *p;
if (head == 0)
{
create();
cout << "Enter root element of tree -> ";
cin >> ptr->data;
head = ptr;
cout << "Enquing ptr - " << ptr << endl;
enqu(ptr);
}
while (!isempty())
{
p = dequ();
cout << "Enter left child ->";
int x;
cin >> x;
if (x != -1)
{
create();
p->left = ptr;
ptr->data = x;
cout << "Enquing ptr - " << ptr << endl;
enqu(ptr);
}
cout << "Enter right child ->";
cin >> x;
if (x != -1)
{
create();
p->right = ptr;
ptr->data = x;
cout << "Enquing ptr - " << ptr << endl;
enqu(ptr);
}
}
}
void inorder(struct node *yes)
{
if (yes != 0)
{
inorder(yes->left);
cout << "--> " << yes->data << endl;
inorder(yes->right);
}
}
void preorder(struct node *yes)
{
if (yes != 0)
{
cout << "--> " << yes->data << endl;
inorder(yes->left);
inorder(yes->right);
}
}
void postorder(struct node *yes)
{
if (yes != 0)
{
inorder(yes->left);
inorder(yes->right);
cout << "--> " << yes->data << endl;
}
}
int count(struct node *yes)
{
static int x = 0, y = 0;
if (yes == 0)
return 0;
x = count(yes->left);
y = count(yes->right);
return x + y + 1;
}
int height(struct node *yes)
{
static int a = 0, b = 0;
if (yes == 0)
return 0;
a = count(yes->left);
b = count(yes->right);
if (a > b)
return a + 1;
else
return b + 1;
}
};
int main()
{
int x;
cout << "Enter height of tree - ";
cin >> x;
int max = 0;
max = pow(2, x + 1) - 1;
tree tr(max);
cout << "Preorder traversal -- " << endl;
tr.preorder(tr.head);
cout << "Inorder traversal -- " << endl;
tr.inorder(tr.head);
cout << "Postorder traversal -- " << endl;
tr.postorder(tr.head);
cout << "\n No. of elements -- " << tr.count(tr.head);
cout << "\n Height of tree --" << tr.height(tr.head);
}
The preorder and postorder functions doesn't call themselves recursively. Instead they call the inorder function, which will lead to all but the root will be printed using inorder.

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;
}

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;
}
}