What I want to happen is for the pushFront(int) function to do this:
bool stack::pushFront( const int n )
{
items[++top] = n; // where top is the top of the stack
return true; // only return true when the push is successful
}
items is a struct type of the object "item". Have a look:
class stack
{
stack(int capacity);
~stack(void);
...
private:
int maxSize; // is for the item stack
int top; // is the top of the stack
struct item {
int n;
};
item *items;
i've defined the ctor to the stack class object and dtor as follows:
stack::stack(int capacity)
{
items = new item[capacity];
if ( items == NULL ) {
throw "Cannot Allocoate Sufficient Memmory";
exit(1);
}
maxSize = capacity;
top = -1;
}
stack::~stack(void)
{
delete [] items;
items = NULL;
maxSize = 0;
top = -1;
}
Yes the main issue for me is the items[++top] = n; statement. I've been trying to find ways around it like below:
bool stack::pushFront(const int n)
{
int *a = new int[maxSize];
a[++top] = n;
return true;
}
But I cant drag (+) 'a' array out to see those actual array elements... Which is what I was hoping to happen..
What I want is for the statement items[++top] = n; to work..
You can't assign an int value to an item, because you haven't told the compiler how to do that.
You need to either write a constructor or operator= for item that takes an int as a parameter or use
items[++top].n = n;
bool stack::pushFront( const int n )
{
if(top == maxSize-1)
return false;
items[++top].n = n; // where top is the top of the stack
return true; // only return true when the push is successful
}
It appears you have defined a stack of fixed size. You should check that adding to the stack does not exceed the size. To pushFront, you just need to copy the data in the array to make space for the 0th element to be modified:
bool stack::push(const int n)
{
if ( top >= capacity-1 ) return false;
items[++top].n = n
}
bool stack::pushFront(const int n)
{
if ( top >= capacity-1 ) return false;
bcopy( items, items+1, top+1 );
items[0].n = n;
return true;
}
Related
I'm learning Data Structures as required of me by my university. I've implemented the Queue DS using Dynamic Array but it somehow doesn't work. It updates the value on the first enqueue method call but from the second call onward, it does nothing.
MY CODE
#include <iostream>
#define MAXSIZE 8
class Queue
{
private:
int *arr;
int front;
int rear;
int itemsCount;
public:
Queue()
{
arr = new int[MAXSIZE];
front = -1;
rear = -1;
itemsCount = 0;
}
~Queue()
{
delete[] arr;
}
int dequeue()
{
int x = arr[front];
front = (front + 1) % MAXSIZE;
itemsCount--;
return x;
}
void enqueue(int x)
{
if (empty())
{
front++;
}
rear = (rear + 1) % MAXSIZE;
arr[rear] = x;
itemsCount++;
}
bool full() const
{
if (itemsCount == MAXSIZE)
return true;
return false;
}
bool empty() const
{
if (itemsCount == 0)
return true;
return false;
}
};
int main(int argc, char const *argv[])
{
Queue myQ;
myQ.enqueue(11);
myQ.enqueue(22); // This doesn't update the array at 1th index
myQ.enqueue(33);
myQ.enqueue(44);
myQ.enqueue(55);
myQ.enqueue(66);
myQ.enqueue(77);
myQ.enqueue(88);
std::cout << myQ.dequeue() << std::endl;
return 0;
}
P.S I know the implementation is incomplete and I haven't handled all the edge cases yet. That's because I couldn't get the normal case to work.
P.P.S It works with Static Array. But not with Dynamically allocated one.
Apparently, the array was being updated and the program was running as it should have when I performed the dequeue operations and displayed the values on screen. But the debugger somehow was only showing the value at the first index of the dynamically allocated array.
array pointer
Sequel to: array wrapper corrupts stack
The project:
I am working on a std::vector replacement.
The error:
I get a heap corruption error whenever I attempt to delete a temporary array I am creating in order to store the copied elements of another array that I delete in order to reallocate it when my array gets resized. (It seems that if I try to assign one array to another, I actually end up assigning the pointer to the array to the other array instead of copying the elements. Truly crazy stuff).
I read online that this error may actually come from the part where I actually interact with the array, but the error only pops out when I attempt to delete it.
Where I interact with the array is the function _tempcpy. I pass a pointer to a source and destination array and copy each element from the source to the destination. I struggled a bit with making sure that the array would start from 0 and not 1 and in the process I messed a bit too much with the element_count member, so it may be that i am somehow writing outside of bounds and I have stared so much at the code I can't see the issue.
The code:
template<class T> class dyn_arr
{
public:
dyn_arr(void)
{
this->array = {};
this->element_count = {};
}
~dyn_arr(void)
{
this->dealloc();
}
bool alloc(unsigned int element_count)
{
if (0 == element_count)
{
element_count = 1;
}
if (this->array != nullptr)
{
T* temp = new T[this->element_count];
if (false == this->_tempcpy(&this->array, &temp, this->element_count))
{
return false;
}
delete[] this->array;
this->array = new T[this->element_count];
if (false == this->_tempcpy(&temp, &this->array, this->element_count))
{
return false;
}
delete[] temp;
if (nullptr != this->array)
{
return true;
}
}
else
{
this->array = new T[this->element_count];
if (nullptr != this->array)
{
return true;
}
}
return false;
}
bool dealloc(void)
{
if (nullptr == this->array)
{
return false;
}
delete[] this->array;
return true;
}
bool add(T Object)
{
if (0 == Object)
{
return false;
}
if (true == this->alloc(this->element_count))
{
this->array[this->element_count] = Object;
++this->element_count;
return true;
}
return false;
}
T get(unsigned int index)
{
if (index > this->element_count)
{
return T{};
}
return this->array[index];
}
unsigned int get_count(void)
{
return this->element_count;
}
private:
bool _tempcpy(T** src, T** dest, unsigned int count)
{
if ((nullptr == src) || (nullptr == dest) || (0 == count))
{
return false;
}
for (unsigned int i = 0; i < count; ++i)
{
*dest[i] = *src[i];
}
return true;
}
T* array;
unsigned int element_count;
};
int main()
{
dyn_arr<int> pNr = {};
pNr.add(1);
pNr.add(2);
pNr.add(3);
for (int i = 0; i < pNr.get_count(); ++i)
{
printf("%d\n", pNr.get(i));
}
getchar();
return 0;
}
In your alloc function there lie a few problems, such as:
if (0 == element_count)
{
element_count = 1;
}
is unnecessary. Instead, you can just do a +1 where necessary which is almost everywhere except the temp dynamic array.
bool alloc(...)
{
this->array = new T[this->element_count];
//...
else
{
this->array = new T[this->element_count];
}
}
should be
this->array = new T[this->element_count + 1];
//...
else
{
this->array = new T[this->element_count + 1];
}
this will fix the problems with allocation. That leaves us with _tempcpy() which fails because instead of trying to get the next element of the underlying array, it tries to do that with the double ptr itself. Read about operator precedence rules. Fixed version:
bool _tempcpy(T** src, T** dest, unsigned int count)
{
//....
for (unsigned int i = 0; i < count; ++i)
{
(*dest)[i] = (*src)[i];
}
//....
}
However, I am unsure as to why double ptr is needed in this function in the first place. Just use single pointers. Also dest should be const as it is not changing in this function. It gives the reader of the function a clear idea of which parameters will change inside the function and which will not:
bool _tempcpy(T* src, const T* dest, unsigned int count) {...}
same could be applied to other parts of the class.
Additionally, in C++
dyn_arr(void)
We don't do this. There's no need to explicitly write void. According to the C++ standard:
8.3.5 Functions [dcl.fct]
...
A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list.
The code below a solution to the following requirement:
"Change the representation of Link and List from ยง27.9 without changing the user interface provided by the functions. Allocate Links in an array of Links and have the members: first, last, prev, and next be ints (indices into the array). " - Exercise 6 Chapter 27 - Programming: Principles and Practice Using C++ B. Stroustrup
The interface is inherited from an ordinary implementation of an Intrusive doubly linked list. I've added the bool array (and the associated functions) to keep track of memory:
#include <iostream>
struct Link
{
int next;
int prev;
};
//------------------------------------------------------------------------------------
struct List
{
Link** head;
int first; // points to the current first node
int last;
bool* available;
int list_size;
int get_index()
{
for (int i = 0; i < list_size; ++i)
{
if (available[i] == true)
{
available[i] = false;
return i;
}
}
throw std::bad_alloc("bla bla!\n");
}
List()
{
list_size = 30;
head = new Link*[list_size];
available = new bool[list_size];
first = -1;
last = -1;
for (int i = 0; i < list_size; ++i)
{
available[i] = true;
}
}
void List::push_back(Link* l)
{
if (l == nullptr)
{
throw std::invalid_argument("bla bla!\n");
}
int index = get_index();
head[index] = l;
if (last != -1)
{
head[last]->next = index;
head[index]->prev = last;
}
else
{
first = index;
head[index]->prev = -1;
}
last = index;
head[index]->next = -1;
}
void push_front(Link* l)
{
if (l == nullptr)
{
throw std::invalid_argument("bla bla\n");
}
int index = get_index();
head[index] = l;
if (first != -1)
{
head[first]->prev = index;
head[index]->next = first;
}
else
{
last = index;
head[index]->next = -1;
}
first = index;
head[index]->prev = -1;
}
// index = ptr - base
std::ptrdiff_t index_from_address(Link* l) { return l - head[0]; }
Link* front() const { return head[first]; }
};
//------------------------------------------------------------------------------------
int main()
{
List l;
for (int i = 0; i < 10; ++i)
{
l.push_back(new Link());
}
for (int i = 0; i < 10; ++i)
{
l.push_front(new Link());
}
std::cout <<"first = "<< l.first <<", index = " << l.index_from_address(l.front());
getchar();
}
Expected result:
first = 19, index = 19
Actual result:
first = 19, index = 194
Why?
l - head[0]
Here you compare the values of the two pointers. You let all pointers in the array be default initialized, so their values are indeterminate, and therefore the behaviour of accessing the values is undefined.
You probably intended index_from_address to find the index where a particular pointer object is stored - rather than the object that is pointed to, since the pointed to object is not in the array pointed by head. To do that, you must add a whole bunch of &:
Link*& front() const // return a reference to the pointer object, not a copy
// take a reference to the pointer as an argument, add const for good measure
std::ptrdiff_t index_from_address(Link*& l) const
// compare the addresses of the pointers, rather than values
{ return &l - &head[0]; }
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Using this simple example of a binary heap. How would i implement this data structure using c++ code.
1
/ \
3 6
/\ /\
5 9 8
Also apart from being able to gain easy access to the max or min values in an array, how is this data structure useful?
the example come from the following link: http://www.algolist.net/Data_structures/Binary_heap
Here is my simplest C++ implementation for heap. The code is well-commented.
/*
Usage:
heap Heap;
Heap.clear();
Heap.insert(value);
Heap.remove();
Heap.print();
*/
struct heap {
int myarray[NN+1]; // myarray to store the numbers as heap, 1 indexed
int n; // the number of nodes in my array
heap() { // constructor
clear(); // we clear the heap
}
void clear() { // initialize the heap
n = 0; // initially there are no nodes in the heap
}
void insert( int K ) { // inserting an element K in the heap
if( n == NN ) { // the heap is full
printf("cannot insert any more element, the heap is full\n");
return;
}
++n; // so, we have a new element, we increased n before adding
// the element because we start from index 1
myarray[n] = K; // inserted the element at the rightmost position
int p = n; // for keeping the current position
while( p > 1 ) { // p = 1 means we are on the root, and its a heap
int pr = p / 2; // pr is the parent of p
if( myarray[pr] > myarray[p] ) { // parent is greater than child
swap( myarray[pr], myarray[p] );
p = pr; // now the new position of the current element is pr
} else break; // otherwise its a heap, so we can stop here
}
}
int remove() { // removing the minimum element from the heap
if( n == 0 ) { // is the heap is empty
printf("The heap is empty, cannot delete.\n");
return -1;
}
int K = myarray[1]; // first element in the heap is the minimum
myarray[1] = myarray[n]; // brought the last element in 1st position
n--; // as we removed one element, now we need to maintain the heap
int p = 1; // as we moved the rightmost element in index 1
while( 2 * p <= n ) { // means p has at least one child, if 2*p > n
// we are sure that p is in the last level
int ch = 2 * p; // contains the index of the child
if( 2 * p + 1 <= n ) { // right child exists
if( myarray[ch] > myarray[ch+1] ) // right child is smaller
// than left child
ch++; // ch contains the index of the right child
}
if( myarray[p] > myarray[ch] ) { // so, current node is larger
// than its child
swap( myarray[p], myarray[ch] );
p = ch; // new position of the current element
} else break; //current node is smaller than its children, so heap
}
return K; // as we stored the minimum element in K
}
void print() { // printing the heap
printf("Number of elements: %d\n", n);
for( int i = 1; i <= n; i++ ) printf("%d ", myarray[i]);
printf("\n");
}
// Time: O(nlogn)
// Extra space: O(1) as we will pass the input array as res here
void heapSort(int* res) {
for(int i = 0, len = n; i < len; ++i) {
res[i] = remove();
}
}
};
I am writing below Java implementation it can help you to write code in c++;
import java.util.Arrays;
/**
* Min heap implementation, also caters to duplicate
*/
public class MinHeap {`
private int capacity = 10;
private int size;
int[] items;
public MinHeap() {
items = new int[capacity];
size = 0;
}
public void ensureExtraCapacity() {
if (size == capacity) {
items = Arrays.copyOf(items, capacity * 2);
capacity *= 2;
}
}
private int getLeftChildIndex(int index) {
return 2 * index + 1;
}
private int getRightChildIndex(int index) {
return 2 * index + 2;
}
private int getParentIndex(int index) {
return (index - 1) / 2;
}
private boolean hasLeftChild(int index) {
return size > getLeftChildIndex(index);
}
private boolean hasRightChild(int index) {
return size > getRightChildIndex(index);
}
private boolean hasParent(int index) {
if(index == 0)
return false;
return getParentIndex(index) >= 0;
}
private int leftChild(int index) {
return items[getLeftChildIndex(index)];
}
private int rightChild(int index) {
return items[getRightChildIndex(index)];
}
private int parent(int index) {
return items[getParentIndex(index)];
}
private void swapValues(int index1, int index2) {
int temp = items[index1];
items[index1] = items[index2];
items[index2] = temp;
}
public int peek() {
if (size == 0) throw new IllegalStateException();
return items[0];
}
public int poll() {
if (size == 0) throw new IllegalStateException();
int polled = items[0];
items[0] = items[size - 1];
size--;
heapifyDown();
return polled;
}
public void add(int item) {
ensureExtraCapacity();
items[size] = item;
size++;
heapifyUp();
}
private void heapifyUp() {
int index = size - 1;
while (hasParent(index) && parent(index) > items[index]) {
swapValues(index, getParentIndex(index));
index = getParentIndex(index);
}
}
private void heapifyDown() {
int index = 0;
while (hasLeftChild(index)) {
int minimumChildIndex = getLeftChildIndex(index);
if (hasRightChild(index) && rightChild(index) < leftChild(index))
minimumChildIndex = getRightChildIndex(index);
if (items[index] < items[minimumChildIndex]) {
break;
} else {
swapValues(index, minimumChildIndex);
}
index = minimumChildIndex;
}
}
/* public void printMinHeap() {
while (size > 0) {
int poll = poll();
System.out.println(poll);
}
}*/
/* public static void main(String[] args) {
MinHeap minHeap = new MinHeap();
minHeap.add(7);
minHeap.add(3);
minHeap.add(4);
minHeap.add(10);
minHeap.add(1);
minHeap.add(15);
minHeap.add(2);
minHeap.add(17);
minHeap.add(1);
minHeap.printMinHeap();
}*/
}
Alright, so without going into detail on why I'm writing this class, here it is.
template<class aType>
class nArray
{
public:
aType& operator[](int i)
{
return Array[i];
}
nArray()
{
aType * Array = new aType[0];
_Size = 0;
_MaxSize = 0;
_Count = 0;
}
nArray(int Count)
{
aType * Array = new aType[Count*2]();
_Size = Count;
_MaxSize = Count * 2;
_Count = 0;
}
int Resize(int newSize)
{
aType *temp = new aType[newSize*2];
for(int i=0;i<_Count;i++)
{
temp[i] = Array[i];
}
delete[] Array;
aType * Array = new aType[newSize*2];
for(int i=0;i<_Count;i++)
{
Array[i] = temp[i];
}
delete [] temp;
_Size = newSize;
_MaxSize = newSize*2;
return 0;
}
int Push_Back(aType Item)
{
if(_Count+1 >= _Size)
{
Resize(_MaxSize);
}
Array[_Count] = Item;
_Count++;
return _Count - 1;
}
aType GetAt(int Index, int &ret)
{
if(Index > _Size-1)
ret = 1;
return aType();
ret = 0;
return Array[Index];
}
private:
int _Size;
int _Count;
int _MaxSize;
aType * Array;
};
It is supposed to be a std::Vector type object, without all the bells and whistles.
Problem is, it doesn't seem to work.
I basically start by going
nArray<string> ca = nArray<string>(5);
ca.Push_Back("asdf");
ca.Push_Back("asdf2");
int intret = 0;
cout << ca.GetAt(1,intret);
I get an Access Violation Reading Location error and it hits on the line
Array[_Count] = Item
in the Push_back function.
The problem seems to be that it's not treating the Array object as an array in memory.
I've spent time going through the code step by step, and I don't know what else to say, it's not operating right. I don't know how to word it right. I'm just hoping someone will read my code and point out a stupid mistake I've made, because I'm sure that's all it amounts to.
Update
So now I changed 3 initializations of Array in nArray(), nArray(int Count), and Resize(int newSize)
template<class aType>
class nArray
{
public:
aType& operator[](int i)
{
return Array[i];
}
nArray()
{
Array = new aType[0];
_Size = 0;
_MaxSize = 0;
_Count = 0;
}
nArray(int Count)
{
Array = new aType[Count*2]();
_Size = Count;
_MaxSize = Count * 2;
_Count = 0;
}
int Resize(int newSize)
{
aType *temp = new aType[newSize*2];
for(int i=0;i<_Count;i++)
{
temp[i] = Array[i];
}
delete[] Array;
Array = new aType[newSize*2];
for(int i=0;i<_Count;i++)
{
Array[i] = temp[i];
}
delete [] temp;
_Size = newSize;
_MaxSize = newSize*2;
return 0;
}
int Push_Back(aType Item)
{
if(_Count+1 >= _Size)
{
Resize(_MaxSize);
}
Array[_Count] = Item;
_Count++;
return _Count - 1;
}
aType GetAt(int Index, int &ret)
{
if(Index > _Size-1)
ret = 1;
return aType();
ret = 0;
return Array[Index];
}
private:
int _Size;
int _Count;
int _MaxSize;
aType * Array;
};
This is how my code was before. Anyway, the original problem was the fact that when I try to access a specific element in the array, it just accesses the first element, and it doesn't seem to add elements eather. It doesn't seem to be treating Array as an array.
int Resize(int newSize)
{
.
.
aType * Array = new aType[newSize*2];
At this point, instead of updating the member variable as you intended, you've actually created a local variable called Array whose value is discarded when you exit from Resize(). Change the line to
Array = new aType[newSize*2];
The same thing is happening in your constructors, they also need changing accordingly. Moreover, since the default constructor allocates an array, you should set the size members accordingly. You have too many of these: an array needs to keep track of current element count and maximum capacity, however you appear to have three members. What is the purpose of the third? Redundant information is bad, it makes code difficult to read and without a single point of truth it is easier to make mistakes.
With the code in Resize(), you can do better: the second copy is completely redundant.
int Resize(int newSize)
{
aType *temp = new aType[newSize*2];
for(int i=0;i<_Count;i++)
{
temp[i] = Array[i];
}
delete[] Array;
Array = temp;
_Size = newSize;
_MaxSize = newSize*2;
return 0;
}
Also, in
aType GetAt(int Index, int &ret)
{
if(Index > _Size-1)
ret = 1;
return aType();
ret = 0;
return Array[Index];
}
you need curly braces around body of the if(), just indentation on its own won't do the trick:
aType GetAt(int Index, int &ret)
{
if(Index > _Size-1)
{
ret = 1;
return aType();
}
ret = 0;
return Array[Index];
}
You have a number of problems. At a guess, the one causing problems so far is that your default ctor (nArray::nArray()) defines a local variable named Array that it initializes, which leaves nArray::Array uninitialized.
Though you probably haven't seen any symptoms from it (yet), you do have at least one more problem. Names starting with an underscore followed by a capital letter (such as your _Size, _MaxSize, and _Count) are reserved for the implementation -- i.e., you're not allowed to use them.
The logic in your Resize also looks needlessly inefficient (if not outright broken), though given the time maybe it's just my brain not working quite right at this hour of the morning.
Your array is not initialized by the constructors and resize function (working on local vars instead).
And is there a reason you want to store instances of string and not pointers to string (string *) ?
I think the answer after the changes is in moonshadow's reply:
aType GetAt(int Index, int &ret)
{
if(Index > _Size-1)
ret = 1;
return aType();
ret = 0;
return Array[Index];
}
This code will always return aType(), the last two lines will never be reached.
You might also want to check what happens if you start out with a default-constructed nArray. (Hint: you call Resize(_MaxSize); but what is the value of _MaxSize in this case?
Edit:
This outputs "asdf2" for me as it should be (with the initialization and the braces fixed):
template<class aType>
class nArray
{
public:
aType& operator[](int i)
{
return Array[i];
}
nArray()
{
Array = new aType[0];
_Size = 0;
_MaxSize = 0;
_Count = 0;
}
nArray(int Count)
{
Array = new aType[Count*2]();
_Size = Count;
_MaxSize = Count * 2;
_Count = 0;
}
int Resize(int newSize)
{
aType *temp = new aType[newSize*2];
for(int i=0;i<_Count;i++)
{
temp[i] = Array[i];
}
delete[] Array;
Array = new aType[newSize*2];
for(int i=0;i<_Count;i++)
{
Array[i] = temp[i];
}
delete [] temp;
_Size = newSize;
_MaxSize = newSize*2;
return 0;
}
int Push_Back(aType Item)
{
if(_Count+1 >= _Size)
{
Resize(_MaxSize);
}
Array[_Count] = Item;
_Count++;
return _Count - 1;
}
aType GetAt(int Index, int &ret)
{
if(Index > _Size-1) {
ret = 1;
return aType();
}
ret = 0;
return Array[Index];
}
private:
int _Size;
int _Count;
int _MaxSize;
aType * Array;
};
#include <string>
#include <iostream>
using namespace std;
int main()
{
nArray<string> ca = nArray<string>(5);
ca.Push_Back("asdf");
ca.Push_Back("asdf2");
int intret = 0;
cout << ca.GetAt(1,intret);
}