It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I implement a queue myself. when testing, I expect the dequeue to reutrn when the queue is empty by testing if the tail pointer point to the head node. However, the address of the head node and the one pointer point are different when the point indeed points to the head, hence the queue never stop dequeue even if there is nothing in it.
This confuse me a lot. Any suggestion on this?
thanks a lot.
//header
#ifndef QUEUE_H
#define QUEUE_H
struct node
{
int val;
struct node* next;
};
class queue
{
private:
node head;
node* tail;
public:
queue();
void enqueue(int val);
void dequeue(int& holder, bool& v);
};
#endif
// queue.cpp
#include "queue.h"
using namespace std;
queue::queue()
{
tail = &head;
}
void queue::enqueue(int val)
{
node* tmp = new node;
tmp->val = val;
if(tail == &head)
{
tail = tmp;
tmp->next = &head;
head.next = tmp;
}
else
{
node* holder = head.next;
head.next = tmp;
tmp->next = &head;
holder->next = tmp;
}
}
void queue::dequeue(int& holder,bool& v)
{
if(tail == &head)
{
v = false;
}
else
{
node* cur = tail;
tail = tail->next;
holder = cur->val;
v = true;
delete cur;
}
}
//test.cpp
#include <iostream>
#include "queue.h"
using std::cout;
using std::endl;
int main()
{
int ary[] = {1,2,3,4,5};
queue myq;
for(int i = 0;i< sizeof(ary);i++)
{
myq.enqueue(ary[i]);
}
int tmp;
bool flag;
for(int i = 0;i<=7;i++)
{
myq.dequeue(tmp,flag);
if(flag)
cout<<"number is "<<tmp<<endl;
else
cout<<"queue empty"<<endl;
}
return 0 ;
}
I could give you the exact fix, but that would teach you absolutely nothing, you'd just copy and paste that into your code and go away do something else. So I'm going to help you with a line of code to add to show what the current value of &head is, and thus help identify what the actual problem is...
Add this line to enqueue (at the top of the function) and dequeue:
std::cout << __FUNCTION__ << ": " << &head << std::endl;
It will print the name of the function and the address off head. (You may need to include iostream as well)
Pay particular attention to how many printouts you get!
Working code below: (Learn to use a debugger)
#include <iostream>
using namespace std;
//header
#ifndef QUEUE_H
#define QUEUE_H
struct node {
int val;
struct node* next;
};
class queue {
private:
struct node* head;
struct node* tail;
public:
queue();
void enqueue(int val);
void dequeue(int& holder, bool& v);
};
#endif
using namespace std;
queue::queue() {
tail = NULL;
head = NULL;
}
void queue::enqueue(int val) {
node* tmp = new node;
tmp->val = val;
if (head == NULL && NULL == tail) {//No nodes Empty
head = tail = tmp;
tmp->next = NULL;
}else if (tail == head) { //Single node
tail = tmp;
tmp->next = head;
head->next = tmp;
} else {
tail->next = tmp;
tmp->next = head;
tail = tmp;
}
}
void queue::dequeue(int& holder, bool& v) {
if (NULL == tail || NULL == head) {
v = false;
return;
} else if (tail == head) {// single node
holder = head->val;
delete head;
head = NULL;
tail = NULL;
v = true;
} else { //more than one node
//Go to the last but one node and chop the tail
node* cur = head;
while (cur->next != tail)
cur = cur->next;
cur->next = head;
holder = tail->val;
delete tail;
tail = cur;
v = true;
}
return;
}
using std::cout;
using std::endl;
int main() {
int ary[] = { 1, 2, 3, 4, 5 };
queue myq;
for (int i = 0; i < 5; i++) {
myq.enqueue(ary[i]);
}
int tmp;
bool flag;
for (int i = 0; i <= 7; i++) {
myq.dequeue(tmp, flag);
if (flag) {
cout << "number is " << tmp << endl;
}
else {
cout << "queue empty" << endl;
}
}
return 0;
}
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed yesterday.
Improve this question
I am trying to make a quicksort algorithm for singly-linked lists. I, however, must be somehow creating a cyclical list in the process. In the concatenate function, the while loop gets stuck printing out 2 and 22 continuously. So, I assume that I must somehow be creating a list where Node 2 points to Node 22 and vice versa. Unfortunately, I have no idea how, since I feel like I have added nullptr to the end of every list where it would matter. I have reviewed my partition function so many times I add more bugs than I fix. Is there something I am missing with how linked lists work?
I have been stuck on this for a while so any help would be greatly appreciated.
Here is my quicksort code.
// quick.cpp
#include "volsort.h"
#include <iostream>
#include <string>
using namespace std;
// Prototypes
Node *qsort(Node *head, bool numeric);
void partition(Node *head, Node *pivot, Node *&left, Node *&right, bool numeric);
Node *concatenate(Node *left, Node *right);
// Implementations
void quick_sort(List &l, bool numeric) {
l.head = qsort(l.head, numeric);
}
Node *qsort(Node *head, bool numeric) {
if (head == nullptr || head->next == nullptr) {
return head;
}
Node *l = nullptr;
Node *r = nullptr;
partition(head, head, l, r, numeric);
l = qsort(l, numeric);
r = qsort(r, numeric);
head = concatenate(l, head);
head = concatenate(head, r);
return head;
}
void partition(Node *head, Node *pivot, Node *&left, Node *&right, bool numeric) {
Node *cur = pivot->next;
bool c;
Node *tl=nullptr, *tr=nullptr;
while (cur != pivot && cur != nullptr) {
if (numeric) {
c = node_number_compare(cur, pivot);//compare numeric elements of the Nodes
}
else {
c = node_string_compare(cur, pivot);//compare string elements of the code
}
if (c) {
if (left == nullptr) {
left = cur;
cur = cur->next;
tl = left;
}
else {
tl->next = cur;
cur = cur->next;
tl = tl->next;
tl->next = nullptr;
}
}
else {
if (right == nullptr) {
right = cur;
cur = cur->next;
tr = right;
}
else {
tr->next = cur;
cur = cur->next;
tr = tr->next;
tr->next = nullptr;
}
}
}
}
Node *concatenate(Node *left, Node *right) {
if (right == nullptr && left == nullptr) {
return nullptr;
}
else if (left == nullptr) {
right->next = nullptr;
return right;
}
else if (right == nullptr) {
left->next = nullptr;
return left;
}
Node *t = left;
while (t->next != nullptr) {
cout << t->number << endl;
t = t->next;
}
t->next = right;
while (t->next != nullptr) {
cout << t->number << endl;
t = t->next;
}
t->next = nullptr;
return left;
}
Input:
45
4
9
22
2
Here's the list class functions if it helps.
#include "volsort.h"
#include <string>
#include <iostream>
List::List() {
head = NULL;
size = 0;
}
List::~List() {
if (head != NULL) { // follow the links, destroying as we go
Node *p = head;
while (p != NULL) {
Node *next = p->next; // retrieve this node's "next" before destroy it
delete p;
p = next;
}
}
}
bool node_number_compare(const Node *a, const Node *b) {
if (a->number <= b-> number) {
return true;
}
else {
return false;
}
}
bool node_string_compare(const Node *a, const Node *b) {
return a->string <= b->string;
}
void List::push_front(const std::string &s) {
Node *node = new Node();
node->next = NULL;
node->string = s;
node->number = std::stoi(s);
if (head == NULL) {
head = node;
size = 1;
}
else {
Node *p = head;
while (p->next != NULL) {p = p->next;} // go to end of list
p->next = node;
size++;
}
}
void List::dump_node(Node *n) {
while (n->next != NULL) {
std::cout << n->number << " " << n->string << std::endl;
}
}
I am learning DSA, and was trying to implement linked list but the insertion function that i wrote is not
working in a for or while loop, its not the same when i call that function outside the loop, it works that way. I am not able to figure it out, please someone help me.
#include <iostream>
class Node {
public:
int data;
Node *next;
Node(int &num) {
this->data = num;
next = NULL;
}
};
class LinkedList {
Node *head = NULL;
public:
void insert(int num) {
Node *tmp;
if (head == NULL) {
head = new Node(num);
tmp = head;
} else {
tmp->next = new Node(num);
tmp = tmp->next;
}
}
void printList() {
Node *tmp = head;
while (tmp) {
std::cout << tmp->data << " ";
tmp = tmp->next;
}
std::cout << std::endl;
}
void reverseList() {
Node *curr = head, *prev = NULL, *nextNode;
while (curr) {
nextNode = curr->next;
curr->next = prev;
prev = curr;
curr = nextNode;
}
head = prev;
}
};
int main() {
LinkedList list1;
// This is not working
int num;
while (num != -1) {
std::cin >> num;
list1.insert(num);
}
// This is working
// list1.insert(1);
// list1.insert(2);
// list1.insert(3);
// list1.insert(4);
// list1.insert(5);
list1.printList();
list1.reverseList();
list1.printList();
return 0;
}
I expect this after insertion
Edit:
although #Roberto Montalti solved this for me, but before that I tried passing incrementing value using a for loop which worked but as soon as I pull that cin out it crashes. can someone tell me what's happening under the hood?
for (int i = 1; i <= 10; i++)
{
list1.insert(i);
}
When inserting the nth item (1st excluded) tmp is a null pointer, i don't understand what you are doing there, you are assigning to next of some memory then you make that pointer point to another location, losing the pointer next you assigned before, you must keep track of the last item if you want optimal insertion. This way you are only assigning to some *tmp then going out of scope loses all your data... The best way is to just keep a pointer to the last inserted item, no need to use *tmp.
class LinkedList
{
Node *head = NULL;
Node *tail = NULL;
public:
void insert(int num)
{
if (head == NULL)
{
head = new Node(num);
tail = head;
}
else
{
tail->next = new Node(num);
tail = tail->next;
}
}
...
}
You need to loop until you reach the end of the list and then add the new node after that. Like this.
void insert(int num) {
Node *tmp = head;
if (head == NULL) {
head = new Node(num);
}
else {
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = new Node(num);
}
}
first of all you need to define a node for each of the tail and head of the list as follows
Node *h;
Node *t;
you may also separate the Node from the LinkedList class so you can modify easily
class Node{
public:
int data;
Node *next;
Node(int data, Node* next);
~Node();
};
Node::Node(int data, Node* next)
{
this->data= data;
this->next= next;
}
Node::~Node(){}
}
after that you can try to add these functions to your LinkedList class
so it can deal with other special cases such empty list or full, etc..
void addToHead(int data){
Node *x = new Node(data,h);
h=x;
if(t==NULL){
t=x;
}
void addToTail(int data){
Node *x = new Node(data,NULL);
if(isEmpty()){
h=t=x;
}
else
{
t->next=x;
t=x;
}
}
now for the insert function try this after you implemented the Node class and the other functions,
void insert(int v){
if(h==nullptr){addToHead(v); return;}
if(h->data>=v) {addToHead(v);return;}
if(t->data<=v) {addToTail(v); return;}
// In this case there is at least two nodes
Node *k=h->next;
Node *p=h;
while(k != nullptr){
if(k->data >v){
Node *z =new Node(v,k);
p->next=z;
return;
}
p=k;
k=k->next;
}
}
the idea of making all of this is not lose the pointer when it goes through elements in the Linked List so you don't end up with a run time error.
I hope this can be useful to you.
There was an issue with your insert function.
Read about segmentation fault here https://www.geeksforgeeks.org/core-dump-segmentation-fault-c-cpp/#:~:text=Core%20Dump%2FSegmentation%20fault%20is,is%20known%20as%20core%20dump.
for a quick workaround you can use this
using namespace std;
#include <iostream>
class Node
{
public:
int data;
Node *next;
Node(int num)
{
this->data = num;
next = NULL;
}
};
class LinkedList
{
Node *head = NULL;
public:
void insert(int num)
{
Node *tmp= new Node(num);
tmp->next=head;
head=tmp;
}
void printList()
{
Node *tmp = head;
while (tmp)
{
std::cout << tmp->data << " ";
tmp = tmp->next;
}
std::cout << std::endl;
}
void reverseList()
{
Node *curr = head, *prev = NULL, *nextNode;
while (curr)
{
nextNode = curr->next;
curr->next = prev;
prev = curr;
curr = nextNode;
}
head = prev;
}
};
int main()
{
LinkedList list1;
// This is not working
int num,i=0,n;
cout<<"Type the value of n";
cin>>n;
while (i<n)
{
cin >> num;
cout<<num<<" "<<&num<<endl;
list1.insert(num);
i++;
}
list1.printList();
list1.reverseList();
list1.printList();
return 0;
}
This is my code for an implementation of a doubly linked list that inherits previous code from a single linked list, I am currently having trouble with a linker error and surfed the web for the past hour looking for an answer to my problem and found nothing so far to help me. This is my last resor can anyone help?
Specifically the error i get when i try to use g++ to link my .o files is:
DoublyList.o:DoublyList.cpp:(.text+0xf): undefined reference to
`LinkedList::LinkedList()'
collect2.exe: error: ld returned 1 exit status
I have found very similar questions asked but none of the answers helped me or at least I do not know how to implement them in my code specifically, any help will be apprectiated.
My LinkedList class
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
using namespace std;
struct node
{
float value;
node *next;
};
class LinkedList
{
private:
node *first;
public:
LinkedList();
virtual void insert(float val);
virtual void del(float val);
virtual void read();
virtual int search(float val);
};
#endif
My LinkedList class definition
#include <iostream>
#include "LinkedList.h"
using namespace std;
LinkedList::LinkedList()
{
this->first = NULL;
}
void LinkedList::insert(float val)
{
if(this->first==NULL or this->first->value >= val)
{
node* a_node = new node();
a_node->value = val;
this->first = a_node;
return;
}
node* n = new node();
n = this->first;
node* new_node = new node();
new_node->value = val;
while(n->next != NULL and n->next->value < new_node->value)
{
n = n->next;
}
new_node->next = n->next;
n->next = new_node;
}
void LinkedList::del(float val)
{
node* n = this->first;
node* prev = new node();
prev = n;//in case if it is the first value
int i = this->search(val);
if(this->first->value == val)
{
this->first = this->first->next;
return;
}
if(i != -1)
{
for(int j = 0; j < i; j++)
{
prev = n;
n = n->next;
}
}
//one last check
if(n->value == val)
{
prev->next = n->next;
}
}
void LinkedList::read()
{
node* n = this->first;
int i = 1;
while(n != NULL)
{
cout << i << ". " << n->value << endl;
n = n->next;
i++;
}
}
int LinkedList::search(float val)
{
int i = 0;
node* n = this->first;
while(n != NULL)
{
if(n->value == val)
return i;
else
{
n = n->next;
i++;
}
}
return -1;
}
My doublylist class
#ifndef DOUBLYLIST_H
#define DOUBLYLIST_H
#include "LinkedList.h"
class DoublyList: public LinkedList
{
public:
struct node
{
float value;
node * next;
node * prev;
};
node * first;
DoublyList();
void insert(float val);
void del(float val);
void read();
int search(float val);
};
#endif
My Doubly List definiton
#include <cstddef>
#include "DoublyList.h"
#include "LinkedList.h"
using namespace std;
//constructor
DoublyList::DoublyList()
{
first = NULL;
}
//Insert a node into the correct position in the doubly linked list
void DoublyList::insert(float val)
{
//if linked list is empty or val <= the first node
if(this->first == NULL or this->first->value >= val)
{
node * a_node = new node();
a_node->value = val;//set node's value
//begin replacing and assigning pointers
a_node->next = this->first;
a_node->prev = NULL;
this->first = a_node;
return;
}
node * n = new node();
n = this->first;
node * new_node = new node();
new_node->value = val;
node * prev_node = new node();
while(n->next != NULL and n->next->value < new_node->value)
{
prev_node = n;
n = n->next;
}
prev_node->next = new_node;
new_node->next = n->next;
new_node->prev = prev_node;
n->next = new_node;
}
void DoublyList::del(float val)
{
node * n = this->first;
int i = this->search(val);
//if first node
if(this->first->value == val)
{
this->first = this->first->next;
this->first->prev = NULL;
return;
}
//if value found
if(i != -1)
{
for(int j = 0; j < i; j++)
{
n = n->next;
}
//if a middle node
if(n->value == val and n->next != NULL)
{
n->prev->next = n->next;
return;
}
//if last node
if(n->prev != NULL)
{
n->prev->next = n->next;
}
}
return;//value not found so return
}
void DoublyList::read() { }
int DoublyList::search(float val) { }
Edit: Forgot to mention this error specifically happens aruond line 8 of DoublyList.cpp, this was from previous trials to link the .o files.
The command I used to call the linker is
g++ -g main2.cpp DoublyList.o
Where main2.cpp is the code that contains my main function to test the code.
Thanks to xskxzr the solution was to also link LinkedList.o along with all the rest of the .o files. If anyone ever has the same problem this is the answer.
I am trying to implement the a dot product calculation formula into the linked list implementation on my below code and I am having the below error:
request for member 'add_node' in 'B', which is of pointer type 'linked_list {aka node*}' (maybe you meant to use '->' ?)
How can I clear that and make working code? I don't want to use classes as well
#include <iostream>
#include <stdlib.h>
using namespace std;
struct node
{
int data;
int index;
node *next;
};
typedef node* linked_list;
node *head = NULL;
node *tail = NULL;
void add_node(int i,int n)
{
node *tmp = new node;
tmp->index = i;
tmp->data = n;
tmp->next = NULL;
if(head == NULL)
{
head = tmp;
tail = tmp;
}
else
{
tail->next = tmp;
tail = tail->next;
}
}
void display(node *head)
{
while(head!=0)
{
cout << head->index <<" ," << head->data << endl;
display(head->next);
break;
}
}
int main()
{
linked_list A;
A.add_node(2,7);
A.add_node(4,5);
A.add_node(7,8);
A.add_node(9,4);
linked_list B;
B.add_node(3,5);
B.add_node(4,6);
B.add_node(9,5);
int product=0;
while(A!=0 && B!=0)
{
if(A->index == B->index)
{
product = product + A->data * B->data;
A=A->next;
B=B->next;
}
else if(A->index < B->index)
{
A=A->next;
}
else
{
B=B->next;
}
}
return product;
return 0;
}
The error tells you what you need to know. linked_list is a pointer. You need to use the -> operator, not the dot operator.
Additionally, your node struct does not contain a method called add_node(). In fact it doesn't contain any methods at all.
#include <iostream>
using namespace std;
struct node
{
int data;
int index;
node *next;
};
class linked_list
{
private:
node *head,*tail;
public:
linked_list()
{
head = NULL;
tail = NULL;
}
void add_node(int i,int n)
{
node *tmp = new node;
tmp->index = i;
tmp->data = n;
tmp->next = NULL;
if(head == NULL)
{
head = tmp;
tail = tmp;
}
else
{
tail->next = tmp;
tail = tail->next;
}
}
node* gethead()
{
return head;
}
};
void display(node *head)
{
while(head!=0)
{
cout << head->index <<" ," << head->data << endl;
display(head->next);
break;
}
}
int main()
{
linked_list A;
A.add_node(2,7);
A.add_node(4,5);
A.add_node(7,8);
A.add_node(9,4);
linked_list B;
B.add_node(3,5);
B.add_node(4,6);
B.add_node(9,5);
display(A.gethead());
display(B.gethead());
int product=0;
node *current_a = A.gethead();
node *current_b = B.gethead();
while(current_a != 0 && current_b!=0)
{
if(current_a->index == current_b->index)
{
product = product + current_a->data * current_b->data;
current_a=current_a->next;
current_b=current_b->next;
}
else if(current_a->index < current_b->index)
{
current_a=current_a->next;
}
else
{
current_b=current_b->next;
}
}
cout<<"\nDot Product : "<< product<<endl;
return 0;
}
enter code here
It looks like in "SortedInsert", the head is always zero and then the code segfaults anyway... really frustrating. Any idea why the head is always zero even though I set it to something, and then why the code segfaults in general?
Thanks
#include <iostream>
#include <cassert>
#include <string>
#include <stdlib.h>
#include <sstream>
using namespace std;
struct Node {
Node* next = 0;
int data;
~Node(){
if (next != 0){
delete next;
}
}
};
void SortedInsert(Node* head, int value){
if(head == 0){
Node* header = new Node;
header->data = value;
head = header;
return;
}
cout << "TEST" << endl;
Node* temp = head;
while(temp != 0){
if(value > temp->data){
Node* insert = temp->next;
Node* otherTemp = new Node;
otherTemp->data = value;
temp->next= otherTemp;
temp->next->next = insert;
}
temp=temp->next;
}
return;
}
int main() {
srand(32);
Node* sortedList = 0;
for (int i = 0; i < 10; i++){
SortedInsert(sortedList, rand() % 100);
}
Node* temp = sortedList;
for (int i=0; i < 9; i++){
assert(temp->data <= temp->next->data);
temp = temp->next;
}
delete sortedList;
}
SortedInsert has its own copy of the head pointer. When you change head inside the function it doesn't affect the value in main. The solution is to pass head by reference or by passing the address.
void SortedInsert(Node** head, int value) {
//Use *head to refer to the head of the list
}
int main() {
...
Node* sortedList = 0;
SortedInsert(&sortedList, ...);
...
}
Or
void SortedInsert(Node*& head, int value) {
//Use head to refer to the head of the list
}
int main() {
...
Node* sortedList = 0;
SortedInsert(sortedList, ...);
...
}
Try the following
void SortedInsert( Node* &head, int value )
{
if ( head == nullptr || value < head->data )
{
head = new Node { head, value };
}
else
{
Node *current = head;
while ( current->next != nullptr && !( value < current->next->data ) )
{
current = current->next;
}
Node *tmp = new Node { current->next, value };
current->next = tmp;
}
}
As for your funcion implementation then the function deals with a copy of the head. Any changes of the copy do not influence on the argument itself. You should pass the head by reference or return the head from the function.