I'm trying to initialize a Double-Link List and creating new nodes within it
However, I keep getting this error when trying to create a new node "temp", filling it with data, then inserting it into the dLink list.
Here's the code:
// Node of the Double-Link List
struct node {
double x, y;
node *prev;
node *next;
};
// Double-Link List Function
struct dList {
node *head;
node *rear;
};
// Function to check if a list is empty
bool isEmpty(dList *L)
{
if (L == NULL)
return true;
return false;
}
// Function to insert a node at the rear of a list
void insertAtRear(dList *L, double a, double b)
{
node *temp = new node;
temp->x = a;
temp->y = b;
if (isEmpty(L))
{
L->head = temp;
L->rear = temp;
return;
}
temp->prev = L->rear;
L->rear->next = NULL;
L->rear = temp;
return;
}
// Main Function
int main() {
dList *L1=NULL;
dList *L2=NULL;
string fileName1, fileName2;
cout << "Please insert the name of the first csv file in which the information is stored:" << endl;
cin >> fileName1;
readFile(L1, fileName1);
cout << "Please insert the name of the second csv file in which the information is stored:" << endl;
cin >> fileName2;
readFile(L2, fileName2);
system("pause");
return 0;
}
I didn't include the readFile function seeing as it's not the issue, just keep in mind that I'm calling insertAtRear() from within that function
I tried setting *prev and *next as nullptr when initializing them in the structure init.
I'm aware that the issue is related to pointers and them not being correctly initialized but I can't seem to figure out how to fix the issue.
#Yksisarvinen is right, did you initialize L1 & L2 in the readFile function? they appear to be null.
"I'm aware that the issue is related to pointers and them not being correctly initialized"
You can initialize objects correctly with class constructors
struct node {
double x, y;
node *prev;
node *next;
node(const double &x, const double &y) : x(x), y(y), prev(nullptr), next(nullptr) {}
node(const node&) = delete;
~node(void) {}
};
struct dList {
node *head;
node *rear;
dList(node *head=nullptr, node *rear=nullptr) : head(head), rear(rear) {}
dList(const dList&) = delete;
~dList(void)
{
for (; head != nullptr; head = rear)
{
rear = head->next;
head->next = head->prev = nullptr;
delete head;
}
}
};
implementation of isEmpty & insertAtRear should be something like:
bool isEmpty(dList *L)
{
if (L == nullptr) throw "error: null dList pointer!!!!";
return ((L.head == nullptr) || (L.rear == nullptr));
}
bool insertAtRear(dList *L, double a, double b)
{
if (L == nullptr) return false;
node *temp = new node(a, b);
if (isEmpty(L)) L->head = L->rear = temp;
else { temp->prev = L->rear; L->rear = L->rear->next = temp; }
return true;
}
and main function can be:
int main() {
dList L1;
dList L2;
...
readFile(&L1, fileName1);
...
readFile(&L2, fileName2);
system("pause");
return 0;
}
I hope this is helpful
Related
I typed 1234, but the list has 4,3,2,1 in it. I suspect the problem is getchar() itself, or a function in the class, but I have no way to find out.
The link class is responsible for some linked list operations, such as deletion, insertion, etc., while the node class is responsible for creating and assigning nodes.
The createlist class is responsible for the creation of the linked list, which is the main source of the problem. I wrote the debug statement in it, so you can run it and see the results for yourself
using namespace std;
class Node
{
public:
int data;
Node *next;
Node()
{
next = nullptr;
}
Node(int data)
{
this->data = data;
}
Node(const Node &temp)
{
this->data = temp.data;
}
};
class Link
{
public:
Node *head;
int length = 0;
Link()
{
head = new Node();
}
~Link()
{
while (head != nullptr)
{
Node *p = head->next;
free(head);
head = p;
}
}
void insert(const Node &cache)
{
Node *temp = new Node(cache);
temp->next = head->next;
head->next = temp;
length++;
}
};
void Creatlist(Link &link)
{
char cache;
while (1)
{
cache = getchar();
if (cache == '\n')
break;
link.insert(Node(cache - '0'));
cout << cache << " ";
}
cout<<endl;
Node *p = link.head->next;
cout << "in the linklist:";
while (p != nullptr)
{
cout << p->data << " ";
p = p->next;
}
}
int main()
{
Link link;
cout<<"inut numbers:"<<endl;
Creatlist(link);
}```
With the insert you inserted to the FRONT of the list. So you had "1", then "2->1" ... If you want to insert to the end, don't insert at the head, but hake a Node* tail in the class Link and an insert_end function as
//...
Node* temp;
void insert_end(const Node &cache){
Node *temp = new Node(cache);
tail->next=temp;
tail=tail->next;
length++;
}
Alsoin the constructor set tail=head
I have a linked-list and I want to sort it in a special order.
I tried to use bubble sort.
As I have many data types in my struct(called Node), I can't swap the values.
struct Node
{
int data;
Node *next;
Node(int x)
{
data = x;
next = NULL;
}
union
{
sold s;
apartment a;
villa v;
}u;
};
Actually I can't swap my union values in my_swap function.
what I need is a new swap function.
here's my code.
#include<iostream>
#include<vector>
#include<string>
using namespace std;
struct adderess {
char city[50];
char street[100];
char alley[100];
int code;
};
struct apartment {
float structure_s;
float price;
int floor;
bool elevator;
adderess adr;
};
struct villa {
float structure_s;
float yard_s;
float price;
int floor;
adderess adr;
};
struct sold {
int type;
float comission;
bool con;
};
struct Node
{
int data;
Node *next;
Node(int x)
{
data = x;
next = NULL;
}
union
{
sold s;
apartment a;
villa v;
}u;
};
void print_list(Node *head)
{
Node *start = head;
while (start)
{
cout << start->data << " -> ";
start = start->next;
}
cout << "\n\n";
}
void my_swap(Node *node_1, Node *node_2)
{
int temp = node_1->data;
node_1->data = node_2->data;
node_2->data = temp;
}
double total_price(Node **n) {
if ((*n)->data == 1)
return((*n)->data*(*n)->data);
else
return((*n)->data*(*n)->data*(*n)->data);
}
void bubble_sort(Node *head)
{
int swapped;
Node *lPtr; // left pointer will always point to the start of the list
Node *rPrt = NULL; // right pointer will always point to the end of the list
do
{
swapped = 0;
lPtr = head;
while (lPtr->next != rPrt)
{
if (total_price(&lPtr) >total_price(& lPtr->next))
{
my_swap(lPtr, lPtr->next);
swapped = 1;
}
lPtr = lPtr->next;
}
//as the largest element is at the end of the list, assign that to rPtr as there is no need to
//check already sorted list
rPrt = lPtr;
} while (swapped);
}
int main()
{
Node *head = new Node(2);
head->next = new Node(1);
head->next->next = new Node(4);
head->next->next->next = new Node(3);
head->next->next->next->next = new Node(6);
head->next->next->next->next->next = new Node(5);
cout << "The original list = " << endl;
print_list(head);
bubble_sort(head);
cout << "The Sorted list = " << endl;
print_list(head);
return 0;
}
Rather than swapping the values within two nodes, you can swap their positions itself in the linked list. For that you'll need to maintain a prev pointer which is the pointer occurring before lPtr in the linked list.
void my_swap(Node*& head, Node*& prev, Node*& node_1, Node*& node_2)
{
if (prev == nullptr)
{
node_1->next = node_2->next;
node_2->next = node_1;
prev = node_2;
head = node_2;
}
else
{
node_1->next = node_2->next;
node_2->next = node_1;
prev->next = node_2;
prev = node_2;
}
}
void bubble_sort(Node *head)
{
bool swapped;
Node *prev, *lPtr, *rPtr; // left pointer will always point to the start of the list
rPtr = nullptr; // right pointer will always point to the end of the list
do
{
swapped = false;
prev = nullptr;
lPtr = head;
while (lPtr->next != rPtr)
{
if (total_price(&lPtr) > total_price(&lPtr->next))
{
my_swap(head, prev, lPtr, lPtr->next);
swapped = true;
}
else
lPtr = lPtr->next;
}
//as the largest element is at the end of the list, assign that to rPtr as there is no need to
//check already sorted list
rPtr = lPtr;
} while (swapped);
}
I haven't checked if it runs correctly but hopefully you get the idea after going through the code.
I am working on a BST and when I print out the elements in any order, I get a random '0' appended to it, but I cannot find where its coming from.
I followed the pseudo code thats present in Introduction to algorithms by Cormen and have also looked at Geeks for Geeks but I have no luck getting rid of that 0.
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node* LeftChild;
Node* RightChild;
Node(int data){
this->data = data;
this->LeftChild = NULL;
this->RightChild = NULL;
}
//pointers of the class
};
class BST {
private:
Node* root;
public:
BST(){ ///creating an empty tree in Constant Time
root = new Node(NULL);
}
Node* getRoot(){ return this->root; };
int i =0;
void printTree(Node *root)
{
if (root == NULL)
return;
else {
printTree(root->LeftChild);
cout << root->data << " ";
printTree(root->RightChild);
}
}
Node* InsertNode(Node *root,int data)
{
Node *z = new Node(data);
Node *y = new Node(NULL);
Node *x = this->root;
//if(x->data < z->data){
// x = z;
//return x;
//}
while(x!= NULL){
y = x;
if(data < x->data){
x = x->LeftChild;
}
else{
x = x->RightChild;
}
}
if(y== NULL) y= z;
else if(data < y->data){
y->LeftChild = z;
}
else{
y->RightChild =z;
}
return y;
/*
if(this->root->data== NULL){
this->root =z;
return root;
}
else{
this->root =y;
}
*/
//this->root = z;
//return root;
}
bool FindNode(Node *root,int data);
int Largest(Node *root){
return root->data;
}
};
int main()
{
BST myBst;
Node * root = (myBst.getRoot());
root = myBst.InsertNode(root, 24);
myBst.InsertNode(root, 60);
myBst.InsertNode(root, 55);
myBst.InsertNode(root, 32);
myBst.printTree(root);
return 0;
}
Here is the output:
0, 24,32,55,60
The constructor does not make a sense
BST(){ ///creating an empty tree in Constant Time
root = new Node(NULL);
}
There is created a dummy node with initialization of the data member data with NULL.
What you need is just to write
BST() : root( nullptr ) { ///creating an empty tree in Constant Time
}
The function InsertNode must have only one parameter instead of two parameters as you wrote
Node* InsertNode(Node *root,int data){
The pointer root is the data member of the class. So there is no need to pass it to the function. Otherwise the function should be declared as a static member function of the class (that nevertheless does not make a great sense).
That is the function should be declared like
void InsertNode( int data ){
Also the function has at least a memory leak
Node* InsertNode(Node *root,int data){
Node *z = new Node(data);
Node *y = new Node(NULL);
Node *x = this->root;
while(x!= NULL){
y = x;
//...
The function can be written for example the following way
void InsertNode( int data )
{
Node *new_node = Node( data );
Node **current = &root;
while ( *current != nullptr )
{
if ( data < ( *current )->data )
{
current = &( *current )->LeftChild;
}
else
{
current = &( *current )->RightChild;
}
}
*current = new_node;
}
I'm writing my own linked list class (for educational purposes) and here it is:
My code
#include <iostream>
using namespace std;
#define PRINT(x) #x << " = " << x << " "
struct ListNode {
int val;
ListNode* next = nullptr;
ListNode(int x) : val(x), next(nullptr) {}
};
class LinkedList {
private:
ListNode* _head;
unsigned long long int _size;
public:
LinkedList() :_head(nullptr), _size(0) {}
LinkedList(ListNode* _h) :_head(_h), _size(0) {
ListNode* node = _head;
while (node != nullptr) {
_size++;
node = node->next;
}
}
// Copy constructor
LinkedList(const LinkedList& obj) {
ListNode* node = obj._head;
while (node != nullptr) {
this->add(node->val);
node = node->next;
}
}
~LinkedList() {
while (_head != nullptr) {
remove();
}
}
void add(const int& value) {
ListNode* node = new ListNode(value);
node->next = _head;
_head = node;
_size++;
}
int remove() {
int v = _head->val;
ListNode* node = _head;
_head = _head->next;
delete node;
_size--;
return v;
}
void print() {
if (size() == 0) {
cout << "List is empty" << endl;
return;
}
ListNode* node = _head;
while (node->next != nullptr) {
cout << node->val << " -> ";
node = node->next;
}
cout << node->val << endl;
}
unsigned long long int size() { return _size; }
ListNode* head() { return _head; }
};
int main() {
LinkedList L;
L.add(4);
L.add(3);
L.add(2);
L.add(1);
L.print();
LinkedList L2(L);
return 0;
}
The problem is that when I run this code, I get this error: error for object 0x7fff5b8beb80: pointer being freed was not allocated I don't understand why. My logic beyond the copy constructor is simple: I iterate over the list I'm copying, which is obj, and I add a new element to this list, which is the list I'm copying to. Since my add() function creates a new element with, well, new, I can't see where my two lists share an element which I'm trying to delete twice in the destructor. What am I doing wrong?
You forgot to initialize your _head in copy constructor:
// Copy constructor
LinkedList(const LinkedList &obj) {
_head = NULL; // <- Add This
ListNode *node = obj._head;
while (node != nullptr) {
this -> add(node -> val);
node = node -> next;
}
}
I am writing a simple app that gets a list and saves the objects as nodes in a singly linked list and we can add(), remove(), copy(), etc. each node depending on the given data set. each node has a char value which is our data and an int count which counts the occurrence of the related char.
e.g. for a list like
a, a, b, b, c, a
there would be three nodes (since there are three different characters) which are:
[a,3,*next] -> [b,2,*next] -> [c,1,*next] -> nullptr
bool isAvailable() checks if the data is already in the list or not.
Q: When inserting a data there are two options:
The data has not been entered: so we have to create a newNodewith the given data, count=1and *next=NULL.
The data is already entered: so we have to count++ the node that has the same data.
I know if the given data is available or not, but how can I point to the node with same data?
Here's the code:
#include "stdafx.h"
#include<iostream>
using namespace std;
class Snode
{
public:
char data;
int count;
Snode *next;
Snode(char d, int c)
{
data = d;
count = c;
next = NULL;
}
};
class set
{
private:
Snode *head;
public:
set()
{
head = NULL;
tail = NULL;
}
~set();
void insert(char value);
bool isAvailable(char value);
};
set::~set()
{
Snode *t = head;
while (t != NULL)
{
head = head->next;
delete t;
}
}
bool set::isAvailable(char value)
{
Snode *floatingNode = new Snode(char d, int c);
while(floatingNode != NULL)
{
return (value == floatingNode);
floatingNode->next = floatingNode;
}
}
void set::insert(char value)
{
Snode *newNode = new Snode(char d, int c);
data = value;
if (head == NULL)
{
newNode->next = NULL;
head = newNode;
newNode->count++;
}
else
{
if(isAvailable)
{
//IDK what should i do here +_+
}
else
{
tail->next= newNode;
newNode->next = NULL;
tail = newNode;
}
}
}
I know if the given data is available or not, but how can I point to the node with same data?
You'll need to start at the head of the list and iterate along the list by following the next pointers until you find the node with the same data value. Once you've done that, you have your pointer to the node with the same data.
Some other notes for you:
bool set::isAvailable(char value)
{
Snode *floatingNode = new Snode(char d, int c);
while(floatingNode != NULL)
{
return (value == floatingNode);
floatingNode->next = floatingNode;
}
}
Why is this function allocating a new Snode? There's no reason for it to do that, just initialize the floatingNode pointer to point to head instead.
This function always returns after looking at only the first node in the linked list -- which is not the behavior you want. Instead, it should return true only if (value == floatingNode); otherwise it should stay inside the while-loop so that it can go on to look at the subsequent nodes as well. Only after it drops out of the while-loop (because floatingNode finally becomes NULL) should it return false.
If you were to modify isAvailable() slightly so that instead of returning true or false, it returned either floatingPointer or NULL, you'd have your mechanism for finding a pointer to the node with the matching data.
e.g.:
// Should return either a pointer to the Snode with data==value,
// or NULL if no such Snode is present in the list
Snode * set::getNodeWithValueOrNullIfNotFound(char value) const
{
[...]
}
void set::insert(char value)
{
Snode * theNode = getNodeWithValueOrNullIfNotFound(value);
if (theNode != NULL)
{
theNode->count++;
}
else
{
[create a new Snode and insert it]
}
}
You had a lot of problems in your code, lets see what are they:
First of all, Snode doesn't need to be a class, rather you can go with a simple strcut; since we need everything public.(not a mistake, but good practice)
You could simple initialize count = 1 and next = nullptr, so that no need of initializing them throw constructor. The only element that need to be initialized through constructor is Snod's data.
Since c++11 you can use keyword nullptr instead of NULL, which denotes the pointer literal.
Member function bool set::isAvailable(char value) will not work as you think. Here you have unnecessarily created a new Snode and cheacking whether it points to nullptr which doesn't allow you to even enter the loop. BTW what you have written in the loop also wrong. What do you mean by return (value == floatingNode); ? floatingNode is a Snode by type; not a char.
Hear is the correct implementation. Since we don't wanna overwrite the head, will create a Node* pointer and assign head to it. Then iterate through list until you find a match. If not found, we will reach the end of the isAvailable() and return false.
inline bool isAvailable(const char& value)
{
Node *findPos = head;
while(findPos != nullptr)
{
if(findPos -> data == value) return true;
else findPos = findPos->next_node;
}
return false;
}
In void set::insert(char value), your logic is correct, but implementation is wrong. Following is the correct implementation.(Hope the comments will help you to understand.
void insert(const char& value)
{
if(head == nullptr) // first case
{
Node *newNode = new Node(value);
newNode->next_node = head;
head = newNode;
}
else if(isAvailable(value)) // if node available
{
Node *temp = head;
while(temp->data != value) // find the node
temp = temp->next_node;
temp->count += 1; // and count it by 1
}
else // all new nodes
{
Node *temp = head;
while(temp->next_node != nullptr) // to find the null point (end of list)
temp = temp->next_node;
temp = temp->next_node = new Node(value); // create a node and assign there
}
}
Your destructor will not delete all what you created. It will be UB, since your are deleting newly created Snode t ( i.e, Snode *t = head;). The correct implementation is as bellow.(un-comment the debugging msg to understand.)
~set()
{
Node* temp = head;
while( temp != nullptr )
{
Node* next = temp->next_node;
//std::cout << "deleting \t" << temp->data << std::endl;
delete temp;
temp = next;
}
head = nullptr;
}
Last but not least, the naming (set) what you have here and what the code exactly doing are both different. This looks more like a simple linked list with no duplicates. This is however okay, in order to play around with pointers and list.
To make the code or iteration more efficient, you could do something like follows. In the isAvailable(), in case of value match/ if you found a node, you could simply increment its count as well. Then in insert(), you can think of, if node is not available part.
Hope this was helpful. See a DEMO
#include <iostream>
// since you wanna have all of Node in public, declare as struct
struct Node
{
char data;
int count = 1;
Node* next_node = nullptr;
Node(const char& a) // create a constrcor which will initilize data
: data(a) {} // at the time of Node creation
};
class set
{
private:
Node *head; // need only head, if it's a simple list
public:
set() :head(nullptr) {} // constructor set it to nullptr
~set()
{
Node* temp = head;
while( temp != nullptr )
{
Node* next = temp->next_node;
//std::cout << "deleting \t" << temp->data << std::endl;
delete temp;
temp = next;
}
head = nullptr;
}
inline bool isAvailable(const char& value)
{
Node *findPos = head;
while(findPos != nullptr)
{
if(findPos -> data == value) return true;
else findPos = findPos->next_node;
}
return false;
}
void insert(const char& value)
{
if(head == nullptr) // first case
{
Node *newNode = new Node(value);
newNode->next_node = head;
head = newNode;
}
else if(isAvailable(value)) // if node available
{
Node *temp = head;
while(temp->data != value) // find the node
temp = temp->next_node;
temp->count += 1; // and count it by 1
}
else // all new nodes
{
Node *temp = head;
while(temp->next_node != nullptr) // to find the null point (end of list)
temp = temp->next_node;
temp = temp->next_node = new Node(value);
}
}
void print() const // just to print
{
Node *temp = head;
while(temp != nullptr)
{
std::cout << temp->data << " " << temp->count << "\n";
temp = temp->next_node;
}
}
};
int main()
{
::set mySet;
mySet.insert('a');
mySet.insert('a');
mySet.insert('b');
mySet.insert('b');
mySet.insert('c');
mySet.insert('a');
mySet.print();
return 0;
}