I am trying to implement a linkedlist in C++ and trying to incorporate array like data access using '[]'.
First I declared a Node class as the following.
class Node{
public:
int data;
Node *next, *prev;
Node(int val){
this -> data = val;
this -> next = NULL;
this -> prev = NULL;
}
};
Then I implemented the Linkedlist class as the following where I have overloaded the '[]' operator like the following
class LinkedList{
public:
Node *head;
LinkedList(){
this -> head = NULL;
}
LinkedList(Node *h){
this -> head = h;
}
int operator [] (int index){
if(index < 0 || index >= getsize(this -> head)){
cout << "List out of bounds" << endl;
return -1;
}else{
Node *cur = this -> getnode(index);
return cur -> data;
}
}
Node* getnode(int index){
int count = 0;
Node *cur = this -> head;
while(cur != NULL){
if(count == index)
break;
count++;
cur = cur -> next;
}
return cur;
}
};
In the main function I have tried to print the 'l[0]'. It shows error as
no operator "<<" matches these operandsC/C++(349)
linklist_sort.cpp(173, 10): operand types are: std::ostream << LinkedList
Please help me out. Am I missing some concept here ?
The main function :
int main(){
srand(time(0));
LinkedList *l = new LinkedList();
for(int i = 0; i<10; i++){
int num = rand() % 50 + 1;
l -> head = l -> insert(l->head,num);
}
l->printlist(l->head);
int n1, n2;
cout << "\n";
cin >> n1 >> n2;
l->swap(l->head,n1,n2);
l->printlist(l->head);
cout << "\n";
cout << l[0]; //Error here
return 0;
}
The getsize function :
int getsize(Node *head){
if(head == NULL)
return 0;
else
return 1 + getsize(head->next);
}
Since l is a pointer which is created by
LinkedList *l = new LinkedList();
it needs to be dereferenced to be able to use operator first.
This would solve your problem:
cout << (*l)[0];
But I suggest you to not create LinkedList with new keyword so you can avoid using raw pointers and memory leaks in the application code.
You could use LinkedList l; instead.
Related
I am using a map with int value -> trie, trie is the struct. So why am I getting runtime error when I print all keys value in my map? But if I don't print anything then there is no error(the insert() part don't cause any error).
struct trie{
node *root;
trie(){
root = new node();
}
void insert(int x){
node *cur = root;
for(int i = 31; i >= 0; i--){
int b = (x >> i) & 1;
if (cur->child[b] == NULL) cur->child[b] = new node();
cur = cur->child[b];
}
cur->isleaf = true;
}
int maxxor(int x){
node *cur = root;
int res = 0;
for(int i = 31; i >= 0; i--){
int b = (x >> i) & 1;
if (cur->child[b ^ 1] != NULL){
res |= (1ll << i);
cur = cur->child[b ^ 1];
}
else cur = cur->child[b];
}
return res;
}
int minxor(int x){
node *cur = root;
int res = 0;
for(int i = 31; i >= 0; i--){
int b = (x >> i) & 1;
if (cur->child[b] != NULL) cur = cur->child[b];
else{
res |= (1ll << i);
cur = cur->child[b ^ 1];
}
}
return res;
}
~trie(){
delete root;
}
};
map<int, trie> tr;
int32_t main(){
ios::sync_with_stdio(false);
tr[3].insert(1);// no error
for(auto x: tr) cout << x.first << ' '; //RUNTIME ERROR?
}
I have tried to debug and read various questions/answers but I still not be able to debug this code. Any help are appreciated.
You have implemented a "complex" tree if i may say, using linked list. And in order to avoid trouble, you need to make sure that your destructors do their work propoerly and are coherent i.e destroy all allocated memory and don't "try" to "destroy" unallocated space or already destroyed space.
That said, your trie destructor destroys root data member, which calls node destructor. And node destructor destroys both two child which were not necessarily allocated. This is the origin of your Segmentation Error.
To correct this you should only destroy allocated child.
Here is a simplified version of your code
#include <bits/stdc++.h>
#define int int64_t
using namespace std;
struct node{
node* child[2];
bool isleaf;
node(){
child[0] = child[1] = NULL;
isleaf = false;
}
~node(){
}
};
struct trie{
node *root;
trie(){
cout << " in trie ctor" << endl;
root = new node();
}
void insert(int x){
cout << "in insert trie methode " << endl;
node *cur = root;
cur->child[0] = new node();
cur->child[1] = new node();
}
~trie(){
delete root->child[0]; // i'm sure it has been allocated
delete root->child[1]; // i'm sure it has been allocated
// delete root, would be like doing int *p; delete p;
}
};
map<int, trie> tr;
int32_t main(){
ios::sync_with_stdio(false);
tr[3].insert(1);
for(auto x: tr)
cout << x.first << endl << endl;
}
I didn't put the full code because it was very long and i only need help with the small portion which is the **** area. i can't seem to use front() or top() to get the top element of the queue. I tried making top() function List keep getting error : 1) class List has no memeber named 'top' which means i don't have a function top in List, when i make it it says 2) no match for 'operator=' in printer_cpu[i] = SList::top() with T=PCB]()'
template <class T>
class node{
public:
T data;
node *next;
};
template <class T>
class List{
node<T> *head;
node<T> *tail;
public:
List()
{
head = tail = NULL;
}
bool isEmpty()
{
if(head == NULL) return true;
else return false;
}
void enqueue(T new_data){
node<T> *temp = new node<T>;
temp->data = new_data;
temp->next = NULL;
if(isEmpty()){
head = temp;
tail = temp;
}
else{
tail->next = temp;
tail = temp;
}
}
void dequeue(){
if(isEmpty())
{
cout << "The list is already empty" << endl;
}
node<T>* temp;
if(head == tail){
temp->data=head->data;
delete head;
head = tail = NULL;
}
else{
temp->data = head->data;
head = head->next;
delete temp;
}
}
node<T> top() // need help here ****
{
return head;
}
void display(){
node<T> *current = head;
while(current != NULL){
cout << current->data << endl;
current = current->next;
}
}
};
struct PCB
{
int ProcessID;
int ProcessorSize;
int priority;
string name;
};
typedef List<PCB> printing;
typedef List<PCB> disk;
void gen(vector<printing> &printer_queue,string printer_name[], int printers)
{
for(int i = 0; i < printers; i++)
{
int num = i+1;
ostringstream convert;
convert << num;
printer_name[i] = "p" + convert.str();
printer_queue.push_back(printing());
}
int main()
{
int numOfPrinter = 5;
string interrupt;
cin >> interrupt;
PCB cpu;
PCB printer_cpu[numOfPrinter];
string printer_name[numOfPrinter];
vector<printing> PQ;
gen(PQ,printer_name,numOfPrinter);
for(int i = 0; i < numOfPrinter; i++)
{
if(interrupt == printer_name[i])
{
cout << "Enter a name for this printer file: " << endl;
cin >> cpu.name;
PQ[i].enqueue(cpu);
printer_cpu[i] = PQ[i].top(); //need help here ****
}
}
}
It looks like you're missing an asterisk, because you need to return of type pointer, because that's what head is.
You should have
node<T> * top()
{
...
}
You also need to overload the = operator, because you are trying to compare type PCB with type node *.
Well, I compile your code successfully after correcting some mistakes.
I didn't meet class List has no memeber named 'top' problem.
Then your top() function returns the value of head, so you should change it to: node<T>* top() because head is a pointer to node<T>.
And the reason you got no match for 'operator=' error is that printer_cpu[i]'s type is PCB while PQ[i].top()'s type should be node<T>*
I have also found that the code you post lacks a } just before int main().
My program is meant to run several functions, insertnode takes values from the user and creates a list of them using nodes and sorts them in order from least to greatest, printlist prints the values separated by spaces, mergelist merges the two lists in order, and reverselist reverses the list. The command prompt accepts values but once the stopping condition (0) is entered for the second list it crashes. Visual Studio shows no errors. I figure something is either wrong with the functions or the pointers. Someone spoke to me of a memory leak but Im unsure as to how to fix that.
#include <iostream>
#include <stack>
using namespace std;
class node {
private:
double num;
node *link;
public:
node() { }
node(double m, node *n) { num = m; link = n; }
node* getlink() { return link; }
double getdata() { return num; }
void setdata(double m) { num = m; }
void setlink(node* n) { link = n; }
};
typedef node* nodeptr;
void insertnode(nodeptr& head, double m);
void printlist(nodeptr head);
nodeptr mergelists(nodeptr& head1, nodeptr& head2);
void reverselist(nodeptr& head);
int main()
{
double input;a
nodeptr head1 = NULL; // Pointer to the head of List #1
nodeptr head2 = NULL; // Pointer to the head of List #2
nodeptr temp;
// Part 1 - Create two sorted lists
cout << "-------------------------------------" << endl;
cout << "CREATE LIST #1: " << endl;
cout << "-------------------------------------" << endl;
do {
cout << "Enter value (0 to quit): ";
cin >> input;
insertnode(head1, input);
} while (input != 0);
cout << "-------------------------------------" << endl;
cout << "CREATE LIST #2: " << endl;
cout << "-------------------------------------" << endl;
do {
cout << "Enter value (0 to quit): ";
cin >> input;
insertnode(head2, input);
} while (input != 0);
// Part 1 - Print the lists to make sure that they are correct.
printlist(head1);
printlist(head2);
// Part 2 - Merge the two lists and display the new merged list
temp = mergelists(head1, head2);
printlist(temp);
// Part 3 - Reverse the merged list and then display it
reverselist(temp);
printlist(temp);
return 0;
}
void insertnode(nodeptr& head, double m){
nodeptr p = head;
nodeptr k = p;
if (!p){
nodeptr n = new node(m, NULL);
}
else {
while (m >= p->getdata()){
k = p;
p = p->getlink();
}
nodeptr n = new node;
n->setdata(m);
k->setlink(n);
if (p){
n->setlink(p);
}
}
}
void printlist(nodeptr head){
nodeptr p = head;
while (p){
double m = p->getdata();
cout << m << " ";
p = p->getlink();
}
cout << endl;
}
nodeptr mergelists(nodeptr &head1, nodeptr &head2){
nodeptr result = 0, last = 0;;
if (head1->getdata() <= head2->getdata()){
result = head1;
head1 = head1->getlink();
}
else {
result = head2;
head2 = head2->getlink();
}
last = result;
while (head1 && head2){
if (head1->getdata() <= head2->getdata()){
last->setlink(head1);
last = head1;
head1 = head1->getlink();
}
else{
last->setlink(head2);
last = head2;
head2 = head2->getlink();
}
}
if (head1)
last->setlink(head1);
else if (head2)
last->setlink(head2);
last = 0;
head1 = 0;
head2 = 0;
return result;
}
void reverselist(nodeptr& head){
stack<double> holder;
nodeptr p = head;
while (p){
holder.push(p->getdata());
p = p->getlink();
}
p = head;
while (p){
p->setdata(holder.top());
holder.pop();
p = p->getlink();
}
}
There are a few issues with this method:
void insertnode(nodeptr& head, double m){
nodeptr p = head;
nodeptr k = p;
if (!p)
{
head = new node(m, NULL); // Update head
}
else
{
while (p && m >= p->getdata()) // Check for p!=NULL
{
k = p;
p = p->getlink();
}
nodeptr n = new node;
n->setdata(m);
k->setlink(n);
if (p)
{
n->setlink(p);
}
}
}
The simplified version:
void insertnode(nodeptr& head, double m)
{
nodeptr p = head;
nodeptr k = nullptr;
while (p && m >= p->getdata())
{
k = p;
p = p->getlink();
}
if (!k)
{
head = new node(m, p);
}
else
{
k->setlink(new node(m, p));
}
}
There are two issue is that you are not updating the head node when you insert into the linked list. The previous answer by #uncletall outlined this.
The second issue is very simple -- you failed to initialize the link to NULL when you default construct a node. Make the following change in your node class:
class node {
private:
double num;
node *link;
public:
node() : link(0) { } // here is the change here
//...
//... the rest of your code
};
When you default construct a node the link is now initialized. Without this change, your link node was a garbage value, thus you were not traversing the links properly when you were inserting more items in the list.
The change is similar to (but not exactly) the same as this:
class node {
private:
double num;
node *link;
public:
node() { link = 0; } // here is the change here
//...
//... the rest of your code
};
The difference is that link is assigned in the body of the constructor here, while the first example initializes the link to 0 before the constructor has started. Both wind up doing the same thing.
If you can follow my main below, I run the program, I am able to enter an integer, it finds the next prime number, then asks for data. Once I enter data once, the program hangs. Seems to be in an infinite loop, or something. It doesn't crash. When I pause it, it brings up read.c file with an arrow on line 256. Not sure what this means whatsoever. Any help would be much appreciated.
I have the following class and member function declarations in hashtable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#define TRUE 1
#define FALSE 0
#define VERBOSE 0x01
#define NON_VERBOSE 0x02
#include "linkedlist.h"
class hashTable{
public:
int keys;
int tableSize;
linkedList<int> **table;
hashTable(const int n);
//~hashTable();
void hash(int value);
int search(int value);
int divisionMethod(int value, int sizeOfTable);
int midSquareMethod(int value, int sizeOfTable);
int total();
void printHashTable();
int next_prime(int value, char flag);
};
// constructor
hashTable::hashTable(const int n){
linkedList<int> newList;
tableSize = next_prime(n, VERBOSE);
cout << "Table size is: " << tableSize << "\n"; // for debugging
system("pause"); // for debugging
table = new linkedList<int>*[tableSize];
for (int i = 0; i < tableSize; i++)
table[i] = { new linkedList<int> };
}
// Compute the Hash Function and "Hash" element into table
void hashTable::hash(int value){
table[value % tableSize]->addToHead(value);
keys++;
//divisionMethod(midSquareMethod(value, tableSize), tableSize)
}
// Simple Search Function
// Returns the element searched for if found, 0 otherwise
int hashTable::search(int value){
return(table[value % tableSize]->search(value));
}
// Divsion Method for producing a semi-unique key
int hashTable::divisionMethod(int value, int sizeOfTable){
int key;
key = value % sizeOfTable;
return(key);
}
// Middle Square Method for producing a semi-unique key
int hashTable::midSquareMethod(int value, int sizeOfTable){
int key;
key = ((value * value) & 0x0ff0) >> 4; // pick the middle 8 bits
return(key);
}
// Returns the total number of keys in the table
int hashTable::total(){
return(keys);
}
// Print the hash table (for demonstration purposes
void hashTable::printHashTable(){
int i = 0, valueToPrint;
while (i < tableSize){
cout << i << ": ";
valueToPrint = table[i]->removeFromHead();
while (valueToPrint != 0){
cout << valueToPrint << " -> ";
valueToPrint = table[i]->removeFromHead();
}
cout << "|" << endl;
i++;
}
}
int hashTable::next_prime(int value, char flag){
int FOUND = FALSE;
int n;
while (!FOUND) {
for (n = 2; (n * n) <= value && (value % n) != 0; ++n);
if ((n * n) <= value) {
if (flag == VERBOSE)
cout << value << " is divisible by " << n << "\n";
value++;
}
else {
if (flag == VERBOSE)
cout << "The next largest prime is " << value << "\n";
FOUND = TRUE;
}
}
return(value);
}
#endif
Here is my linkedlist.h:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <iostream>
using namespace std;
template <class TYPE>
class Node{
public:
TYPE data;
Node* next;
// constructor
Node(TYPE const& x){
data = x;
next = NULL;
}
};
template <class TYPE>
class linkedList{
//struct Node{
// TYPE data;
// Node *next;
//};
public:
Node<TYPE> *head;
Node<TYPE> *tail;
int size;
// constructor
linkedList(){
head = NULL;
tail = NULL;
size = 0;
}
~linkedList();
void addToHead(TYPE value);
void addToTail(TYPE value);
TYPE removeFromHead();
TYPE removeFromTail();
TYPE search(TYPE searchData);
TYPE isEmpty();
};
//destructor
template <class TYPE>
linkedList<TYPE>::~linkedList(void){
while (head){
Node<TYPE> *temp = head;
head = head->next;
delete temp;
}
}
// Insert an element at the head (start) of the linked list
template <class TYPE>
void linkedList<TYPE>::addToHead(TYPE value){
Node<TYPE> *newNode = new Node<TYPE>(value);
if (isEmpty())
head = newNode;
else{
newNode->next = head;
head = newNode;
}
}
// Add an element to the tail (end) of the linked list
template <class TYPE>
void linkedList<TYPE>::addToTail(TYPE value){
Node<TYPE> *newNode = new Node<TYPE>(value);
Node *tempPtr;
if(isEmpty()){
head = newNode;
tail = newNode;
}
else{
tail->next = newNode;
tail = tail->next;
}
}
// Remove an element from start of Linked List
template <class TYPE>
TYPE linkedList<TYPE>::removeFromHead(){
TYPE tempValue;
Node<TYPE> *temp;
if (head){
tempValue = head->data;
temp = head;
if (head == tail)
head = tail = 0;
else
head = head->next;
delete temp;
return tempValue;
}
else
return 0;
}
// Remove an element from the end of the linked list
template <class TYPE>
TYPE linkedList<TYPE>::removeFromTail(){
TYPE tempValue;
Node *temp;
if (tail){
tempValue = tail->data;
if (head == tail){
delete head;
head = tail = 0;
}
else{
for (temp = head; temp->next != tail; temp = temp->next);
delete tail;
tail = temp;
tail->next = 0;
}
return tempValue;
}
else
return 0;
}
// Search for an element in the linked list
// Will return the element if found, otherwise it returns 0
template <class TYPE>
TYPE linkedList<TYPE>::search(TYPE searchData){
Node<TYPE> *temp;
temp = head;
while (temp->next != tail){
if (tail->data == searchData)
return searchData;
if (temp->data == searchData)
return searchData;
else
temp = temp->next;
}
return 0;
}
// isEmpty() function checks if head == NULL
template <class TYPE>
TYPE linkedList<TYPE>::isEmpty(){
return(head == NULL);
}
#endif
Here is my main:
#include "hashtable.h"
int main(){
int n, input;
cout << "Enter an integer: ";
cin >> n;
cout << "\n\n";
hashTable myHashTable(n);
cout << "Enter some values into the table:" << endl;
cin >> input;
while (input != 0){
myHashTable.hash(input);
cin >> input;
}
myHashTable.printHashTable();
}
Something must be wrong, you have in attribute of your hashTable class ... a hashTable pointer. It must be a linkedlist pointer, nop ?
I did find out what was causing all this. It was the way that I was implementing the linked lists in my array of pointers. Pretty much just programmer error from long nights. Of course there is a lot wrong with my code that I posted here, which I fixed it all, e.g. search function in my hash class, etc.,
Here is what I changed that pretty much fixed a good portion of my problem posted here:
hashTable::hashTable(const int n, char hFunction){
keys = 0;
hashFunction = hFunction;
tableSize = next_prime(n, VERBOSE);
cout << "Table size is: " << tableSize << "\n\n"; // for debugging
system("pause"); // for debugging
table = new linkedList<int>[tableSize];
I also changed my linkedList<int> **table to linkedList<int> *table. If anyone else needs any pointers on the rest of this NOW working hash function, just get a hold of me.
I got a problem with my doubly linked list. How can i make the input unique ( i don`t want it to be repeated )
for example i can input 1 and then again 1 i will have a list of 1 and 1. I need to forbid this somehow :) so the list can contain only not repeating numbers.
#include <cstdlib>
#include <iostream>
using namespace std;
struct node
{
int data;
node* next;
node* prev;
};
class Node
{
public:
Node();
~Node();
void setKopa();
void printForward();
private:
node* head;
node* tail;
node* n;
};
Node::Node()
{
setKopa();
}
Node::~Node()
{
delete n;
}
void Node::setKopa()
{
int lenght;
do
{
cout << "Input list lenght (how many elements): ";
cin >> lenght;
if(lenght<2)
cout << "Error list has to have atleast 2 elements!" <<endl;
}
while(lenght<2);
int fill;
cout << "Input "<< lenght <<" elements: "<<endl;
for (int i=0; i<lenght; i++)
{
cin>>fill;
n = new node;
n->data = fill;
if (i==0)
{
n->prev = NULL;
head = n;
tail = n;
}
else if (i+1==lenght)
{
n->prev = tail;
tail->next = n;
tail = n;
tail->next = NULL;
}
else
{
n->prev = tail;
tail->next = n;
tail = n;
}
}
}
void Node::printForward()
{
node* temp = head;
while(temp != NULL)
{
cout << temp->data << " ";
temp = temp-> next;
}
cout << endl;
}
int main()
{
Node a;
a.printForward();
system("pause");
return 0;
}
When you read input, go through the list to see if the input is already there.
With that (simple) answer out of the way, I would like to address some other things regarding your code. The first is that you have a memory leak in that you never delete the list. The second is that you don't need the class member variable n, it might as well be a local variable inside the setKopa loop.
Your way of adding new nodes is also, well, weird. It should, in my opinion, be more general instead of using the loop counter to check what to do. What I suggest is that you make a member function to add new nodes, taking the integer data as argument. This way you can call this function to add nodes anywhere, and not just in the setKopa function. In fact, I think the list should not handle that input at all, instead it should be a free-standing function called from main and which calls the addNode function.
Also the node structure doesn't need to be in the global namespace, it could be a private structure in the Node class. And speaking of the Node class, shouldn't it really be called List instead?
So if I may suggest, you might want to do something like this:
#include <iostream>
class List
{
public:
List()
: head(nullptr), tail(nullptr)
{}
~List();
void addNode(const int data);
void printAll() const;
private:
struct node
{
node()
: next(nullptr), prev(nullptr)
{}
node* next;
node* prev;
int data;
};
node* head;
node* tail;
};
List::~List()
{
for (node* next, *cur = head; cur; cur = next)
{
next = cur->next;
delete cur;
}
}
void List::addNode(const int data)
{
node* n = new node;
n->data = data;
if (tail == nullptr)
{
// First node in list
head = tail = n;
}
else
{
n->prev = tail;
tail->next = n;
tail = n;
}
}
void List::printAll() const
{
std::cout << "{ ";
for (node* cur = head; cur != nullptr; cur = cur->next)
std::cout << cur->data << ' ';
std::cout << "}\n";
}
int main()
{
List list;
for (int i = 0; i < 10; ++i)
list.addNode(i);
list.printAll();
}
The above code should print
{ 0 1 2 3 4 5 6 7 8 9 }
Replace the node-adding loop with your own.