My teacher gave the class for a driver to complete a program, and I'm unsure how to code the insert function because of it.
The line giving me trouble:
you.Insert(me,0);
you is for the default constructor and me is for an explicit value constructor, so this line is supposed create a node in you with the contents of me.
I'm lost understanding how to write the parameter to access me for my insert function
void WRD::Insert( ?, int new_data)
I'll include the explicit constructor I have, any insight understanding this mentally will help. (included example of what insert should look like or do based on an example I was given.)
WRD::WRD(const string & s)
{
cout<<"one called\n";
front = 0;
for(unsigned i=0; i<s.length(); i++)
{
AddChar(s[i]);
}
}
class node
{
public:
char symbol;
node * next;
};
v
oid Insert(node * &ptr, int new_data)
{
node *new_ptr = new node;
new_ptr -> data = new_data;
new_ptr -> next = 0; //always initialize a pointer
if (Empty(ptr))
{
ptr = new_ptr;
}
else if (new_ptr->data <= ptr->data)
{
new_ptr->next = ptr;
ptr = new_ptr;
}
else
{
node *fwd_ptr=ptr, *pre_ptr=ptr;
while(fwd_ptr!=0 && (fwd_ptr->data < new_ptr->data))
{
pre_ptr = fwd_ptr;
fwd_ptr = fwd_ptr->next;
}
if (fwd_ptr == 0)
{
pre_ptr->next = new_ptr;
}
else
{
new_ptr->next = fwd_ptr;
pre_ptr->next = new_ptr;
}
}
}
Like this I think (assuming I've understood you right)
void WRD::Insert(const WRD& w, int new_data)
It might help to show more of your driver program, in particular how you and me are declared.
Related
Today, I have learned about the Binary Search Tree, and I am trying to implement it, but I got a problem.
Assume that I have a Struct like this:
struct Node {
int v;
Node* left = NULL;
Node* right = NULL;
}
Below it, I have:
// At the beginning, root is NULL
Node* root = NULL;
Node* new_node(int v) {
Node* n = new Node;
n->v = v;
return n;
}
void insert(int v) {
// At the beginning, root is NULL
Node* c = root;
while (c != NULL) {
if (v < c->v) {
c = c->left;
} else {
c = c->right;
}
}
c = new_node(v);
}
And in the main code, I tested my implementation by using this code:
int main() {
insert(5);
}
When I use insert(5), in insert function, the variable c will be root, and because root at that time is NULL, so c will equal to new_node(v). But when I print root->v it returns nothing.
Did I make something wrong??
In your code you do not modify root after initialization. root is always NULL. This
Node* c = root;
// ...
c = new_node(v);
will not change root. It merely declares a local variable c, initializes it with the value of root and assigns a new value to it.
If you want to change the value of something inside a function you can pass it by reference, pointers are no different with respect to that. For example:
#include <iostream>
struct Node {
int v;
Node* left = NULL;
Node* right = NULL;
};
Node* root = NULL;
Node*& find_insertion(Node*& ptr, int v){
if (ptr == NULL) return ptr;
if (v < ptr->v) {
return find_insertion(ptr->left,v);
} else {
return find_insertion(ptr->right,v);
}
}
void insert_at(Node*& ptr,int v){
Node*& insertion = find_insertion(root,v);
insertion = new Node;
insertion->v = v;
}
void insert(int v){
insert_at(root,v);
}
int main() {
insert(5);
std::cout << root->v;
}
Next you should take a look at smart pointers (std::unique_ptr) to avoid leaks or compilcated manual memory managment.
I had to implement a Linked HashTable for a project. Now I have to come up with an excercise and a solution to it using my hashtable. Everything works just fine, except I get random Segfault errors.
By Random I mean: It is the same line of code that causes it, but always at different times, calls.
I tested my code in Atom, Codeblocks and in Visual Studio Code. Both Atom and CB threw SegFault error, but VS Code ran it just fine without a problem.
NOTE: THIS IS NOT THE FULL/REAL CODE. It's part of a header file that is included in the main.cpp file which is then compiled and ran.
The Code:
#include <iostream>
#include <typeinfo>
#include <string>
using namespace std;
//List:
template<class T>
struct Node
{
string data;
Node *next;
};
class List
{
private:
Node *head, *tail;
int length;
friend class HashTable;
public:
List();
List(const List &L);
//~List() {delete this;};
List& operator =(List L);
int find(string);
void insert(string value);
void remove_head();
void remove_poz(int);
void remove_tail();
void clear();
void display();
};
List::List()
{
head = NULL;
tail = NULL;
length = 0;
}
template<>
string List<string>::findByIndex(int ind)
{
int i = 0;
Node<string>* temp = new Node<string>;
temp = head;
while (temp != NULL)
{
i++;
if (i == ind) return temp->data;
temp = temp->next;
}
delete temp;
return "-1";
}
template<class T>
void List<T>::remove_head()
{
Node<T>* temp = new Node<T>;
temp = head;
head = head->next;
delete temp;
length--;
}
template<class T>
void List<T>::remove_pos(int pos)
{
int i;
Node<T>* curr = new Node<T>;
Node<T>* prev = new Node<T>;
curr = head;
for (i = 1; i < pos; ++i)
{
prev = curr;
curr = curr->next;
}
if (curr)
{
prev->next = curr->next;
length--;
}
else cout << "Error" << endl;
}
template<class T>
void List<T>::remove_tail()
{
Node<T>* curr = new Node<T>;
Node<T>* prev = new Node<T>;
curr = head;
while (curr->next != NULL)
{
prev = curr;
curr = curr->next;
}
tail = prev;
prev->next = NULL;
delete curr;
length--;
}
//HashTable:
class HashTable
{
private:
List *table;
float load, stored;
int slots;
friend class List;
public:
HashTable();
HashTable(int);
~HashTable();
int hashFunc(string key);
int findTable(string);
int findList(string);
HashTable& operator =(const HashTable&);
void resize(); //I need this one
void insert(string);
void remove(string);
void clear(int);
void clear();
void display();
};
HashTable::HashTable()
{
stored = 0;
load = 0.00;
slots = 15;
table = new List[slots];
}
int HashTable::hashFunc(string key)
{
int g, h = 0;
unsigned int i;
for (i = 0; i < key.size(); ++i)
{
h = (h << 4) + (int)(key[i]);
g = h & 0xF0000000L;
if (g != 0)
{
h = h ^ (g >> 24);
}
h = h & ~g;
}
return h % slots;
}
template<class T>
void HashTable<T>::remove(T value)
{
int ind = hashFunc(value);
int findInd = table[ind].findByValue(value);
if (findInd == 0)
table[ind].remove_head();
else if (findInd < table[ind].length)
table[ind].remove_pos(findInd);
else table[ind].remove_tail();
if (table[ind].isEmpty()) occupied--;
stored--;
load = stored / slots;
}
The function that would cause the segfault:
(This would be called over and over again in a loop till I don't have more elements in my table)
string reakcio(HashTable<string>& HT, int tarolok)
{
const int anyagszam = rand() % 4 + 2; //Min 2, Max 5 anyag hasznalodik
int i = 0, j;
string anyagok[5];
string eredmeny;
for(j = 0; j < tarolok && i < anyagszam; ++j) //elemek kivetele
{
while(!HT.table[j].isEmpty())
{
anyagok[i++] = HT.table[j].findByIndex(1); //This line right here is the culprit :(
HT.remove(anyagok[i-1]);
}
}
const int siker = rand() % 4 + 0; //75% esely a sikerre
if (siker)
{
eredmeny = anyagok[0];
for(i = 1; i < anyagszam; ++i)
eredmeny += " + " + anyagok[i];
}
else
eredmeny = "Sikertelen reakcio";
return eredmeny;
}
(Note: only the functions that might be needed are shown here)
Every element of my hashtable, or of my lists is a 10 character long random string value.
srand(time(NULL)) is used before the function call in main.cpp
Any help or advice would be much appreciated, as I'm stuck at this and I really need to move on to the next portion of my exercise, but I can't without this.
The main.cpp file:
#include <iostream>
//#include "LinkedHash.h"
#include "functions.cpp"
int main()
{
HashTable<string> Anyagok;
int tarolok;
tarol(Anyagok); //Stores the data from file, no problem here, functions.cpp
tarolok = Anyagok.getSlots();
srand(time(NULL));
int i = 1;
while (Anyagok.getStored() > 5 )
cout<<reakcio(Anyagok, tarolok)<<" "<<i++<<endl;
return 0;
}
The LinkedHash.h contains the hashtable and the list, the functions.cpp contains the problematic function.
EDIT:
By suggestion I changed out the
Node<string>* temp = new Node<string>;
temp = head;
part to
Node<string>* temp = head;
Also removed the delete line.
But my problem is still the same :/
Everything works just fine, except I get random Segfault errors
Then nothing works at all.
A first review show little care to the cornercases in the list class. You need to define a correct behavior for
operation on empty lists
operation on first and last element
key not found during search
Notable errors found:
remove_head, remove_tail will segfault on empty list. head is NULL. head->next is invalid memory access. Similar errors are all over the implementation.
HashTable<T>::remove(T value) will always remove something. Even if the value argument is not in the hashtable. This is deeply flawed
findByIndex returning "-1" make no sense. "-1" is a valid input.
Node<T>* temp = new Node<T>;temp = head;. You just leaked memory. You need a pointer to manipulate node addresses. You should not instantiate Nodes to get a pointer. This is not an issue (ie not noticeable) for a small projet, but unacceptable for a real implementation.
i want to make a linked list ..
but the first node with a data and null link
if i input a string (123)
linked list be like this:
1/null - 2/point to the last one(1) - 3/point to the last one(2)
#include <iostream>
#include <string>
using namespace std;
struct link
{
int data;
link* next;
};
class LinkedList
{
private:
link* first;
public:
LinkedList(){}
void Add(string s)
{
for (int i = 0; i > s.length(); i++)
{
if (i == 0)
{
first->data = s[i];
first->next = NULL;
}
else
{
link* NewOne = new link;
NewOne->data = s[i];
NewOne->next = first;
first = NewOne;
}
}
}
void display()
{
cout << first->data;
}
};
int main()
{
LinkedList l1;
l1.Add("2734");
l1.display();
return 0;
}
what's the wrong in the code
You forget to allocate memory for first.
Following may help (using std::unique_ptr for free/correct memory management):
struct link{
char data;
std::unique_ptr<link> next;
};
class LinkedList {
private:
std::unique_ptr<link> first;
public:
void Set(const std::string& s){
for (auto c : s) {
std::unique_ptr<link> node = std::move(first);
first = std::make_unique<link>();
first->data = c;
first->next = std::move(node);
}
}
Live example
It also looks like you're storing characters in an int. Your output will be the ASCII value of the character rather than the raw int values.
I would recommend using unique pointers as Jarod42 has done. Having said that, this quick example below does not use them so you will need to call delete appropriately or use unique_ptr.
I added a last pointer to help traversal of the list as we make new links.
private:
Link * first;
Link *last;
int numLinks;
public:
LinkedList()
{
first = NULL;
last = NULL;
numLinks = 0;
}
Now for Add
void Add(string s)
{
for (int i = 0; i < s.length(); i++)
{
if (numLinks == 0)
{
first = new Link;
first->data = (s[i] - '0');
first->next = NULL;
last = first;
numLinks++;
}
else
{
Link * newLink = new Link;
newLink->data = (s[i] - '0');
newLink->next = NULL;
last->next = newLink;
last = newLink;
numLinks++;
}
}
}
The constructor does not initialize the first member. Subsequently, in Add():
for (int i = 0; i > s.length();i++){
if (i == 0){
first->data = s[i];
first->next = NULL;
}
This ends up dereferencing an uninitialized pointer, leading to undefined behavior.
There's also a problem with your display() too, but this is the main problem.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am doing linked list exercises and currently understand how to write a link list in struct format. However I would like to change my code to make linked list a class and have the print, sort, add, delete, functions as members of the class. Please give me ideas on how this can be done.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstddef>
using namespace std;
struct mylist {
int payload;
struct mylist * link;
};
void addlink(struct mylist *, int);
struct mylist * droplink(struct mylist *);
void printmylist(struct mylist *);
void sortmylist(struct mylist *);
int main() {
struct mylist head;
struct mylist *lptr;
head.payload = 15;
head.link = 0;
lptr = &head;
printmylist(lptr);
addlink(lptr, 21);
printmylist(lptr);
addlink(lptr, -5);
printmylist(lptr);
addlink(lptr, 90);
printmylist(lptr);
lptr = droplink(lptr);
printmylist(lptr);
sortmylist(lptr);
printmylist(lptr);
return 0;
}
void addlink(struct mylist *lp, int val) {
struct mylist *temp;
struct mylist *newlink;
//run out to end of chain
temp = lp;
do {
if (temp->link != 0)
temp = temp->link;
} while (temp->link != 0);
newlink = (struct mylist *) malloc(sizeof(struct mylist));
newlink->payload = val;
newlink->link = 0;
temp->link = newlink;
return;
}
struct mylist * droplink(struct mylist *lp) {
cout << "Releasing front value of " << lp->payload << endl;
return lp->link;
}
void printmylist(struct mylist *lp) {
struct mylist *temp;
temp = lp;
while (temp->link != 0) {
cout << temp->payload << " then ";//if there is just one link, loop never runs
if (temp->link != 0)
temp = temp->link;
}
cout << temp->payload; //gets the last link's value
cout << endl;
return;
}
void sortmylist(struct mylist *lp) {
struct mylist *temp;
struct mylist *temp2;
int linkcount = 1;
int temppayload;
temp = lp;
while (temp->link != 0) {
if (temp->link != 0) {
++linkcount;
temp = temp->link;
}
}
cout << linkcount << " links " << endl;
temp = lp;
for (int ct2 = 1; ct2 < linkcount; ++ct2) {
temp = lp;
for (int ct = 1; ct < linkcount; ++ct) {
if (temp->link != 0)
temp2 = temp->link;
if (temp->payload > temp2->payload) {
temppayload = temp->payload;
temp->payload = temp2->payload;
temp2->payload = temppayload;
}
if (temp2->link != 0)
temp = temp2;
}
}
}
The only real difference between a struct and a class in C++ is that by default all members of a class are private, and all members of a struct are public.
I assume what you're really asking is how to make your linked list methods members of your struct / class. This is very easy.
All of your existing methods accept a struct mylist* as the first parameter. In C++, this is provided automatically by the compiler, as a hidden parameter called this. You can refer to this explicitly, but it is also accessible implicitly.
So where in C you might have:
lp->payload = 0;
In a C++ class member function, you could have:
this->payload = 0;
Or more commonly:
payload = 0;
So broadly speaking, the steps required to "c++ify" your C code are:
Move the declarations of the methods into the body of the struct
Remove the struct mylist * argument from each method
Remove the references to lp in each method
Call the member functions by dereferencing an instance of the struct (e.g. lptr->addlink(-5);)
As a rule, you can change every struct that is passed to a linked list function from:
struct Node {
int payload;
struct Node *link;
};
...
void addlink(struct Node *lp, int val) {
...
}
to this:
class Node {
public:
Node() : _link(0), _payload(0) { } // initialize members on new empty node
Node(int val) : _link(0), _payload(val) { } // pass a new value directly
~Node() {
// call a function to clear everything pointed to from _link
}
void addlink(int val) {
Node *temp = this;
do {
if (temp->link() != 0)
temp = temp->link();
} while (temp->link() != 0);
Node *newlink = new Node(val); // this will do what the next 2 lines do
//Node *newlink = new Node; <- you can also create a Node this way and then assign the payload
//newlink->setPayload(val);
// newlink->link = 0; <-- not needed 'new Node' has already initialized it
temp->setLink(newlink);
}
// provide access to the data (get/set)
int payload() { return _payload; }
void setPayload(int n) { _payload = n; }
Node *link() { return _link; }
void setLink(Node *p) { _link = p; }
// data members
private:
int _payload;
Node *_link;
};
This fragment gives you the idea. Now you can add the rest :)
The best of course, is to place the code within the functions in a .cpp file and leave the definition of the class in the header:
class Node {
public:
Node();
Node(int val); // pass a new value directly
~Node();
void addlink(int val);
// provide access to the data (get/set)
// you can leave thse one liners in the header, they'll most likely be inlined
int payload() { return _payload; }
void setPayload(int n) { _payload = n; }
Node *link() { return _link; }
void setLink(Node *p) { _link = p; }
// data members
private:
int _payload;
Node *_link;
};
The bodies of the functions in the cpp:
Node::Node() : _link(0), _payload(0)
{
}
Node::Node(int val) : _link(0), _payload(val)
{
}
......
Hope this helps.
Hi i would like to make an external single linked list. I have a problem with "Non-Ivalue in assignment" and its occuring on line "this = currP->next" i tried making it currP.next but its also producing an error
#include <cstdlib>
using namespace std;
struct node{
int data;
node *next;
node(int i){
data = i;
next = NULL;
}
void insert(int position, node &n){
node *currP = this;
node *prevP= NULL;
for(int counter = 0; counter>=position;counter++, prevP = currP, currP = currP->next){
if(counter==position)
{
n.next = currP->next;
currP->next = &n;
}
}
}
void add(node &n){
next = &n;
}
void deleteNode(int i){
node *currP = this;
node *prevP = NULL;
while(currP!= NULL){
if(currP->data == i){
if(prevP == NULL)
this = currP->next;
else{
prevP->next = currP->next;
}
}
prevP = currP;
currP = currP->next;
}
}
};
An lvalue is a variable that can reside at the left side of the equal operator. This means its value can be changed. You can't change the value of this, it's just not permitted, therefore the error.
You could re-write your function as follows:
node* deleteNode(int i){
if ( this->data == i )
return this->next;
else
{
if ( this->next )
this->next = this->next->deleteNode(i);
else
return this;
}
}
deleteNode() will now return a pointer to the start of the rest of the list and the recursive algorithm will concatenate the first part with the last part. It's not tested so a few adjustments may be necessary but I hope you get the point.
A lvalue is a semantic rule.
It means "left-value".
Examples of lvalues are:
A variable. ie "a"
A memory address. ie "a[4]" or "*(a+8)"
this is not a lvalue. You just can't assign anything to it. It's the reference to the method caller.