I'm making a simple linked list with a classic functions. The elements in this list should not be repeated and should be in an order. The function find recieves two parameters: The valor that should be finded and the pointer to save the node that has it. Everything is going well, but the pointer keeps being nullptr because is not saving the current memory address. I can't understand why my pointer is not pointing to the current node. Please Help me.
template <class T>
class simpleNode {
public:
T data;
simpleNode<T>* next = NULL;
simpleNode(T newData) {
data = newData;
}
};
template <class T, class C>
class simpleLinkedListOnePointer {
public:
simpleNode<T>* head;
C comparator;
simpleLinkedListOnePointer <T, C>() {
head = NULL;
}
bool find(T x, simpleNode<T>*& p) {
p = head;
while (p && comparator(p->data, x))
p = p->next;
return p?true:false;
}
bool insert(T x) {
simpleNode<T>* ptr;
if (find(x, ptr)) {
return false;
}
simpleNode<T>* ptrAdd = new simpleNode<T>(x);
if (!ptr) {
ptrAdd->next = head;
head = ptrAdd;
return true;
}
else {
cout << "ESTE ES EL NODO APUNTADO POR PTR: " << ptr->data << endl;
ptrAdd->next = ptr->next;
ptr->next = ptrAdd;
return true;
}
}
bool remove(T x) {
return 1;
}
void print() {
simpleNode<T>* p = head;
while (p) {
cout << p->data << "->";
p = p->next;
}
cout << endl;
}
};```
Related
So, I am trying to implement a stack using a linked list as the parent, and have written these two classes:
template <class T>
class LL {
public:
struct Node {
Node* next = nullptr;
T data = 0;
};
Node* head;
public:
LL();
~LL();
void insert(T item);
void append(T item);
virtual void disp();
};
template<class T>
LL<T>::LL(){ head = nullptr; }
template<class T>
void LL<T>::insert(T item)
{
Node* newNode = new Node;
newNode->data = item;
if (head == nullptr) head = newNode;
else
{
Node* loop = head;
Node* prev = nullptr;
while (loop != nullptr && loop->data < item) {
prev = loop;
loop = loop->next;
}
if (prev == nullptr) { //head
newNode->next = head;
head = newNode;
}
else { //insert
newNode->next = prev->next;
prev->next = newNode;
}
}
}
template<class T>
void LL<T>::append(T item)
{
Node* newNode = new Node;
newNode->data = item;
if (head == nullptr) head = newNode;
else
{
Node* loop = head;
while(loop->next != nullptr)
loop = loop->next;
loop->next = newNode;
}
}
template<class T>
void LL<T>::disp()
{
cout << "[";
if (head) {
if (head->next == nullptr)
cout << head->data;
else {
Node* loop = head;
while (loop->next != nullptr)
{
cout << loop->data << ",";
loop = loop->next;
}
cout << loop->data;
}
}
cout << "]" << endl;
}
template<class T>
LL<T>::~LL()
{
if (head != nullptr) {
while (head != nullptr) {
Node* temp = head;
head = head->next;
delete temp;
temp = nullptr;
}
}
}
template<class T>
class stack: public LL<T> {
private:
public:
stack();
~stack();
virtual void push(T item);
void pop(T ret);
bool empty();
void disp();
};
template<class T>
stack<T>::stack():LL<T>()
{
}
template<class T>
stack<T>::~stack()
{
}
template<class T>
void stack<T>::push(T item){ this->append(item); }
template<class T>
void stack<T>::pop(T ret)
{
ret = this->head->data;
this->head = this->head->next;
}
template<class T>
bool stack<T>::empty() { return false;}
template<class T>
void stack<T>::disp()
{
Node<T>* loop = this->head;
cout << "-" << endl;
while (loop) {
cout << loop->data << endl;
loop = loop->next;
}
cout << "-";
}
The trouble comes in the very last function, "disp()", where it does not give me access to the Node struct. It gives me the error "'Node': identifier not found". This prevents me from declaring the needed "loop" variable. As far as I know, the Node struct should be inherited from the LL class and protected in the stack class. Thus, I should be able to access it directly.
Any ideas?
Ok, so I got around it using this post:
Declaring a struct in a template class, undefined for member functions
My disp() function now looks like this:
template<class T>
void stack<T>::disp()
{
typename LL<T>::Node* loop = this->head;
cout << "-" << endl;
while (loop) {
cout << loop->data << endl;
loop = loop->next;
}
cout << "-";
}
enter image description hereMy code that I recently build have this message :
clang: error: linker command failed with exit code 1 (use -v to see invocation)
after I build the whole project.
I have tried:
clean the build and build
I have saved my project file as workspace file and ran the file
In build settings there is no metaDataLevel so I can't flag it to None
Node.h
template<class dataType>
class Node {
private:
dataType data;
Node* next;
Node* prev;
public:
Node();
Node(dataType);
bool setNext(Node*);
bool setPrev(Node*);
Node* getNext() const;
Node* getPrev() const;
void setData(const dataType&);
dataType getData() const;
bool add(const dataType);
bool remove(const dataType);
~Node();
};
template<class dataType>
Node<dataType>::Node()
{
next = nullptr;
prev = nullptr;
}
I am not sure if this will help or not but i'll place the implementation below:
template<class dataType>
Node<dataType>::Node(dataType d)
{
data = d;
next = nullptr;
prev = nullptr;
}
template<class dataType>
bool Node<dataType>::setNext(Node* head)
{
this->next = head;
return true;
}
template<class dataType>
bool Node<dataType>::setPrev(Node* head)
{
this->prev = head;
return true;
}
template<class dataType>
Node<dataType>* Node<dataType>::getNext() const
{
return next;
}
template<class dataType>
Node<dataType>* Node<dataType>::getPrev() const
{
return prev;
}
template<class dataType>
void Node<dataType>::setData(const dataType& d){
this->data = d;
}
template<class dataType>
dataType Node<dataType>::getData() const
{
return data;
}
template<class dataType>
bool Node<dataType>::add(const dataType d){
Node* dummy = new Node(d);
dummy->setNext(this);
this->setPrev(dummy);
dummy->setPrev(nullptr);
this = dummy;
return true;
}
template<class dataType>
bool Node<dataType>::remove(const dataType d){
Node* pointer = this;
while(pointer != nullptr)
{
if(pointer->getData() == d)
{
if(pointer->getPrev() == nullptr)
{
this = pointer->getNext();
pointer = pointer->getNext();
delete pointer->getPrev();
pointer->setPrev(nullptr);
}
else if(pointer->getNext() == nullptr)
{
pointer->getPrev()->setNext(nullptr);
delete pointer;
pointer = nullptr;
}
else
{
pointer->getPrev()->setNext(pointer->getNext());
pointer->getNext()->setPrev(pointer->getPrev());
Node* dummy = pointer;
pointer = pointer->getNext();
delete dummy;
}
}
}
return true;
}
template<class dataType>
Node<dataType>::~Node(){
Node* pointer = this;
Node* holder = this->getNext();
while (holder != nullptr)
{
delete pointer;
pointer = holder;
holder = holder->getNext();
}
delete pointer;
delete holder;
}
here is the testing code i used:
int main(){
int v = 10;
string d = "X";
Node<int>* headInt = new Node<int>(v);
Node<string>* headString = new Node<string>();
headString->setData(d);
cout << "headInt contain" << headInt->getData() << ", ";
cout << "headString contain" << headString->getData() << endl << endl;
headInt->add(22);
headString->add("XXII");
cout << "headInt contain" << headInt->getData() << ", ";
cout << "headString contain" << headString->getData() << endl << endl;
headInt->remove(22);
headString->remove("XXII");
cout << "headInt contain" << headInt->getData() << ", ";
cout << "headString contain" << headString->getData() << endl << endl;
}
I am expecting to have this as my result :
headInt contain 10,
headString contain X
headInt contain 22,
headString contain XXII
headInt contain 10,
headString contain X
I'm new with data structures in C++, and i'm trying to do a doubly linked list with templates. All the examples that i have seen are only for 1 element of the template node, so i'm trying to put 2 elements in the template node in the list, but i don't know how to do it, anyway, i tried to make the list.
Here's the code:
#include<iostream>
#include<cstring>
using namespace std;
template<class T>
// node class
class node
{
public:
node();
node(T);
~node();
node *next;
T data[2];
void borra_todo();
void print();
};
// by defect
template<typename T>
node<T>::node()
{
data[0] = NULL;
data[1] = NULL;
next = NULL;
}
// by parameter
template<typename T>
node<T>::node(T data_)
{
data[0] = data_[0];
data[1] = data_[1];
next = NULL;
}
// delete nodes
template<typename T>
void node<T>::borra_todo()
{
if (next)
next->borra_todo();
delete this;
}
// node printing
template<typename T>
void node<T>::print()
{
cout << data[0] << " " << data[1] << "->";
}
template<typename T>
node<T>::~node() {}
// list
template <class T>
class list
{
private:
node<T> *m_head;
int m_num_nodes;
public:
list();
~list();
void add_head(T);
void add_end(T);
void add_sort(T);
void fill(char r[30], char n[30]);
void search(T);
void del_by_data(T);
void print();
};
template<typename T>
list<T>::list()
{
m_num_nodes = 0;
m_head = NULL;
}
//add in the beginning
template<typename T>
void list<T>::add_head(T data_)
{
node<T> *new_node = new node<T>(data_);
node<T> *temp = m_head;
if (!m_head)
{
m_head = new_node;
}
else
{
new_node->next = m_head;
m_head = new_node;
while (temp)
{
temp = temp->next;
}
}
m_num_nodes++;
}
// add to the last
template<typename T>
void list<T>::add_end(T data_)
{
node<T> *new_node = new node<T> (data_);
node<T> *temp = m_head;
if (!m_head)
{
m_head = new_node;
}
else
{
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = new_node;
}
m_num_nodes++;
}
// it is supposed that sorts items in the list ...
template<typename T>
void list<T>::add_sort(T data_)
{
node<T> *new_node = new node<T> (data_);
node<T> *temp = m_head;
if (!m_head)
{
m_head = new_node;
}
else
{
for (int i =0; i <= 1; i++)
{
if (m_head->data[0] > data_[i])
{
new_node->next = m_head;
m_head = new_node;
}
else
{
while ((temp->next != NULL) && (temp->next->data[0] < data_[i]))
{
temp = temp->next;
}
new_node->next = temp->next;
temp->next = new_node;
}
}
m_num_nodes++;
}
}
// sort adding ...
template<typename T>
void list<T>::fill(char rfc[30])
{
char temprfc[30];
char tempnombre[30];
temprfc = "DUDE010101R0";
tempnombre = "Dude";
add_sort(temprfc, tempnombre);
temprfc = "AUDE010101R1";
tempnombre = "Commander";
add_sort(temprfc, tempnombre);
}
// print list
template<typename T>
void list<T>::print()
{
node<T> *temp = m_head;
if (!m_head)
{
cout << "List is empty" << endl;
}
else
{
while (temp)
{
temp->print();
if (!temp->next)
cout << "NULL\n";
temp = temp->next;
}
}
cout << endl;
}
// search the list
template<typename T>
void list<T>::search(T data_)
{
node<T> *temp=m_head;
int cont=1;
int cont2=0;
while(temp)
{
if(strcmp(temp->data,data_[0]))
{
cout<<"Element found " << temp->data;
cout << " in position: " << cont << endl;
cont2++;
}
temp=temp->next;
cont++;
}
if(cont2==0)
{
cout << "Element not found"<<endl;
}
}
// ... delete by data
template<typename T>
void list<T>::del_by_data(T data_)
{
node<T> *temp = m_head;
node<T> *temp1 = m_head->next;
int cont =0;
if (m_head->data == data_)
{
m_head = temp->next;
}
else
{
while (temp1)
{
if (temp1->data == data_)
{
node<T> *aux_node = temp1;
temp->next = temp1->next;
delete aux_node;
cont++;
m_num_nodes--;
}
temp = temp->next;
temp1 = temp1->next;
}
}
if (cont == 0)
{
cout << "No data" << endl;
}
}
// destroy the constructor
template<typename T>
list<T>::~list() {}
int main()
{
list<char> list1;
char element1[30];
char element2[30];
int dim, choice, pos;
do{
cout << "Select a choice.\n";
cout << "1. Print list\n";
cout << "2. Delete an element of the list\n";
cout << "3. Search an element of the list\n";
cout << "4. Exit\n";
cin >> choice;
switch(choice)
{
case 1:
{
cout << "Printing list:\n";
list1.fill("1","2");
list1.print();
break;
}
case 2:
{
cout << "Element to delete: ";
cin >> element1;
list1.search(element1);
element1 = "";
break;
}
case 3:
{
cout << "Element to search: ";
cin >> element1;
list1.search(element1);
element1 = "";
break;
}
}
}while(choice != 4);
return 0;
}
The code doesn't compile, it marks errors like:
" error: prototype for ‘void list::fill(char*)’ does not match any in class ‘list’
void list::fill(char rfc[30])
^
t3b.cpp:79:8: error: candidate is: void list::fill(char*, char*)
void fill(char r[30], char n[30]);"
Any ideas on how to fix it? Or any ideas on how to put 2 elements in a node using templates?
Thanks in advance.
Dude, you should really try to isolate the error a little bit before posting it. This is 500 lines of code, I had to copy and paste it all into an editor before I could even look at it.
When you declared fill, it had two arguments, when you defined it, it had one. Also, I would avoid arrays of characters for numerous reasons, instead use std::string.
Hi I am trying to make a doubly linked list to store individual numbers as nodes of a doubly linked list and then add them together and print them out for a homework assignment. I am having a lot of trouble getting this to work and have traced my problem to my add node functions as they don't update the pointers correctly. For example on the AddToFront() function I can't understand how I can get the prev pointer to work and point to the node behind it.
I can't use the STL and have to implement the LL myself in case anyone is wondering. Thanks!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
using namespace std;
/////// PART A
template <class T>
class List {
private:
struct Node {
T data;
Node *next;
Node *prev;
};
Node *front, *current, *rear;
public:
List();
~List();
void AddtoFront (T newthing);
void AddtoRear (T newthing);
bool FirstItem (T & item);
bool LastItem (T & item);
bool NextItem (T & item);
bool PrevItem (T & item);
};
template <class T>
List<T>::List() {
front = NULL; current = NULL; rear = NULL;
}
template <class T>
List<T>::~List() {
}
template <class T>
void List<T>::AddtoFront (T newthing) {
if (front == NULL) {
Node *temp;
temp = new Node;
temp->data = newthing;
temp->next = front;
temp->prev = NULL;
front = temp;
} else {
Node *temp;
temp = new Node;
front->prev = temp;
temp->data = newthing;
temp->next = front;
temp->prev = NULL;
front = temp;
}
}
template <class T>
void List<T>::AddtoRear (T newthing) {
if (rear == NULL) {
Node *temp;
temp = new Node;
temp->data = newthing;
temp->prev = rear;
temp->next = NULL;
rear = temp;
} else {
Node *temp;
temp = new Node;
rear->next = temp;
temp->data = newthing;
temp->prev = rear;
temp->next = NULL;
rear = temp;
}
}
template <class T>
bool List<T>::FirstItem (T & item) {
if (front == NULL) { return false; }
current = front;
item = front->data;
return true;
}
template <class T>
bool List<T>::LastItem (T & item) {
if (rear == NULL) { return false; }
current = rear;
item = rear->data;
return true;
}
template <class T>
bool List<T>::NextItem (T & item) {
if (current != NULL) current = current->next;
if (current == NULL) { return false; }
item = current->data;
return true;
}
template <class T>
bool List<T>::PrevItem (T & item) {
if (current == NULL) { return false; }
if (current->prev != NULL) current = current->prev;
item = current->data;
return true;
}
/////// PART B
class BigNumber {
private:
//complete here...
//include here a List of integers, or shorts etc
List<int>L;
public:
//complete here...
//what methods do you need?
//e.g., ReadFromString, PrintBigNumber, AddBigNumbers
BigNumber();
~BigNumber();
void ReadFromString(char * decstring);
void PrintBigNumber();
void AddBigNumbers(BigNumber B1, BigNumber B2);
};
BigNumber::BigNumber(){
// anything here?
}
BigNumber::~BigNumber(){
//you can keep that empty
}
void BigNumber::ReadFromString (char * decstring ) {
//read a string, adding a new node per digit of the decimal string
// To translate 'digits' to integers: myinteger=decstring[index]-48
//You need to use the AddtoFront()
int temp;
for (unsigned i=0; i < strlen(decstring); ++i) {
//cin >> decstring[i];
temp = decstring[i]-48;
//L.AddtoFront(temp);
L.AddtoRear(temp);
//cout <<"Number added!" <<endl;
}
}
void BigNumber::PrintBigNumber () {
//complete here, print the list (i.e., use FirstItem() and NextItem() )
int val;
if (L.FirstItem(val)) {
cout << val;
} else {
cout << "print failed";
}
//if (L.FirstItem(val)) { cout << "true-first";} else { cout <<"false-first";};
//if (L.LastItem(val)) { cout << "true";} else { cout <<"false";};
//L.FirstItem(val);
//cout << val;
/*while (L.PrevItem(val)){
cout << val;
//cout <<"Print error!Value not here.";
}*/
}
void BigNumber::AddBigNumbers(BigNumber B1,BigNumber B2){
//complete here.
//use FirstItem(), NextItem() and AddNode()
//to add two big numbers, what do you have to do? Be careful about the carry
//Remember to add the last carry, the resulting number can have one more digit than B1 or B2
}
/////// PART C
BigNumber B1, B2, RES;
int main (int argc, char ** argv) {
//use command line arguments
if(argc!=3){printf("usage: executable number1 number2\n");exit(0);}
B1.ReadFromString(argv[1]);
B2.ReadFromString(argv[2]);
//print
cout << endl<< "Add the following numbers " << endl;
B1.PrintBigNumber();
cout << " + ";
B2.PrintBigNumber();
cout << " = " << endl;
//compute the addition
RES.AddBigNumbers(B1,B2);
//print the result
RES.PrintBigNumber();
cout << endl;
return 0;
}
EDIT: I added in a line each in AddToFront() and AddToRear(). Is this on the right track?
AddtoFront needs to also update the prev pointer for front. That is, you're currently doing
temp -> front <-> rest_of_list
where it needs to be
temp <-> front <-> rest_of_list.
Also, you might notice that the two branches of your if statement in AddtoFront are identical... :)
I have a problem with this Binary Search Tree.
After that i cut a leave, if I try to show the tree VisualStudio answer me this message
An unhandled exception of type 'System.AccessViolationException' occurred in ABR1.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
It's more that 3 days that i try to understand could someone help me???
// ABR1.cpp : main project file.
#include "stdafx.h"
#include <iostream>
using namespace System;
using namespace std;
template <class T>
class ABR{
private:
struct Leaf{
T value;
struct Leaf *DX; //
struct Leaf *SX; //
};
Leaf *root;
public:
//constructors
ABR() { root = NULL; }
//destructor
//~ABR();
void appendLeaf(T);
bool cutLeaf(T);
bool isInTree(T) const;
Leaf* findLeaf(T) const;
void showTreeInOrder() const { showTreeInOrder(root); }
void showTreeInOrder(Leaf *) const;
void showTreePreOrder() const { showTreePreOrder(root); }
void showTreePreOrder(Leaf *) const;
};
template <class T>
void ABR<T>::appendLeaf(T newValue){
if (isInTree(newValue)){
cout << "The value is just present..." << endl;
return;
}
Leaf *newLeaf; // To point to a new leaf
Leaf *ptrLeaf; // To move in the tree
// Allocate the necessary memory
newLeaf = new Leaf; //generate the new leaf
newLeaf-> value = newValue;
newLeaf-> DX = NULL;
newLeaf-> SX = NULL;
if(!root) //if is the first leaf
root = newLeaf;
else{
ptrLeaf = root;
//cout<<ptrLeaf->value<<ptrLeaf->SX<<ptrLeaf->DX<<endl;
while (ptrLeaf != NULL){
//cout << ptrLeaf->value <<"\t";
if (ptrLeaf->value < newValue){
if (ptrLeaf->DX == NULL){
ptrLeaf->DX = newLeaf;
return;
}
else
ptrLeaf = ptrLeaf->DX;
}
else{
if(ptrLeaf->SX == NULL){
ptrLeaf->SX = newLeaf;
return;
}
else
ptrLeaf = ptrLeaf->SX;
}
}
}
}
template <class T>
bool ABR<T>::isInTree(T toFind) const{
Leaf *ptrLeaf;
ptrLeaf = root;
while (ptrLeaf){
if (ptrLeaf->value == toFind)
return true;
else{
if (ptrLeaf->value < toFind)
ptrLeaf = ptrLeaf->DX;
else
ptrLeaf = ptrLeaf->SX;
}
}
return false;
}
template <class T>
typename ABR<T>::Leaf * ABR<T>::findLeaf(T toFind) const
{
Leaf *ptr;
ptr = root;
while(ptr != NULL)
{
//cout << ptr->value << "#" << endl;
if (toFind == ptr->value){
//cout << "Trovato";
return ptr;
}
else if (ptr->value < toFind)
ptr = ptr->DX;
else
ptr = ptr->SX;
} cout << "Element don't find" << endl;
return NULL;
}
template <class T>
void ABR<T>::showTreeInOrder(Leaf *ptr) const
{
if(ptr != NULL)
{
showTreeInOrder(ptr->SX);
cout << ptr->value << endl;
showTreeInOrder(ptr->DX);
}
}
template <class T>
void ABR<T>::showTreePreOrder(Leaf *ptr) const
{
if(ptr != NULL)
{
showTreePreOrder(ptr->DX);
cout << ptr->value << endl;
showTreePreOrder(ptr->SX);
}
}
template <class T>
bool ABR<T>::cutLeaf(T toCut)
{
Leaf *Leafptr, *tempLeafptr;
Leafptr = findLeaf(toCut);
if (Leafptr == NULL)
{
cout << "The element is not present..." << endl;
return false;
}
else if (Leafptr->DX == NULL)
{
tempLeafptr = Leafptr;
Leafptr = Leafptr->SX;
delete tempLeafptr;
return true;
}
else if (Leafptr->SX == NULL)
{
tempLeafptr = Leafptr;
Leafptr = Leafptr->DX;
delete tempLeafptr;
return true;
}
else
{
tempLeafptr = Leafptr->DX;
while (tempLeafptr->SX)
tempLeafptr = tempLeafptr->SX;
tempLeafptr->DX = Leafptr->SX;
tempLeafptr = Leafptr;
Leafptr = Leafptr->DX;
delete tempLeafptr;
return true;
}
}
int main(){
ABR<int> albero;
for(int a = 0.0; a < 100.0; a+= 3)
albero.appendLeaf(a);
albero.appendLeaf(1000);
albero.appendLeaf(1001);
albero.showTreePreOrder();
int b = 75;
albero.cutLeaf(b);
albero.showTreePreOrder(); //ERROR
//albero.showTreeInOrder();//SAME ERROR
system("PAUSE");
return 0;
}
You're recursing in showTreePreOrder and encountering a stack overflow. Running it in the debugger told me this in under one minute.
EDIT:
Your problem is in this section of cutLeaf(). First, you're assuming Leafptr->SX isn't null and you're deleting it, but it is null for the last leaf. Second, when you delete the leaf you don't set its parent's DX pointer to null. Therefore, when you traverse the list, you traverse into leaves that have been freed.
else if (Leafptr->DX == NULL)
{
tempLeafptr = Leafptr;
Leafptr = Leafptr->SX;
delete tempLeafptr;
return true;
}
The same problems exist in the else clause.