I tried to implement tower of hanoi using stack but there seems to be some problem when running the program. It runs fine sometimes but sometimes the program terminates.
I created a separate class to work as stack.
class stack{
int* arr;
int stackSize;
public:
stack(int size = 0);
~stack();
void push(int a);
int pop();
};
stack::stack(int size){
this->arr = new int(size);
this->stackSize = 0;
}
stack::~stack(){
delete []this->arr;
}
void stack::push(int a){
this->stackSize++;
int* temp = new int(this->stackSize);
for(int i = 0; i < this->stackSize; i++){
temp[i] = this->arr[i];
}
temp[this->stackSize-1] = a;
delete []this->arr;
this->arr = temp;
}
int stack::pop(){
if(this->stackSize <= 0){
cout << "stack underflow" << endl;
}else{
this->stackSize--;
int popped = this->arr[this->stackSize];
int* temp = new int(this->stackSize);
for(int i = 0; i < this->stackSize; i++) {
temp[i] = this->arr[i];
}
delete []this->arr;
this->arr = temp;
return popped;
}
}
void toh(int n, stack &s, stack &des, stack &aux){
if (n <= 0)
return;
toh(n-1, s, aux, des);
des.push(s.pop());
display();
toh(n-1, aux, des, s);
}
this->arr = new int(size); does not allocate memory for an array, it allocates for a single integer. You want this->arr = new int[size]; you do similar in your push function too.
Also, to add, your push should only allocate a new array when it is full.
Also also, in pop, you do not return a value in the case when the if is true. Should either throw an exception, or return a dummy value.
Related
I was doing a code in which I have to create a dynamic array and a pointer (the pointer should be used to move through the data of the array). I have to make methods get (to return the index of a number to be searched in the array), update (when get method returns the index the update method can update the value), length(this method should return the size of the array), next(this method should move the pointer to the next index of the array), start(this method should move the pointer to the start of the array), end(this method should move pointer to the end of array) and Add(it should add a block to the array)
Here is the code
#include <iostream>
#include <conio.h>
using namespace std;
class Runner
{
private:
int *arr;
int *ptr;
int size;
// to input in array
void Input()
{
for (int i = 0; i < size; i++,*ptr++)
{
cout << "Enter value no. " << i + 1 << "\t";
cin >> arr[i];
}
}
//to allocate memory
void Create()
{
cout << "Enter the total number of elements :\t";
cin >> size;
arr = new int[size];
ptr = arr;
Input();
}
public:
//constructor to define starting value
Runner()
{
ptr = NULL;
size = 0;
arr = NULL;
}
//get function
int get(int num)
{
bool NotNull = false;
int index = 0;
do
{
if (ptr != NULL)
{
ptr = &arr[0];
for (int i = 0; i < size; i++,*(ptr++))
{
if (num == *ptr)
{
index = i;
break;
}
}
NotNull = true;
}
else
{
Create();
}
} while (!NotNull);
return index;
}
//update function
void Update(int num)
{
int val;
int index = get(num);
cout << "Enter value to update :\t";
cin >> val;
ptr = ptr + index;
*ptr = val;
}
//length function
int length()
{
if (ptr == NULL)
{
Create();
}
return size;
}
//moving pointer back
void Back()
{
bool NotNull = false;
do
{
if (ptr != NULL)
{
*(ptr--);
NotNull = true;
}
else
{
Create();
}
} while (!NotNull);
}
//moving pointer forward;
void Next()
{
bool NotNull = false;
do
{
if (ptr != NULL)
{
*(ptr++);
NotNull = true;
}
else
{
Create();
}
} while (!NotNull);
}
//to point at the start of array
void Start()
{
bool NotNull = false;
do
{
if (ptr != NULL)
{
ptr = &arr[0];
NotNull = true;
}
else
{
Create();
}
} while (!NotNull);
}
//to move pointer to the end
void End()
{
bool NotNull = false;
do
{
if (ptr != NULL)
{
ptr = &arr[size - 1];
NotNull = true;
}
else
{
Create();
}
} while (!NotNull);
}
//to add a block into array
void Add()
{
int NewSize = size + 1;
int *temp = new int[NewSize];
for (int i = 0; i < size; i++)
{
temp[i] = arr[i];
}
size = NewSize;
ptr = temp;
if (arr != NULL)
{
delete[] arr;
}
arr = NULL;
arr = temp;
cout << "You have been provided a new block to add 1 data entry\n";
cout << "Enter value :\t";
cin >> arr[size - 1];
}
};
int main() //main made just for testing above method's working
{
Runner *obj = new Runner();
obj->get(3);
obj->Update(20);
cout << obj->length() << "\n";
obj->Next();
obj->End();
obj->Back();
obj->Start();
obj->Add();
delete obj;
_getch();
return 0;
}
Well the part of code giving me error is the Add method in which i have to increase the size of array without using realloc().
The Add Method is as follows:
void Add()
{
int NewSize = size + 1;
int *temp = new int[NewSize];
for (int i = 0; i < size; i++)
{
temp[i] = arr[i];
}
size = NewSize;
ptr = temp;
if (arr != NULL)
{
delete[] arr; //the point where heap corruption error occurred
}
arr = NULL;
arr = temp;
cout << "You have been provided a new block to add 1 data entry\n";
cout << "Enter value :\t";
cin >> arr[size - 1];
}
Help me in solving this issue.
The last two statements in Update
ptr = ptr + index;
*ptr = val;
will set pointer to some value relative to the last value, which was set in the preceding call to get. This will cause ptr to refer to memory beyond the allocated space for arr if the value was found in the second half of the array. When you assign the value with *ptr = val; you are at best writing to the wrong array element, at worst writing to memory you don't own. The "Heap Corruption" error detects this.
The solution would be to set ptr using arr instead:
ptr = arr + index;
since ptr may point past the end of the allocated space if the number was not found (and index would be 0).
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;
}
Here's my main in Airport.cpp:
#include <iostream>
#include "Airport_Queue.h"
#include "Airplane.h"
#include <stdlib.h>
int main(){
Airplane *b = new Airplane(true);
(*b).come();
(*b).go();
std::cout << "........." << std::endl;
Airport_Queue *landing_queue = new Airport_Queue(5);
Airplane *a0 = new Airplane(true);
(*landing_queue).enqueue(a0); //error here
//(*landing_queue).dequeue();
return 0;
This is my Airport_Queue.cpp
#include "Airport_Queue.h"
Airport_Queue::Airport_Queue(unsigned n){
Airplane** a = new Airplane*[n];
capacity = n;
size = 0;
head = tail = 0;
}
Airport_Queue::~Airport_Queue(){
for (size_t i = 0; i < size; i++){
delete a[i];
}
delete [] a;
}
void Airport_Queue::enqueue(Airplane* airplane){
if (!(*this).isFull()){
a[tail] = airplane;
(*a[tail]).come();
tail = (tail+1) % capacity;
size++;
}
else{
std::cerr << "Queue is full." << std::endl;
}
}
Airplane* Airport_Queue::dequeue(){
if (!(*this).isEmpty()){
size_t x = head;
(*a[head]).go();
head = (head+1) % capacity;
size--;
return a[x];
}
else{
std::cerr << "Queue is empty." << std::endl;
return NULL;
}
}
bool Airport_Queue::isEmpty(){
if (size == 0)
return true;
else
return false;
}
bool Airport_Queue::isFull(){
if (size == capacity)
return true;
else
return false;
}
int Airport_Queue::getSize(){
return size;
}
I also have a class called Airplane. The command I use to compile and link is
g++ -std=c+11 -Wall -g -o airport Airport.cpp Airplane.cpp Airport_Queue.cpp
How can I fix this run-time error? The error is when I call enqueue. Then I get
4 [main] airport 3796 cygwin_exception::open_stackdumpfile: Dumping stack trace to airport.exe.stackdump
Please. And thank you.
Problems I see:
You have one member variable size. You need two - capacity and size.
In Airport_Queue::Airport_Queue
Airport_Queue::Airport_Queue(unsigned size){
Airplane** a = new Airplane*[size];
size = 0; // This is the argument, not the member variable.
// The member variable remains uninitialized.
head = tail = 0;
}
You need:
Airport_Queue::Airport_Queue(unsigned size){
Airplane** a = new Airplane*[size];
this->capacity = size;
this->size = 0;
head = tail = 0;
}
In Airport_Queue::~Airport_Queue
Airport_Queue::~Airport_Queue(){
for (size_t i = 0; i < sizeof(a); i++){
// sizeof(a) does not give you the number of elements
// in the array. It just gives you the size of the pointer.
delete a[i];
}
delete [] a;
}
You need:
Airport_Queue::~Airport_Queue(){
for (size_t i = 0; i < this->size; i++){
delete a[i];
}
delete [] a;
}
In Airport_Queue::enqueue
Following on the logic from the destructor, the following line needs to be changed.
tail = (tail+1) % sizeof(a);
Change it to:
tail = (tail+1) % capacity;
In In Airport_Queue::dequeue
You have an error similar to the above. Change the line
head = (head+1) % sizeof(a);
to
head = (head+1) % capacity;
In Airport_Queue::isFull
Change the line
if (size == sizeof(a))
to
if (size == capacity)
I hope this fixes most of your problems. If there are any that I missed, hopefully you can find them.
I am trying to implement a minHeap of my own and i am getting an error related to my templated class
Here is the main.cpp:
#include <iostream>
#include"road.h"
#include"region.h"
#include"minHeap.h"
using namespace std;
int main()
{
// int numCities;
int numOldRoads;
cin >> numOldRoads;
minHeap<int> roadHeap(numOldRoads);
roadHeap.push(1);
roadHeap.push(4);
roadHeap.push(5);
roadHeap.push(2);
roadHeap.push(7);
roadHeap.push(6);
roadHeap.push(3);
roadHeap.push(9);
roadHeap.push(8);
int temp;
for(int i = 0; i<numOldRoads; i++){
temp = roadHeap.top();
roadHeap.pop();
cout << temp;
}
return 0;
}
Here is the header file:
#ifndef MIN_HEAP
#define MIN_HEAP
template<class T>
class minHeap{
public:
minHeap(int);
void push(T);
void pop();
T top();
void doubleHeapCap();
bool isEmpty();
private:
T *heap;
int heapSize;
int capacity;
};
#endif
Here is the implementation of the minHeap (also in the header because it was giving me errors otherwise):
#include"minHeap.h"
template<class T>
minHeap<T>::minHeap(int theCapacity = 10){
if(theCapacity < 1) throw "Capacity must be >=1.";
capacity = theCapacity;
heapSize = 0;
heap = new T[capacity + 1]; //heap [0] is not used
}
template<class T>
void minHeap<T>::push(const T& e){
//inserts e into min heap
if(heapSize == capacity){ //doubles capacity if Heap is too small
minHeap.doubleHeapCap;
capacity *=2;
}
int currentNode == ++heapSize;
while(currentNode != 1 && heap[currentNode/2] > e){
//bubble up node
heap[currentNode] = heap[currentNode/2]; //moves parent down
currentNode /= 2; //moves current node
}
heap[currentNode] = e;
}
template<class T>
void minHeap<T>::pop(){
//Deletes smallest element from heap and restructures heap
if(isEmpty()) throw "Heap is empty. Cannot delete.";
//deelt smallest element
heap[1].~T();
//remove last element from heap
T lastE = heap[heapSize--];
//trick down to restructure heap
int currentNode = 1; //root of heap
int child = 2; // first child of heap
while(child <= heapSize){
//set child to smaller child of currentNode
if(child < heapSize && heap[child] > heap[child+1]) child++;
//can we put lastE in currenNode?
if(lastE >= heap[child]) break; //yes we can
//no we can't, Obama
heap[currentNode] = heap[child]; //move child up
currentNode = child; child *= 2; // move a level down
}
//after you finally find one, place the node in the corrent position
heap[currentNode] = lastE;
}
template<class T>
bool minHeap<T>::isEmpty(){
//says whether or not hear is empty
if(heapSize == 0) return 1;
else return 0;
}
template<class T>
void minHeap<T>::doubleHeapCap(){
int currentcapacity = this->capacity;
int newCapacity = (this->capacity)*2;
minHeap *temp;
T *newHeap;
//create a new heap with twic the size
newHeap = new T[newCapacity + 1];
//copy elements over
for(int i=0; i<=capacity; i++){
newHeap[i] = this->heap[i];
}
//delete the old heap
temp = heap;
heap = newHeap;
newHeap = 0;
delete[] temp;
}
and here is the error:
In instantiation of 'void minHeap<T>::doubleHeapCap() [with T = int]':
required from 'void minHeap<T>::push(const T&) [with T = int]'
required from here
error: cannot convert 'int*' to 'minHeap<int>*' in assignment|
warning: unused variable 'currentcapacity' [-Wunused-variable]|
I pretty much copied the code from my data structures book and modified it (the book shows an implementation for a Max Heap and i am interested in a min heap).
As you can see all i am trying to do with the main right now is print out the ascending list of integers that i try to push to the min heap.
I think i dont fully understand how to implement template class functions...
In your class declaration you have this:
T *heap;
In doubleHeapCap you have this:
minHeap *temp;
// code...
temp = heap;
If T is int then you are trying to assign an int* (heap) to a minHeap<int>* (temp). Basically, make temp into a T*, too, and it should work. Or you could just dispense with temp altogether and write:
std::swap(heap, newHeap);
delete[] newHeap;
Hi everyone: Here i have created a queue from two stacks: You add to the one and remove from the other - when you want to remove the first stack dumps all its data into the second one, and it works perfectly - BUT
whenever i try to execute this loop without the bottom for loop or cin
the program receives a segmentation fault, i mean the most bottom for loop doesn't even execute but take it out and see what happens. Could this be some sort of buffer overflow
and Gcc needs time to manage the memory?
=====================================================================
struct Node
{
int DataMember;
Node* Next;
};
class Que
{
public:
Que();
~Que();
void Add(int);
void Pop();
int getSize();
void Purge();
private:
Node* Head;
bool StackOrQue; //True = Que False = Stack
int Size;
int Remove();
void Reverse();
};
void Que::Purge()
{
while(Head != NULL)
Pop();
if(StackOrQue)
StackOrQue = false;
}
int Que::getSize()
{
return Size;
}
Que::Que()
{
Head = NULL;
Size = 0;
StackOrQue = false;
}
Que::~Que()
{
Head = NULL;
}
void Que::Add(int q)
{
if(StackOrQue)
Reverse();
Size += 1;
Node* Temp = new Node;
Temp->DataMember = q;
Temp->Next = Head;
Head = Temp;
}
int Que::Remove()
{
int i = Head->DataMember;
Node* Temp = Head->Next;
delete Head;
Size -= 1;
Head = Temp;
return i;
}
void Que::Pop()
{
if(!StackOrQue)
Reverse();
cout << Remove();
}
void Que::Reverse()
{
Que TempStack;
int k = Size;
for(int i = 0; i < k; i++)
TempStack.Add(this->Remove());
delete this;
*this = TempStack;
if(!StackOrQue)
StackOrQue = true;
else
StackOrQue = false;
}
=====================================================================
Que q;
char a = NULL;
while(a != 'x')
{
q.Purge();
q.Add(1);
q.Add(2);
q.Add(3);
q.Add(4);
q.Add(5);
q.Add(6);
q.Add(7);
q.Add(8);
int size = q.getSize();
for(int i = 0; i < size; i++)
q.Pop();
//cin >> a;
for(int i = 0; i < 0; i++)
;
}
Thanks in-advance
delete this;
*this = TempStack;
There are some extreme corner cases in which delete this; actually does the right thing. This is not one of them. Specially since your Queue is placed in the stack, and you further try to delete it. If you intend to call the destructor instead do this->~Queue(), however after a manual destruction the only sensible thing to do next is a placement new. Assigning to *this is almost always a bad idea (if you bring inheritance into the picture, you have just caused a slice object to be created and more problems ahead the road). Also, your class should be implementing a copy constructor and an assignment operator, to correctly handle the resources allocated.