C++ inserting (and shifting) data into an array - c++

I am trying to insert data into a leaf node (an array) of a B-Tree. Here is the code I have so far:
void LeafNode::insertCorrectPosLeaf(int num)
{
for (int pos=count; pos>=0; pos--) // goes through values in leaf node
{
if (num < values[pos-1]) // if inserting num < previous value in leaf node
{continue;} // conitnue searching for correct place
else // if inserting num >= previous value in leaf node
{
values[pos] = num; // inserts in position
break;
}
}
count++;
} // insertCorrectPos()
Before the line values[pos] = num, I think need to write some code that shifts the existing data instead of overwriting it. I am trying to use memmove but have a question about it. Its third parameter is the number of bytes to copy. If I am moving a single int on a 64 bit machine, does this mean I would put a "4" here? If I am going about this completely wrong any any help would be greatly appreciated. Thanks

The easiest way (and probably the most efficient) would be to use one of the standard libraries predefined structures to implement "values". I suggest either list or vector. This is because both list and vector has an insert function that does it for you. I suggest the vector class specifically is because it has the same kind of interface that an array has. However, if you want to optimize for speed of this action specifically, then I would suggest the list class because of the way it is implemented.
If you would rather to it the hard way, then here goes...
First, you need to make sure that you have the space to work in. You can either allocate dynamically:
int *values = new int[size];
or statically
int values[MAX_SIZE];
If you allocate statically, then you need to make sure that MAX_SIZE is some gigantic value that you will never ever exceed. Furthermore, you need to check the actual size of the array against the amount of allocated space every time you add an element.
if (size < MAX_SIZE-1)
{
// add an element
size++;
}
If you allocate dynamically, then you need to reallocate the whole array every time you add an element.
int *temp = new int[size+1];
for (int i = 0; i < size; i++)
temp[i] = values[i];
delete [] values;
values = temp;
temp = NULL;
// add the element
size++;
When you insert a new value, you need to shift every value over.
int temp = 0;
for (i = 0; i < size+1; i++)
{
if (values[i] > num || i == size)
{
temp = values[i];
values[i] = num;
num = temp;
}
}
Keep in mind that this is not at all optimized. A truly magical implementation would combine the two allocation strategies by dynamically allocating more space than you need, then growing the array by blocks when you run out of space. This is exactly what the vector implementation does.
The list implementation uses a linked list which has O(1) time for inserting a value because of it's structure. However, it is much less space inefficient and has O(n) time for accessing an element at location n.
Also, this code was written on the fly... be careful when using it. There might be a weird edge case that I am missing in the last code segment.
Cheers!
Ned

Related

while every value in array is different than specific int value

I have an array of values e.g. 1, 4, 7, 2.
I also have another array of values and I want to add its values to this first array, but only when they all are different from all values that are already in this array. How can I check it? I've tried many types of loops, but I always ended with an iteration problem.
Could you please tell me how to solve this problem? I code in c++.
int array1[7] = {2,3,7,1,0};
int val1 = rand() % 10;
int val2 = rand() % 10;
int array2[2] = {val1, val2};
and I am trying to put every value from array2 into array1. I tried loop
for (int x:array2)
{
while((val1 && val2) == x)
{
val1 = rand() % 10;
val2 = rand() % 10;
}
}
and many more, but still cannot figure it out. I have this problem because I may have various number of elements for array2. So it makes this "&&" solution infinite.
It is just a sample to show it more clearly, my code has much more lines.
Okay, you have a few problems here. If I understand the problem, here's what you want:
A. You have array1 already populated with several values but with space at the end.
1. How do you identify the number of entries in the array already versus the extras?
B. You have a second array you made from two random values. No problem.
You want to append the values from B to A.
2. If initial length of A plus initial length of B is greater than total space allocated for A, you have a new problem.
Now, other people will tell you to use the standard template library, but if you're having problems at this level, you should know how to do this yourself without the extra help from a confusing library. So this is one solution.
class MyArray {
public:
int * data;
int count;
int allocated;
MyArray() : data(nullptr), count(0), allocated(0) {}
~MyArray() { if (data != nullptr) free(data); }
// Appends value to the list, making more space if necessary
void add(int value) {
if (count >= allocated) {
// Not enough space, so make some.
allocated += 10;
data = (data == nullptr) malloc(allocated * sizeof(int))
: realloc)data, allocated * sizeof(int));
}
data[count++] = value;
}
// Adds value only if not already present.
void addUnique(int value) {
if (indexOf(value) < 0) {
add(value);
}
}
// Returns the index of the value, if found, else -1
int indexOf(int value) {
for (int index = 0; index < count; ++index) {
if (data[index] == value) {
return index;
}
}
return -1;
}
}
This class provides you a dynamic array of integers. It's REALLY basic, but it teaches you the basics. It helps you understand about allocation / reallocating space using old-style C-style malloc/realloc/free. It's the sort of code I was writing back in the 80s.
Now, your main code:
MyArray array;
array.add(2);
array.add(3);
array.add(7);
// etc. Yes, you could write a better initializer, but this is easy to understand
MyArray newValues;
newValues.add(rand() % 10);
newValues.add(rand() % 10);
for (int index = 0; index < newValues.count; ++index) {
array.addUnique(newValues.data[index]);
}
Done.
The key part of this is the addUnique function, which simply checks first whether the value you're adding already is in the array. If not, it appends the value to the array and keeps track of the new count.
Ultimately, when using integer arrays like this instead of the fancier classes available in C++, you HAVE TO keep track of the size of the array yourself. There is no magic .length method on int[]. You can use some magic value that indicates the end of the list, if you want. Or you can do what I did and keep two values, one that holds the current length and one that holds the amount of space you've allocated.
With programming, there are always multiple ways to do this.
Now, this is a lot of code. Using standard libraries, you can reduce all of this to about 4 or 5 lines of code. But you're not ready for that, and you need to understand what's going on under the hood. Don't use the fancy libraries until you can do it manually. That's my belief.

Deleting an element from an array of objects

I tried to write a function that gets an object ("Stone") and deletes the stone from a given array. code:
void Pile::del_stone(Stone &s)
{
Stone *temp = new Stone[size - 1];//allocate new array
for (int i = 0;i <size;++i)
{
if (s != Pile_arr[i])//if the given object to delete is different from the current
{
temp[i] = Pile_arr[i];//copy to the new array
}
else
{
i--;
}
}
Pile_arr = temp;
set_size(this->size - 1);
temp = NULL;
delete[] temp;
}
Pile_arr is a member of Pile class.
The problem is that i get an infinite loop, because i decrease i. I cant figure out how to solve this issue. Any ideas?
Use two indexes: i and j. Use i to know which element of the original array you are looking and j to know where to put the element in temp.
You need to use a separate counter to track where new elements should be placed.
I have used n below:
Stone *temp = new Stone[size - 1];
int n = 0; // Stores the current size of temp array
for (int i = 0;i <size;++i) {
if (s != Pile_arr[i]) {
temp[n++] = Pile_arr[i];
}
}
It's also worth considering the case where s is not found in the array, as this would cause a runtime error (Attempting to add size elements to an array of size size - 1).
Using a STL container would be a far better option here.
This function will:
Allocate a new array of length size-1
Search for the intended object
If you find it, copy it to the same exact position in the array
If you don't --i
Finally, ++i
First of all, this function is bad for 3 reasons:
It only copies one item over--the given item. You have an array with only 1 object.
It copies the item from index to index. Since the final array is one smaller, if the object is at the max original index, it will be out of bounds for the new array.
If the object is not immediately found, the array will get stuck, as you decrease the index, and then increase it using the loop--you'll never move again.
Stone *temp = new Stone[size - 1];//allocate new array
for (int i = 0;i
Instead:
Cache the found object, then delete it from the original array or mark it. temp = found object
Copy the array, one by one, without copying empty spaces and closing the gap. Copy temp_array[i] and increment i if and only if temp_array[j] is not marked/deleted. Increment j
Decide where to put the found object.
Once again, you can decide to use separate indexes--one for parsing the original array, and one for filling the new array.

Copy elements of an old array of pointers into new array of pointers?

I need some assistance with a C++ project. What I have to do is remove the given element from an array of pointers. The technique taught to me is to create a new array with one less element and copy everything from the old array into the new one except for the specified element. After that I have to point the old array towards the new one.
Here's some code of what I have already:
I'm working with custom structs by the way...
Data **values = null; // values is initialized in my insert function so it is
// populated
int count; // this keeps track of values' length
bool remove(Data * x) {
Data **newArray = new Data *[count - 1];
for (int i = 0; i < count; i++) {
while (x != values[i]) {
newArray[i] = values[i];
}
count -= 1;
return true;
}
values = newArray;
return false;
}
So far the insert function works and outputs the populated array, but when I run remove all it does is make the array smaller, but doesn't remove the desired element. I'm using the 0th element every time as a control.
This is the output I've been getting:
count=3 values=[5,6,7] // initial insertion of 5, 6, 7
five is a member of collection? 0
count=3 values=[5,6] // removal of 0th element aka 5, but doesn't work
five is a member of collection? 0
count=4 values=[5,6,5] // re-insertion of 0th element (which is stored in
five is a member of collection? 0 // my v0 variable)
Could anyone nudge me in the right direction towards completing this?
First of all, your code is leaking memory like no good! Next you only copy the first element and not even that if the first element happens to be the one you want to remove. Also, when you return from your function, you haven't changed your internal state at all. You definitely want to do something along the lines of
Data** it = std::find(values, values + count, x);
if (it != values + count) {
std::copy(it + 1, values + count, it);
--count;
return true;
}
return false;
That said, if anybody taught you to implement something like std::vector<T> involving reallocations on every operation, it is time to change schools! Memory allocations are relatively expensive and you want to avoid them. That is, when implementing something like a std::vector<T> you, indeed, want to implement it like a std::vector<T>! That is you keep an internal buffer of potentially more element than there are and remember how many elements you are using. When inserting a new element, you only allocate a new array if there is no space in the current array (not doing so would easily result in quadratic complexity even when always adding elements at the end). When removing an element, you just move all the trailing objects one up and remember that there is one less object in the array.
Try this:
bool remove(Data * x)
{
bool found = false;
// See if x is in the array.
for (int i = 0; i < count; i++) {
if (x != values[i]) {
found = true;
break;
}
}
if (!found)
{
return false;
}
// Only need to create the array if the item to be removed is present
Data **newArray = new Data *[count - 1];
// Copy the content to the new array
int newIndex = 0;
for (int i = 0; i < count; i++)
{
if (x != values[i])
newArray[newIndex++] = values[i];
}
// Now change the pointers.
delete[] values;
count--;
values = newArray;
return true;
}
Note that there's an underlying assumption that if x is present in the array then it's there only once! The code will not work for multiple occurrences, that's left to you, seeing as how this is a school exercise.

priority queue with limited space: looking for a good algorithm

This is not a homework.
I'm using a small "priority queue" (implemented as array at the moment) for storing last N items with smallest value. This is a bit slow - O(N) item insertion time. Current implementation keeps track of largest item in array and discards any items that wouldn't fit into array, but I still would like to reduce number of operations further.
looking for a priority queue algorithm that matches following requirements:
queue can be implemented as array, which has fixed size and _cannot_ grow. Dynamic memory allocation during any queue operation is strictly forbidden.
Anything that doesn't fit into array is discarded, but queue keeps all smallest elements ever encountered.
O(log(N)) insertion time (i.e. adding element into queue should take up to O(log(N))).
(optional) O(1) access for *largest* item in queue (queue stores *smallest* items, so the largest item will be discarded first and I'll need them to reduce number of operations)
Easy to implement/understand. Ideally - something similar to binary search - once you understand it, you remember it forever.
Elements need not to be sorted in any way. I just need to keep N smallest value ever encountered. When I'll need them, I'll access all of them at once. So technically it doesn't have to be a queue, I just need N last smallest values to be stored.
I initially thought about using binary heaps (they can be easily implemented via arrays), but apparently they don't behave well when array can't grow anymore. Linked lists and arrays will require extra time for moving things around. stl priority queue grows and uses dynamic allocation (I may be wrong about it, though).
So, any other ideas?
--EDIT--
I'm not interested in STL implementation. STL implementation (suggested by a few people) works a bit slower than currently used linear array due to high number of function calls.
I'm interested in priority queue algorithms, not implemnetations.
Array based heaps seem ideal for your purpose. I am not sure why you rejected them.
You use a max-heap.
Say you have an N element heap (implemented as an array) which contains the N smallest elements seen so far.
When an element comes in you check against the max (O(1) time), and reject if it is greater.
If the value coming in is lower, you modify the root to be the new value and sift-down this changed value - worst case O(log N) time.
The sift-down process is simple: Starting at root, at each step you exchange this value with it's larger child until the max-heap property is restored.
So, you will not have to do any deletes which you probably will have to, if you use std::priority_queue. Depending on the implementation of std::priority_queue, this could cause memory allocation/deallocation.
So you can have the code as follows:
Allocated Array of size N.
Fill it up with the first N elements you see.
heapify (you should find this in standard text books, it uses sift-down). This is O(N).
Now any new element you get, you either reject it in O(1) time or insert by sifting-down in worst case O(logN) time.
On an average, though, you probably will not have to sift-down the new value all the way down and might get better than O(logn) average insert time (though I haven't tried proving it).
You only allocate size N array once and any insertion is done by exchanging elements of the array, so there is no dynamic memory allocation after that.
Check out the wiki page which has pseudo code for heapify and sift-down: http://en.wikipedia.org/wiki/Heapsort
Use std::priority_queue with the largest item at the head. For each new item, discard it if it is >= the head item, otherwise pop the head item and insert the new item.
Side note: Standard containers will only grow if you make them grow. As long as you remove one item before inserting a new item (after it reaches its maximum size, of course), this won't happen.
Most priority queues I work are based on linked lists. If you have a pre-determined number of priority levels, you can easily create a priority queue with O(1) insertion by having an array of linked lists--one linked list per priority level. Items of the same priority will of course degenerate into either a FIFO, but that can be considered acceptable.
Adding and removal then becomes something like (your API may vary) ...
listItemAdd (&list[priLevel], &item); /* Add to tail */
pItem = listItemRemove (&list[priLevel]); /* Remove from head */
Getting the first item in the queue then becomes a problem of finding the non-empty linked-list with the highest priority. That may be O(N), but there are several tricks you can use to speed it up.
In your priority queue structure, keep a pointer or index or something to the linked list with the current highest priority. This would need to be updated each time an item is added or removed from the priority queue.
Use a bitmap to indicate which linked lists are not empty. Combined with a find most significant bit, or find least significant bit algorithm you can usually test up to 32 lists at once. Again, this would need to be updated on each add / remove.
Hope this helps.
If amount of priorities is small and fixed than you can use ring-buffer for each priority. That will lead to waste of the space if objects is big, but if their size is comparable with pointer/index than variants with storing additional pointers in objects may increase size of array in the same way.
Or you can use simple single-linked list inside array and store 2*M+1 pointers/indexes, one will point to first free node and other pairs will point to head and tail of each priority. In that cases you'll have to compare in avg. O(M) before taking out next node with O(1). And insertion will take O(1).
If you construct an STL priority queue at the maximum size (perhaps from a vector initialized with placeholders), and then check the size before inserting (removing an item if necessary beforehand) you'll never have dynamic allocation during insert operations. The STL implementation is quite efficient.
Matters Computational see page 158. The implementation itself is quite well, and you can even tweak it a little without making it less readable. For example, when you compute the left child like:
int left = i / 2;
You can compute the rightchild like so:
int right = left + 1;
Found a solution ("difference" means "priority" in the code, and maxRememberedResults is 255 (could be any (2^n - 1)):
template <typename T> inline void swap(T& a, T& b){
T c = a;
a = b;
b = c;
}
struct MinDifferenceArray{
enum{maxSize = maxRememberedResults};
int size;
DifferenceData data[maxSize];
void add(const DifferenceData& val){
if (size >= maxSize){
if(data[0].difference <= val.difference)
return;
data[0] = val;
for (int i = 0; (2*i+1) < maxSize; ){
int next = 2*i + 1;
if (data[next].difference < data[next+1].difference)
next++;
if (data[i].difference < data[next].difference)
swap(data[i], data[next]);
else
break;
i = next;
}
}
else{
data[size++] = val;
for (int i = size - 1; i > 0;){
int parent = (i-1)/2;
if (data[parent].difference < data[i].difference){
swap(data[parent], data[i]);
i = parent;
}
else
break;
}
}
}
void clear(){
size = 0;
}
MinDifferenceArray()
:size(0){
}
};
build max-based queue (root is largest)
until it is full, fill up normally
when it is full, for every new element
Check if new element is smaller than root.
if it is larger or equal than root, reject.
otherwise, replace root with new element and perform normal heap "sift-down".
And we get O(log(N)) insert as a worst case scenario.
It is the same solution as the one provided by user with nickname "Moron".
Thanks to everyone for replies.
P.S. Apparently programming without sleeping enough wasn't a good idea.
It's better to implement your own class using std::array and heap algorithms.
`template<class T, int fixed_size = 5>
class fixed_size_arr_pqueue_v2
{
std::array<T, fixed_size> _data;
int _size = 0;
int parent(int i)
{
return (i - 1)/2;
}
void heapify(int i, bool downward = false)
{
int l = 2*i + 1;
int r = 2*i + 2;
int largest = 0;
if (l < size() && _data[l] > _data[i])
largest = l;
else
largest = i;
if (r < size() && _data[r] > _data[largest])
largest = r;
if (largest != i)
{
std::swap(_data[largest], _data[i]);
if (!downward)
heapify(parent(i));
else
heapify(largest, true);
}
}
public:
void push(T &d)
{
if (_size == fixed_size)
{
//min elements in a max heap lies at leaves only.
auto minItr = std::min_element(begin(_data) + _size/2, end(_data));
auto minPos {minItr - _data.begin()};
auto min { *minItr};
if (d > min)
{
_data.at(minPos) = d;
if (_data[parent(minPos)] > d)
{
//this is unlikely to happen in our case? as this position is a leaf?
heapify(minPos, true);
}
else
heapify(parent(minPos));
}
return ;
}
_data.at(_size++) = d;
std::push_heap(_data.begin(), _data.begin() + _size);
}
T pop()
{
T d = _data.front();
std::pop_heap(_data.begin(), _data.begin() + _size);
_size--;
return d;
}
T top()
{
return _data.front();
}
int size() const
{
return _size;
}
};`

PushFront method for an array C++

I thought i'd post a little of my homework assignment. Im so lost in it. I just have to be really efficient. Without using any stls, boosts and the like. By this post, I was hoping that someone could help me figure it out.
bool stack::pushFront(const int nPushFront)
{
if ( count == maxSize ) // indicates a full array
{
return false;
}
else if ( count <= 0 )
{
count++;
items[top+1].n = nPushFront;
return true;
}
++count;
for ( int i = 0; i < count - 1; i++ )
{
intBackPtr = intFrontPtr;
intBackPtr++;
*intBackPtr = *intFrontPtr;
}
items[top+1].n = nPushFront;
return true;
}
I just cannot figure out for the life of me to do this correctly! I hope im doing this right, what with the pointers and all
int *intFrontPtr = &items[0].n;
int *intBackPtr = &items[capacity-1].n;
Im trying to think of this pushFront method like shifting an array to the right by 'n' units...I can only seem to do that in an array that is full. Can someone out their please help me?
Firstly, I'm not sure why you have the line else if ( count <= 0 ) - the count of items in your stack should never be below 0.
Usually, you would implement a stack not by pushing to the front, but pushing and popping from the back. So rather than moving everything along, as it looks like you're doing, just store a pointer to where the last element is, and insert just after that, and pop from there. When you push, just increment that pointer, and when you pop, decrement it (you don't even have to delete it). If that pointer is at the end of your array, you're full (so you don't even have to store a count value). And if it's at the start, then it's empty.
Edit
If you're after a queue, look into Circular Queues. That's typically how you'd implement one in an array. Alternatively, rather than using an array, try a Linked List - that lets it be arbitrarily big (the only limit is your computer's memory).
You don't need any pointers to shift an array. Just use simple for statement:
int *a; // Your array
int count; // Elements count in array
int length; // Length of array (maxSize)
bool pushFront(const int nPushFront)
{
if (count == length) return false;
for (int i = count - 1; i >= 0; --i)
Swap(a[i], a[i + 1]);
a[0] = nPushFront; ++count;
return true;
}
Without doing your homework for you let me see if I can give you some hints. Implementing a deque (double ended queue) is really quite easy if you can get your head around a few concepts.
Firstly, it is key to note that since we will be popping off the front and/or back in order to efficiently code an algorithm which uses contiguous storage we need to be able to pop front/back without shifting the entire array (what you currently do). A much better and in my mind simpler way is to track the front AND the back of the relevant data within your deque.
As a simple example of the above concept consider a static (cannot grow) deque of size 10:
class Deque
{
public:
Deque()
: front(0)
, count(0) {}
private:
size_t front;
size_t count;
enum {
MAXSIZE = 10
};
int data[MAXSIZE];
};
You can of course implement this and allow it to grow in size etc. But for simplicity I'm leaving all that out. Now to allow a user to add to the deque:
void Deque::push_back(int value)
{
if(count>=MAXSIZE)
throw std::runtime_error("Deque full!");
data[(front+count)%MAXSIZE] = value;
count++;
}
And to pop off the back:
int Deque::pop_back()
{
if(count==0)
throw std::runtime_error("Deque empty! Cannot pop!");
int value = data[(front+(--count))%MAXSIZE];
return value;
}
Now the key thing to observe in the above functions is how we are accessing the data within the array. By modding with MAXSIZE we ensure that we are not accessing out of bounds, and that we are hitting the right value. Also as the value of front changes (due to push_front, pop_front) the modulus operator ensures that wrap around is dealt with appropriately. I'll show you how to do push_front, you can figure out pop_front for yourself:
void Deque::push_front(int value)
{
if(count>=MAXSIZE)
throw std::runtime_error("Deque full!");
// Determine where front should now be.
if (front==0)
front = MAXSIZE-1;
else
--front;
data[front] = value;
++count;
}