I'm trying to implement a simple doubly linked list with exposed nodes in C++ like this
(some methods omitted, should be pretty clear as to what they do):
template<typename T>
class Node
{
public:
Node(T _value)
{
m_Data = _value;
m_HasParent = false;
m_HasNext = false;
m_Parent = NULL;
m_Next = NULL;
}
void insertAfter(Node<T>* _item)
{
m_Next = _item;
m_HasNext = true;
_item->insertBefore(this);
}
void insertBefore(Node<T>* _item)
{
if(m_HasParent)
{
m_Parent->insertAfter(_item);
_item->insertAfter(this);
}
else
{
m_Parent = _item;
m_HasParent = true;
}
}
private:
T m_Data;
Node<T>* m_Parent;
Node<T>* m_Next;
bool m_HasParent;
bool m_HasNext;
};
template<typename T>
class LinkedList
{
public:
LinkedList()
{
m_Root = NULL;
m_HasRoot = false;
}
~LinkedList()
{
if(m_HasRoot)
{
delete m_Root;
}
}
void pushFront(T _value)
{
if(m_HasRoot)
{
Node<T>* node = new Node<T>(_value);
m_Root->insertBefore(node);
node->insertAfter(m_Root);
m_Root = node;
}
else
{
m_Root = new Node<T>(_value);
m_HasRoot = true;
}
}
void pushBack(T _value)
{
if(m_HasRoot)
{
Node<T>* last = m_Root;
while(true)
{
if(last->getHasNext())
{
last = last->getNext();
}
else
{
break;
}
}
Node<T>* node = new Node<T>(_value);
last->insertAfter(node);
return;
}
else
{
m_Root = new Node<T>(_value);
m_HasRoot = true;
}
}
T operator[](int _i)
{
Node<T>* last = m_Root;
for(int i = 0; i <= _i; i++)
{
if(last->getHasNext())
{
last = last->getNext();
}
else
{
break;
}
}
return last->getData();
}
private:
Node<T>* m_Root;
bool m_HasRoot;
};
However, when executing the following little test:
int main(int argc, char** argv)
{
LinkedList<int> l;
l.pushBack(0);
l.pushBack(1);
l.pushBack(2);
l.pushBack(3);
int count = l.getCount();
std::cout << "count: " << count << std::endl;
for(int i = 0; i < count; i++)
{
std::cout << "Value at [" << i << "]: " << l[i] << std::endl;
}
std::string s;
std::cin >> s;
return 0;
}
I expect to see the numbers 0, 1, 2, 3 printed out in this order, but this is what I get:
For some reason, the insertion to the back doesn't quite work. I find nothing fundamentally wrong with my code, can anybody spot the problem? This is on MinGW 5.1, 64bit, Windows 10 64bit. However, when executing this problem on runnable.com, everything seems to work just fine?? See this draft. Is this a bug in MinGW or some mistake on my part?
Edit 1
Now this is weird, sometimes it seems to work in runnable, and sometimes it yields the same result as on my local machine... I'm thoroughly confused.
Try changing the loop condition inside ListWidget::operator[] from i <= _i to i < _i. There should be no iteration for _i equal 0.
The sign is that you're starting printing from the second element i.e. 1 and printing the last element twice. You forgot about the root node.
Note that you're checking if a node has a succesor, but you aren't checking if the list is not empty (m_root != nullptr). Make this consistent - either remove all possible cases of UB or don't check anything.
Related
I write a code for insertion sort for integer data in linked list in c++, I referred to the algorithms on the Internet, and finally took the following code using array as a basic concept for my version.
however, the sorting always ignore my first element,(but all the other element is ordered well).
I have tried checking my loop statement, checking the pointer address while looping (because my key pointer loop at first time didn't go into the judge pointer loop), checking the shifting mechanism while comparing, but I cannot find my logic problem.
(I know someone would said I doesn't provide enough data for you to help me, but I have been checking these things for two days, including asking friends and searching the solutions existed on website. So I really hope someone can answer me without blame, thank you.)
array version(on the internet)
#include <iostream>
void InsertionSort(int *arr, int size){
for (int i = 1; i < size; i++) {
int key = arr[i];
int j = i - 1;
while (key < arr[j] && j >= 0) {
arr[j+1] = arr[j];
j--;
}
arr[j+1] = key;
}
}
linked list version(by my own)
Node class used in my version
class Node
{
public:
Node()
{
next = NULL;
pre = NULL;
}
Node(int n)
{
data = n;
next = NULL;
pre = NULL;
}
int getData() { return data; }
Node *getNext() { return next; }
Node *getPre() { return pre; }
void setData(int d) { data = d; }
void setNext(Node *n) { next = n; }
void setPre(Node *p) { pre = p; }
private:
int data;
Node *next, *pre;
};
class List
{
public:
List() { list = NULL; }
List(int n) { generate(n); }
void generate(int n)
{
int j;
list = NULL;
for(j = 0;j < n;j ++)
generate();
}
void generate()
{
Node *buf = new Node(rand());
buf->setNext(list); //list->NODE2.next->NODE1.next->NULL
if(list != NULL)
list->setPre(buf);
list = buf;
}
void insertionSort()
{
bool breakByCompare;
Node* keyptr;
Node* judgeptr;// judge is the value that is going to compare with key
int key;
for(keyptr = list->getNext(); keyptr != NULL;
keyptr = keyptr->getNext()){
//if we set list as 5,7,6 ; 6 is key
key = keyptr->getData();//store the key value for the setting after shifting
breakByCompare = 0;
for(judgeptr = keyptr->getPre() ; judgeptr->getPre()!= NULL;
judgeptr= judgeptr->getPre()){
//list: 5,7,6 ; 7 is judge
if(judgeptr->getData() > key){
// 7>6, so we shift 7 to the position which was for 6
judgeptr->getNext()->setData(judgeptr->getData());// list: 5,7,7 ;
cout << judgeptr->getData() << " , " << keyptr->getData() << endl;
}
else{
break;
}
}
judgeptr->getNext()->setData(key);// list: 5,6,7
}
}
void print()
{
Node *cur = list;
while(cur != NULL)
{
cout<<cur->getData()<<" ";
cur = cur->getNext();
}
cout<<endl;
}
private:
Node *list;
};
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#define SIZE 100
int main()
{
srand(time(NULL));
List *l = new List(10);
l->print();
l->insertionSort();
l->print();
}
One of the most important difference between a linked list and an array is that it is sometimes required to handle the first element as a special case.
Here is a fixed version of your sorting method :
void insertionSort()
{
bool breakByCompare;
Node* keyptr;
Node* judgeptr;
int key;
for(keyptr = list->getNext(); keyptr != NULL; keyptr = keyptr->getNext()){
key = keyptr->getData();
breakByCompare = 0;
// I replaced judgeptr->getPre() by judgeptr in the condition
// to allow the backward loop to go until the root
for(judgeptr = keyptr->getPre() ; judgeptr != NULL; judgeptr= judgeptr->getPre()){
if(judgeptr->getData() > key){
judgeptr->getNext()->setData(judgeptr->getData());
cout << judgeptr->getData() << " , " << key << endl;
}
else break;
}
// Here is the special case : we must support a null judgeptr
// and replace its next element by the list
if (judgeptr) judgeptr->getNext()->setData(key);
else list->setData(key);
}
}
I am a java programmer teaching myself C++.
While writing a binary tree I found that my program did not "add" values to the tree.
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
using namespace std;
class BinaryTree {
struct Node {
public:
int val;
Node* left;
Node* right;
Node::Node(int v) {
val = v;
left = nullptr;
right = nullptr;
}
};
public:
BinaryTree() {
root = nullptr;
}
int size = 0;
int length();
bool BinaryTree::add(int v);
void printTree();
private:
void printTree(Node* n);
Node* root;
};
bool BinaryTree::add(int v) {
if (root == nullptr) {
root = new Node(v);
++size;
return true;
}
Node* ref = root;
cout << ref->val;
while (ref != nullptr) {
if (v < ref->val) {
ref = ref->left;
}
else if (v > ref->val) {
ref = ref->right;
}
else if (v == ref->val) {
return false;
}
}
Node *newNode = new Node(v);
ref = newNode;
++size;
return true;
}
void BinaryTree::printTree() {
printTree(root);
}
void BinaryTree::printTree(Node* n) {
if (n == nullptr) {
return;
}
printTree(n->left);
cout << n->val << endl;
printTree(n->right);
}
int BinaryTree::length() {
return size;
}
void main(int i) {
BinaryTree tree = BinaryTree();
tree.add(6);
tree.add(3);
tree.add(5);
tree.add(7);
tree.add(1);
tree.add(0);
tree.add(0);
tree.printTree();
cout << "binary tree sz is " << tree.length() << endl;
while (true) {};
}
I have been unable to find the problem in regards to why the tree doesn't commit new Nodes except the root.
I used "new" in the code when writing (ref = new Node) etc in the adds method because this should prevent the new Node from being destroyed once it leaves the scope.
If anyone can enlighten me on this issue I will be greatly thankful.
To add a node to the tree you have to link it to some existing node, as in
existing_node->{left or right} = new_node;
Once ref becomes nullptr, you don't have a valid existing node anymore, and it is too late to do anything. Instead, traverse the tree as long as ref->{left or right} is valid:
if (v < ref->val) {
if (ref->left) {
ref = ref->left;
} else {
ref->left = newNode;
return true;
}
}
// etc for v > ref->val
Everything in my program works perfectly, except it is not showing the count for the field. I tried to change some codes but it does not seem to display it in the output. It seems like a easy mistake or something obviously but I have no idea why it doesn't display it. Can someone help?
#include <iostream>
using namespace std;
template<class T>
class BinaryTree
{
struct Node
{
T data;
Node* leftChild;
Node* rightChild;
Node(T dataNew)
{
data = dataNew;
leftChild= NULL;
rightChild = NULL;
}
};
private:
Node* root;
void Add(T new_Data, Node* &the_Root)
{
if (the_Root == NULL)
{
the_Root = new Node(new_Data);
return;
}
if (new_Data < the_Root->data)
Add(new_Data, the_Root->leftChild);
else
Add(new_Data, the_Root->rightChild);
}
int countTree(Node* the_Root)
{
if (the_Root == NULL)
return 0;
else {
int count = 1;
count += countTree(the_Root->leftChild);
count += countTree(the_Root->rightChild);
return count;
}
}
void PrintTree(Node* the_Root)
{
if (the_Root != NULL)
{
cout << the_Root->data <<" ";
PrintTree(the_Root->leftChild);
PrintTree(the_Root->rightChild);
}
}
public:
BinaryTree()
{
root = NULL;
}
void AddItem(T new_Data)
{
Add(new_Data, root);
}
int countTree()
{
return countTree(root);
}
void PrintTree()
{
PrintTree(root);
}
};
int main()
{
BinaryTree<int> *myBT = new BinaryTree<int>();
myBT->AddItem(6);
myBT->AddItem(5);
myBT->AddItem(4);
myBT->AddItem(18);
myBT->AddItem(6);
myBT->PrintTree();
myBT->countTree();
}
The count won't be shown simply because you didn't write any code to show the count.
Try changing myBT->countTree(); to cout << myBT->countTree();, and you will see the count printed.
You aren't actually doing anything with the result of myBT->countTree(). Try printing it:
std::cout << myBT->countTree() << std::endl;
For one of my programming classes, we are required to design a program that can be ran through the provided "stress tests" that our instructor wrote himself.
We are working with nodes and linked lists but in a way that is different than any of the YouTube videos I have looked at on the subject.
I've been tearing my hair out for the past couple of days trying to figure out what is wrong with my program but I'm having no luck.
Here is the code for my Node.cpp file (didn't include Node.h)
#include "Node.h"
Node::Node() {
m_value = 0;
m_next = nullptr;
}
void Node::setValue(int val) {
m_value = val;
}
int Node::getValue() const {
return m_value;
}
void Node::setNext(Node* prev) {
m_next = prev;
}
Node* Node::getNext() const {
return m_next;
}
Here is my LinkedList.cpp
#include <iostream>
#include <vector>
#include "LinkedList.h"
LinkedList::LinkedList() {
m_front = nullptr;
m_size = 0;
}
LinkedList::~LinkedList() {
// Deconstructor
m_size = 0;
Node* a = m_front;
Node* b = a->getNext();
while (a->getNext() != NULL) {
delete a;
a = b;
b = b->getNext();
}
delete a;
a = NULL;
}
bool LinkedList::isEmpty() const{
if (m_size == 0) {
return true;
}
else {
return false;
}
}
int LinkedList::size() const {
return m_size;
}
bool LinkedList::search(int value) const {
if (m_size == 0) {
return false;
}
else if (m_size == 1) {
if (m_front->getValue() == value) {
return true;
}
else {
return false;
}
}
else {
Node* a = m_front;
for (int i = 0; i < m_size; i++) {
if (a->getValue() == value) {
return true;
}
else {
a = a->getNext();
}
}
return false;
}
}
void LinkedList::printList() const {
std::cout << "List: ";
if (m_size == 0) {
// Print Nothing
}
else if (m_size == 1) {
std::cout << m_front->getValue();
}
else {
Node* a = new Node();
a = m_front;
int b = m_front->getValue();
std::cout << b << ", ";
while (a->getNext() != NULL) {
a = a->getNext();
if (a->getNext() == NULL) {
std::cout << a->getValue();
}
else {
std::cout << a->getValue() << ", ";
}
}
}
std::cout << std::endl;
}
void LinkedList::addBack(int value) {
Node* a = new Node();
a->setValue(value);
if (m_size == 0) {
m_front = a;
}
else {
Node* b = new Node();
b = m_front;
while (b->getNext() != NULL) {
b = b->getNext();
}
b->setNext(a);
}
m_size++;
}
void LinkedList::addFront(int value) {
Node* a = new Node(); // Check later
a->setNext(m_front);
a->setValue(value);
m_front = a;
m_size++;
}
bool LinkedList::removeBack() {
if (m_size == 0) {
return false;
}
else {
Node* a = new Node();
Node* b = new Node();
a = m_front;
while (a->getNext() != NULL) {
b = a;
a = a->getNext();
}
b->setNext(nullptr);
delete a;
a = NULL;
m_size--;
return true;
}
}
bool LinkedList::removeFront() {
if (m_size == 0) {
return false;
}
else {
Node* a = new Node();
a = m_front;
m_front = m_front->getNext();
delete a;
a = NULL;
m_size--;
return true;
}
}
std::vector<int> LinkedList::toVector() const {
if (m_size == 0) {
std::vector<int> b;
return b;
}
else {
std::vector<int> a(m_size);
Node* b = new Node();
b = m_front;
for (int i = 0; i < m_size; i++) {
a[i] = b->getValue();
b = b->getNext();
}
return a;
}
}
Basically, I've tested my program on my own and I've been able to make a linked list and run all my add and remove functions and print out the lists just fine. My problem is I run the test that our instructor gave us and it looks like this at the point where I'm having problems (Those print messages are in another file but all they seem to do is print the string arguments that are passed)
int score = 0;
const int MAX_SCORE = 90;
std::cerr << "\n\n=========================\n";
std::cerr << " RUNNING TEST SUITE \n";
std::cerr << "=========================\n\n";
//Run test and award points where appropriate
score += test1() ? 2 : 0;
score += test2() ? 2 : 0;
score += test3() ? 3 : 0;
This goes on for 18 tests, but my program never "makes" it past the first one. It passes the first test then all of a sudden throws an error.
bool Test_LinkedList::test1()
{
LinkedList list;
bool isPassed = false;
printTestMessage("size of empty list is zero");
isPassed = list.size() == 0;
printPassFail(isPassed);
return (isPassed);
}
I actually get this output before it crashes
=========================
RUNNING TEST SUITE
=========================
Test 1: size of empty list is zero: PASSED
So it passes the first test but never makes it out of there. What I mean is that I have tried throwing in a cout message around
score += test1() ? 2 : 0;
std::cout << "Done with test 1"
score += test2() ? 2 : 0;
score += test3() ? 3 : 0;
But that is never outputted. Instead my program breaks and Visual Studio pops up with a message saying
Exception thrown: read access violation.
this was nullptr.
If there is a handler for this exception, the program may be safely continued.
Then it points me to my method in Node.cpp that is
Node* Node::getNext() const {
return m_next;
}
Sorry, I know this is a lot of text to read through but right now I'm beyond stumped and there is no time for me to go into office hours as it is due early tomorrow morning.
edit: i tried omitting the first test and running it. It gets through the next 6 tests but then fails on the 7th (8th) with the same exact error.
bool Test_LinkedList::test8()
{
LinkedList list;
bool isPassed = false;
printTestMessage("search returns false on empty list");
isPassed = !list.search(42);
printPassFail(isPassed);
return (isPassed);
}
The LinkedList destructor has a couple of problems. First, it's pointless to set m_size to 0 and a to NULL since they will both go away at the end of the destructor. More important, the code will attempt to dereference a null pointer when the list is empty:
Node* a = m_front; // okay, gets that head pointer
Node* b = a->getNext(); // bang!!
Here's a cleaner way to write it:
Node* a = m_front;
while (a != NULL) {
Node *temp = a->getNext();
delete a;
a = temp;
}
Can anybody tell me why my main program is printing out 9460301 instead of 350?
I'm just trying to insert a struct as a single item into a linked list. The struct has atrributes x and y. I then wish to print out the x attribute of the struct in my linked list. I have a huge program written out, and I tried stripping it down on this post just to what's neccessary to view for this new issue that has arisen for me.
My chunk struct and Linkedlist class are as follows:
struct chunk{
int x;
int y;
};
template <class T>
class linkedList
{
public:
class node
{
public:
///node class attributes
T mPayload;
node* mNext;
///constructor
node(T toucan):mPayload(toucan),mNext(NULL)
{}
///destructor
~node()
{
///cascading delete
if(mNext)
delete mNext;
}
///node class methods
};
///linkedList class attributes
node* mStart;
///constructor
linkedList():mStart(NULL)
{}
///destructor
~linkedList()
{
///initializes the cascading delete.
if(mStart)
delete mStart;
}
///linkedList class methods
T mReturnT(int indx)
{
if(!mStart)
{
T emptyList;
return emptyList;
}
else
{
node* cur;
for(int i = 0; i<indx+1; i++)
{
if(cur->mNext == NULL)
{
cout << "Indx out of range. Deleting last item." << endl;
break;
}
cur = cur->mNext;
}
return cur->mPayload;
}
}
void mInsertHelper(node* blah, T data)
{
if(blah->mNext != NULL)
mInsertHelper(blah->mNext, data);
else
{
blah->mNext = new node(data);
blah->mNext->mNext = NULL;
}
}
void mInsert(T data)
{
if(mStart == NULL)
{
mStart = new node(data);
//mStart->mPayload = data;
}
else
mInsertHelper(mStart, data);
}
T mPop()
{
///Removes the last item in the list,
///and returns it.
if(!mStart)
return NULL;
else
{
node* cur = mStart;
while(cur->mNext)
{
cur = cur->mNext;
}
T var = cur->mPayload;
delete cur;
return var;
}
}
int mSize()
{
if(!mStart)
return 0;
else
{
node* cur = mStart;
int counter = 1;
while(cur->mNext)
{
cur = cur->mNext;
counter++;
}
delete cur;
return counter;
}
}
};
And my main.cpp:
int main()
{
chunk head;
head.x = 350;
head.y = 600;
linkedList<chunk> p1Snake;
p1Snake.mInsert(head);
cout<<p1Snake.mReturnT(0).x<<endl;
}
You never initialise cur before iterating through it.
node* cur; // <-- UNINITIALISED!
for(int i = 0; i<indx+1; i++)
{
if(cur->mNext == NULL)
{
cout << "Indx out of range. Deleting last item." << endl;
break;
}
cur = cur->mNext;
}
return cur->mPayload;
That first line should be:
node* cur = mStart;
And I think you should use indx instead of indx+1 in that loop... Unless you were using a dummy-head scheme, which you're not.
The logic inside the loop for detecting out-of-bounds is a bit wrong, also. How about revamping the whole thing:
node* cur = mStart;
while( cur && indx > 0 ) {
cur = cur->mNext;
indx--;
}
if( !cur ) {
cout << "Indx out of range." << endl;
return T();
}
return cur->mPayload;