Well, i've read many different posts about this topic, but none could solve my question.
How can i dynamically create objects, and store them in a linked list.
i've this code that an object saves a number, and then it has a pointer that points to the next number, for representation only.
For example: 17
One->next = seven. Boths are objects of the same class.
class Class{
private:
int value;
Class *pNext; //Points to the next object in the linked list.
public:
Class(){value = 0; }
~Class(){;}
void setV(int x){ value = x;}
int getV(){return value;}
//void setP(Class *p){ pNext = p;} ?? Is this right?
};
int main(){
Class *pFirst; //pointer to first element
Class *pLast; //pointer to last element
Class *pCurrent; //pointer to current element
for(int i = 0; i < 4;i++){
pCurrent = new Class;
pCurrent->setV(i);
//pCurrent->setP(NULL);
}
for(int i = 0; i < 4;i++){
cout << pCurrent->getV() << " ";
}
return 0;
}
Thanks
To make the list permanent, you first have to declare your head node and then for each iteration in your for loop, add on to that list.
int main()
{
Class *pFirst; //pointer to first element
pFirst->setV(0);
Class *pLast; //pointer to last element
Class *pCurrent; //pointer to current element
pFirst->pNext = pCurrent; // To keep track of the list via head
for(int i = 0; i < 4;i++)
{
pCurrent = new Class;
pCurrent->setV(i);
pCurrent->pNext = NULL;
}
for(int i = 0; i < 4;i++)
{
cout << pCurrent->getV() << " ";
}
return 0;
}
Related
I'm working on a class project and this piece of code won't let me delete an instance of a class without throwing a breakpoint error.
The class is Node, I'm trying to build a singly linked list for data structures and algorithms. I'll include the whole program, it isn't long, but the code in question that's causing the problem is in deleteMin(), the delete u.
#include <iostream>
using namespace std;
// we create a Node class.
class Node { // inside this class we hold two pieces of information.
int x; // the integer x, which is our data.
Node* next; // and the address of the next node.
public:
Node(int x0) : x(x0), next(NULL) { } // Here I've set up a constructor that sets x equal to the argument
// and defaults the next address to NULL.
bool add(int newValue); // Here follows our three required functions.
int deleteMin();
int size();
void printSSL(); // I also added a printSSL() function so that we can test and see what's going on.
};
//Originally I wanted to put these inside of the Node class, but then you'd end up with a unique head and tail for every Node.
//So instead I've left them outside. If you wanted to create multiple SSList's then you'd want to create an object out of these as well.
Node* head; // The first value in the our SLList.
Node* tail; // The last value in our SLList.
int n; // The number of elements in the list.
// I should mention here that head and tail are set equal to the first value in the SLList in the Main() function below.
// Here follows the actual implementation.
// I chose to try and simplify things by focusing on the add() function.
// If the add function organizes the information, and puts it into the SLList in order,
//then deleteMin() only has to pull the first value.
bool Node::add(int newValue) { // add() is a member function of Node and it takes in the newValue were adding to the list.
Node* u = new Node(newValue); // First thing we do is create a new Node using the argument value x. We pass this into a pointer, u.
if (newValue <= head->x) { // Next, we check to see if the new value is less than the head.
u->next = head; // if it is, then our job is done and we just make this new, smaller value, the new head.
head = u; // we do this by making the initial head equal to the next address in the new Node u.
n++; // Once we have the address saved, we make u into the new head and increment n.
return true; // There's no iteration in this case, so this if statement would be O(1).
}//O(1)
else { // If the new value is greater than the head, then we have to store it further back in the SLList.
Node* y = head; // This was the hardest part of the whole thing... I solved it by creating two Node pointers,
Node* z = head; // Both Node pointers are set equal to head, but this is mostly just to ensure that they aren't empty.
while ((newValue > y->x) && (y != tail)) { // Then I set a while loop that looks at whether the new value is less than the value in the head.
z = y; // The while loop continues, moving through the list of values, setting y equal to the next value,
y = y->next; // and using z to keep track of the former value.
} // The loop exits when we either a) hit the end of the SLList, y == tail, or when the new value is
if (y == tail) { // smaller than the next value, newValue < y->x. When the loop exits we have to deal with these two
y->next = u; // scenarios separately. If we reached the end of our list, then adding the new value is as simple as
tail = u; // setting y->next equal to u, then we make u into the new tail.
} // if we didn't reach the end of the list, then we have to set u inbetween z and y. This was really
else { // the only reason I needed z. I needed to be able to update the address of the previous Node, and
z->next = u; // I also needed to have the address of the next Node, this way I could slip u inbetween the two.
u->next = y; // Worst case scenario, this function runs through the entire SLList and then adds the value at the end.
} // I could have shaved off some time by asking if(newValue > tail->x) then run the z->next=u; and u->next=y; after
n++; // after that, but that throws an error becauset ail is a NULL pointer, which is bull#*#!
return true; // because I'm not dealing the tail->next, all I care about is tail->x which isn't NULL.
}//O(n) // But because this is an SSList and not a DLList I have no way of going to the n-2 element.
}//O(max(1, n)) // When that's done, we just increment n and leave the function.
// Considering that the worst case scenario, when x > tail->x, takes us through the whole SLList.
// I'm going to say that this add function is O(n).
int Node::deleteMin() { // The deleteMin() function starts by checking whether or not the
int x = head->x;
Node* u = head;
head = head->next;
delete u; // I have to figure out what the hells going on right here, why can't I delete this?
return x;
}
int Node::size() {
cout << n + 1 << endl;
return n + 1;
}
void Node::printSSL() {
Node* u = head;
cout << "Head:";
for (int i = 0; i <= n; i++) {
cout << i << ":(" << u->x << ", " << u->next << ") ";
u = u->next;
}
cout << " Tail" << endl;
}
int main()
{
Node one(1);
head = &one;
tail = &one;
one.printSSL();
one.deleteMin();
}
You declared an object of the type Node
Node one(1);
You may not apply the operator delete to a pointer to the object because the object was not allocated dynamically. It has automatic storage duration.
Pay attention to that it is a bad idea when functions depend on global variables. For example you will be unable to define two lists in your program.
What you need is to define a class named something like List the following way
class List
{
private:
Node *head = nullptr, *tail = nullptr;
public:
// special member functions and some other member functions;
void clear();
~List() { clear(); }
};
and to allocate nodes dynamically that will be inserted in the list.
The destructor and the function clear will delete all the allocated nodes in the list.
class Node also should be defined as a nested class of the class List.
For example the function clear can be defined the following way
#include <functional>
//...
void List::clear()
{
while ( head )
{
delete std::exchange( head, head->next );
}
tail = nullptr;
}
#include <iostream>
using namespace std;
class SLList { // SLList is the object that holds the entire list.
public: // The Node class lives inside the SLList class.
struct Node {
int data;
Node* next;
Node(int x0) : data(x0), next(NULL) {}
Node() : data(NULL), next(NULL) {}
};
Node* head;
Node* tail;
int n;
SLList() : n(0) {
Node* initial = new Node();
head = initial;
tail = initial;
cout << "You've created a new SSList" << endl;
}
bool add(int newValue);
int deleteMin();
int size();
void printSSL();
};
bool SLList::add(int newValue) { //
if (n == 0) {
head->data = newValue;
n++;
return true;
}
else {
Node* u = new Node(newValue);
if (newValue <= head->data) { //
u->next = head; //
head = u; //
n++; //
return true; //
}//O(1)
else { //
Node* y = head; //
Node* z = head; //
while ((newValue > y->data) && (y != tail)) { //
z = y; //
y = y->next; //
} //
if (y == tail && newValue > y->data) {
y->next = u; //
tail = u; //
} //
else { //
z->next = u; //
u->next = y; //
} //
n++; //
return true;
}
}//O(n) //
}//O(max(1, n)) //
int SLList::deleteMin() {
int x = head->data;
Node* u = head;
head = head->next;
delete u;
n--;
return x;
}//O(1)
int SLList::size() {
cout << n + 1 << endl;
return n + 1;
}//O(1)
void SLList::printSSL() {
Node* u = head;
cout << n << " Nodes|" << "Head:";
for (int i = 0; i < n; i++) {
cout << i << ":(" << u->data << ", " << u->next << ") ";
u = u->next;
}
cout << " Tail" << endl;
}//O(n)
int main() {
SLList* one = new SLList;
one->printSSL();
one->add(30);
one->printSSL();
one->add(20);
one->printSSL();
for (int i = 0; i < 7; i++) {
int x = rand() % 50;
one->add(x);
one->printSSL();
}
for (int i = 0; i < 9; i++) {
one->deleteMin();
one->printSSL();
}
}
I am trying to implement a simple open hash in c++ for the sake of learning. I am getting very confused about the interaction of functions with array pointers, and I am at the end of my wits.
The code:
struct node{
int data;
node* next;
node* prev;
bool state;
node(){
prev = next = NULL;
state = true;
}
};
//state true means empty, state false means full.
void insert(node *array,int value){
node *current = array;
if(array->state == true){
array->data = value;
array->state = false;
} else {
node* add = new node();
add->data = value;
add->state = false;
while(current->next != NULL){
current = current->next;
}
current->next = add;
add->prev = current;
}
}
void display(node *array, int size){
node *show = new node();
for(int i = 0; i< size; i++){
if(array->state == false){
cout<<array->data;
show = array;
while(show->next != NULL){
show = show->next;
cout<<" --> "<<show->data;
}
} else {
cout<<"Empty.";
}
cout<<"\n\n";
}
}
int main(){
int size;
cout<<"Enter size of the hash table: ";
cin>>size;
node *array = new node[size];
int value;
cout<<"Enter Value: ";
cin>>value;
int index = value%size;
//inserting single value
insert(&array[index],value);
//Hash table output.
display(array,size);
return 0;
}
When I run this code, instead of showing "empty" in places where the array's state is empty, it seems as if the entire array has the same value. The problem lies in the insert function, but I cannot figure it out.
You can simplify this by making the Hashtable an array of pointers to Node. A nullptr then means the slot is empty and you don't have empty and full nodes. Also Nodes only need a next pointer and usually new entries are added to the beginning of the buckets instead of the end (allows duplicate entries to "replace" older ones). Inserting at the beginning of a list becomes real easy with Node **.
#include <cstddef>
#include <iostream>
struct Table {
struct Node {
Node * next;
int data;
Node(Node **prev, int data_) : next{*prev}, data{data_} {
*prev = this;
}
};
std::size_t size;
Node **tbl;
Table(std::size_t size_) : size{size_}, tbl{new Node*[size]} { }
~Table() {
for (std::size_t i = 0; i < size; ++i) {
Node *p = tbl[i];
while(p) {
Node *t = p->next;
delete p;
p = t;
}
}
delete[] tbl;
}
void insert(int value) {
Node **slot = &tbl[value % size];
new Node(slot, value);
}
void display() const {
for(std::size_t i = 0; i < size; i++) {
std::cout << "Slot " << i << ":";
for (const Node *node = tbl[i]; node; node = node->next) {
std::cout << " " << node->data;
}
std::cout << std::endl;
}
}
};
int main(){
std::size_t size;
std::cout << "Enter size of the hash table: ";
std::cin >> size;
Table table{size};
int value;
std::cout << "Enter Value: ";
std::cin >> value;
//inserting single value
table.insert(value);
//Hash table output.
table.display();
return 0;
}
I write a code for insertion sort for integer data in linked list in c++, I referred to the algorithms on the Internet, and finally took the following code using array as a basic concept for my version.
however, the sorting always ignore my first element,(but all the other element is ordered well).
I have tried checking my loop statement, checking the pointer address while looping (because my key pointer loop at first time didn't go into the judge pointer loop), checking the shifting mechanism while comparing, but I cannot find my logic problem.
(I know someone would said I doesn't provide enough data for you to help me, but I have been checking these things for two days, including asking friends and searching the solutions existed on website. So I really hope someone can answer me without blame, thank you.)
array version(on the internet)
#include <iostream>
void InsertionSort(int *arr, int size){
for (int i = 1; i < size; i++) {
int key = arr[i];
int j = i - 1;
while (key < arr[j] && j >= 0) {
arr[j+1] = arr[j];
j--;
}
arr[j+1] = key;
}
}
linked list version(by my own)
Node class used in my version
class Node
{
public:
Node()
{
next = NULL;
pre = NULL;
}
Node(int n)
{
data = n;
next = NULL;
pre = NULL;
}
int getData() { return data; }
Node *getNext() { return next; }
Node *getPre() { return pre; }
void setData(int d) { data = d; }
void setNext(Node *n) { next = n; }
void setPre(Node *p) { pre = p; }
private:
int data;
Node *next, *pre;
};
class List
{
public:
List() { list = NULL; }
List(int n) { generate(n); }
void generate(int n)
{
int j;
list = NULL;
for(j = 0;j < n;j ++)
generate();
}
void generate()
{
Node *buf = new Node(rand());
buf->setNext(list); //list->NODE2.next->NODE1.next->NULL
if(list != NULL)
list->setPre(buf);
list = buf;
}
void insertionSort()
{
bool breakByCompare;
Node* keyptr;
Node* judgeptr;// judge is the value that is going to compare with key
int key;
for(keyptr = list->getNext(); keyptr != NULL;
keyptr = keyptr->getNext()){
//if we set list as 5,7,6 ; 6 is key
key = keyptr->getData();//store the key value for the setting after shifting
breakByCompare = 0;
for(judgeptr = keyptr->getPre() ; judgeptr->getPre()!= NULL;
judgeptr= judgeptr->getPre()){
//list: 5,7,6 ; 7 is judge
if(judgeptr->getData() > key){
// 7>6, so we shift 7 to the position which was for 6
judgeptr->getNext()->setData(judgeptr->getData());// list: 5,7,7 ;
cout << judgeptr->getData() << " , " << keyptr->getData() << endl;
}
else{
break;
}
}
judgeptr->getNext()->setData(key);// list: 5,6,7
}
}
void print()
{
Node *cur = list;
while(cur != NULL)
{
cout<<cur->getData()<<" ";
cur = cur->getNext();
}
cout<<endl;
}
private:
Node *list;
};
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#define SIZE 100
int main()
{
srand(time(NULL));
List *l = new List(10);
l->print();
l->insertionSort();
l->print();
}
One of the most important difference between a linked list and an array is that it is sometimes required to handle the first element as a special case.
Here is a fixed version of your sorting method :
void insertionSort()
{
bool breakByCompare;
Node* keyptr;
Node* judgeptr;
int key;
for(keyptr = list->getNext(); keyptr != NULL; keyptr = keyptr->getNext()){
key = keyptr->getData();
breakByCompare = 0;
// I replaced judgeptr->getPre() by judgeptr in the condition
// to allow the backward loop to go until the root
for(judgeptr = keyptr->getPre() ; judgeptr != NULL; judgeptr= judgeptr->getPre()){
if(judgeptr->getData() > key){
judgeptr->getNext()->setData(judgeptr->getData());
cout << judgeptr->getData() << " , " << key << endl;
}
else break;
}
// Here is the special case : we must support a null judgeptr
// and replace its next element by the list
if (judgeptr) judgeptr->getNext()->setData(key);
else list->setData(key);
}
}
I am trying to make a dynamic array in my member function, however, it seems to create a new dynamic array each time I call the function. Is there anyway to create a dynamic array inside a member function so it doesn't remake itself.
class predator
{
private:
string name;
string species;
protected:
string *list;
public:
predator(string theSpecies);
void killsRecorded(string kills); // add a new kill to the end of the predator's list of kills
string *killsList(); // return a pointer to the array of all kills by this predator
int noOfTotalKills(); // how many kills have been recorded
int k;
static int n;
};
//The header file
void predator::killsRecorded(string kills)
{
k = 0;
list = new string[5];
*(list + k) = kills;
k = n++;
cout<< k<< endl;
}
string* predator::killsList()
{
//cout<< (sizeof(list)/sizeof(list[0]))<< endl;
for(int i=0; i<5; i++)
{
cout<< *(list + i)<< endl;
}
}
Above is my class and header file, void killsRecorded(string kills) should add kills to my array, however, when I try that in my main.
predator *prey;
prey = new predator("Cheetah");
prey->killsRecorded("Mouse");
prey->KillsRecorded("Donkey");
prey->killsList();
It prints out
Created a hunter that is a Cheetah
0
1
Donkey
*BLANK LINE
*BLANK LINE
*BLANK LINE
*BLANK LINE
Instead, Mouse should be in the first line and Donkey in the second. Am I doing something wrong? Also, I can't use vectors, it's for an assignment.
In your constructor, assign n a default value, say 5. Then create an array of that size.
predator::predator()
: n(5),
k(0)
{
kills = new string[n];
}
Then recordKills checks to see if there is space in kills, reallocating if necessary:
recordKills(string kill)
{
if(k >= n) {
string* oldKills = kills;
kills = new string[2*n];
// copy
for(int i = 0; i< n: i++) {
kills[i] = oldKills[i];
}
n *= 2;
delete [] oldKills;
}
kills[k++] = kill;
}
It's generally a bad idea to call a variable by the name of a data structure, so I renamed 'list' to 'kills'.
Then when printing the kills, loop until k:
string* listKills()
{
for(int i = 0; i < k; i++) {
cout << kills[i] << endl;
}
return kills;
}
Remember to delete kills in the destructor!
Hmm, your killsRecorded(string kills) method is an example of how not to program...
you erase list losing all previously recorded kill
you lose the pointer obtained by a previous new[] which leads to a memory leak (how could you free them now your program has forgotten what had been allocated)
What should be done (what vector class does under the hood):
define a chunk of slots that you initially allocate
add the recorded strings to this simple array until it is full
when it is full allocate another array say of twice the size, carefully copy the values from the old array, release the old array and only them affect the new array to the saved pointer
do not forget to release the allocated array in class destructor
and store in the class the current size (number of kills) and the maximum size (allocated size)
Code could be:
class predator
{
private:
string name;
string species;
protected:
string *list;
size_t max_size;
size_t cur_size;
public:
predator(string theSpecies);
void killsRecorded(string kills); // add a new kill to the end of the predator's list of kills
string *killsList(); // return a pointer to the array of all kills by this predator
int noOfTotalKills(); // how many kills have been recorded
/*int k; what it that???
static int n;*/
};
//The implementation file
predator(string theSpecies): species(species) {
list = new string[5];
max_size = 5;
cur_size = 0;
// what do you do with name ?
}
void predator::killsRecorded(string kills)
{
if (cur_size >= max_size) { /* need a bigger array */
max_size *= 2;
temp = new string[max_size];
for(int i=0; i<cursize; i++) { // copy previous recorded values
temp[i] = list[i];
}
delete[] list; // free previous allocated array
list = temp; // ok list is now big enough
}
list[cur_size++] = kills;
}
You should use std::vector...
to do that you have to
#include <vector>
with the command
std::vector<string> kills;
you can create a new vector of strings
with the command
kills.pushback(stringvalue);
you can add a new string into your vector "list" also you don't have to count your kills... you can use
kills.size();
to get the number of strings back.
To get the values (strings) back you can use the vector like an array
string name = kills[3];
btw: you should save the vector as a member... to do that you have to save it in your class definition (header)
If you arn't allowed to use std::vector, you can write your own list...
class list
{
private:
node* head;
int size = 0;
struct node
{
node* next;
string value;
}
public:
list();
~list();
void PushBack(string);
string GetElement(int index);
int GetSize();
};
list::list()
{
head = new list();
head->next = nullptr;
}
list::~list()
{
node* temp = head;
node* temp2 = temp;
do //delete hole list
{
temp2 = temp->next;
delete temp;
temp = temp2;
}while(temp != nullptr);
}
void list::PushBack(string item)
{
node* temp = head;
while(temp->next != nullptr)
{
temp = temp->next;
}
//found the end of the list
node* newNode = new node();
newNode->value = item;
newNode->next = nullptr;
temp->next = newNode;
size++;
}
int list::GetSize()
{
return size;
}
string list::GetElement(int index)
{
node* temp = head;
while(temp->next != nullptr)
{
temp = temp->next;
if(index == 0)
{
return temp->value;
}
index--;
}
//index out of bounds
return "";
}
I can not check if the code is correct at the moment, because on this computer is no IDE... but I think it should word ;)
BTW: you can use this list instead of an array to do that you have to write:
list kills;
kills.PushBack("Peter");
kills.PushBack("Thomas");
kills.PushBack("Alex");
for(int i = 0; i< kills.GetSize();i++)
{
std::cout<<kills.GetElement(i)<<std::endl;
}
I have problem about struct and class. Now I define class inside the struct and then I create the struct as node and push node in queue. The problem is when I pop queue I create the node to receive pop node but the class in node is a new one, not the same as before push. Follow as code.
struct queueNode {
Puzzle puzzle;
queueNode *next;
short lastMove;
};
class Puzzle {
private :
short field[4][4];
short posBlankI;
short posBlankJ;
public :
Puzzle();
bool isFinish();
void print();
void create();
}
class Queue {
private:
queueNode *first, *last;
public:
Queue(){
first = new queueNode;
first->next = NULL;
last = first;
}
~Queue() { delete first; }
bool isEmpty(){ return (first->next == NULL); }
void push(queueNode *aux){
last->next = aux;
last = aux;
}
queueNode pop(){
queueNode *aux = first;
first = first->next;
return *aux;
}
};
//global variable
Queue *q = new Queue();
int main(){
queueNode *root = new queueNode;
root->puzzle.create();
q->push(root);
q->pop().puzzle.print();
return 0;
}
Yes, you can define a class inside a struct. The code sample doesn't do that.
The problem has nothing to do with a class being member of a struct.
The constructor of Queue creates a queue with 1 blank node. q->push(root) inserts the 2nd node at the end. q->pop() returns the copy of the 1st (blank) node, not the 2nd as you expect.
pop return a object not a pointer. A new queueNode is created and its content is copied from *aux. You should modify pop to return a pointer of queueNode.
When you create the Queue, it creates a queueNode using new and puts it into the Queue by default. So when you call pop() it returns that default node you did not configure using create().
I modified your code a bit and got it to compile and run in order to illustrate the point I am making above.(Note: it compiles on VS2010, remove #include "stdafx.h" if you use something else)
Hopefully this helps you see exactly what you are doing.
I would not recommend using the code below in an implementation you care about. Use it as a learning tool only. I suggest separating out your class declarations into separate header files and the implementations into separate CPP files. It helps organize things.
output:
0000
0000
0000
0000
1111
1111
1111
1111
Code:
#include "stdafx.h"
#include <iostream>
class Puzzle {
private :
short field[4][4];
short posBlankI;
short posBlankJ;
public :
Puzzle()
{
for(int i = 0; i<4; i++)
{
for(int j = 0; j < 4; j++)
{
field[i][j] = 0;
}
}
}
bool isFinish();
void print()
{
for(int i = 0; i<4; i++)
{
for(int j = 0; j < 4; j++)
{
std::cout<<field[i][j];
}
std::cout<<std::endl;
}
}
void create()
{
for(int i = 0; i<4; i++)
{
for(int j = 0; j < 4; j++)
{
field[i][j] = 1;
}
}
}
};
struct queueNode {
Puzzle puzzle;
queueNode *next;
short lastMove;
};
class Queue {
private:
queueNode *first, *last;
public:
Queue(){
first = new queueNode;
first->next = NULL;
last = first;
}
~Queue() { delete first; }
bool isEmpty(){ return (first->next == NULL); }
void push(queueNode *aux){
last->next = aux;
last = aux;
}
queueNode pop(){
queueNode *aux = first;
first = first->next;
return *aux;
}
};
//global variable
Queue *q = new Queue();
int main(){
queueNode *root = new queueNode;
root->puzzle.create();
q->push(root);
q->pop().puzzle.print();
q->pop().puzzle.print();
system("Pause");
return 0;
}
Your push adds your node to the end of the internal list. Which isn't empty.
The standard library has queues, lists, and all sorts of nice containers. Use one of those.