I have this function in my custom dynamic array class that allows the user to insert another array into this one. It works, but I'm like 99% sure that this is not the fastest solution, and I'm wondering if it is possible to combine the two for loops to increase peformance? If so, how? I'm kinda stuck.
thanks in advance.
void insertrange(T item[], int sizerange, int index)
{
int k = this->size;
int j = 0;
if(this->size + sizerange >= this->capacity) //if the size + added size are bigger than the capacity
{
this->enlarge(this->capacity + sizerange); //enlarge the array
}
for(k; k >= index; k--) //for every element from the end to the index where to add the new array
{
this->array[k + sizerange] = a[k]; //replace the element to his new spot
}
for(j; j < sizerange; j++) //vor every element in the new array
{
this->array[index + j] = item[j]; //place it in the new spot
}
size += sizerange;
}
I think the key is that you don't have to copy the empty cells.
void insertrange(T item[], int sizerange, int index)
{
// This actually points past the end of the current array, right?
int onePastLastEntry = this->size;
// Still need to make sure the new array is large enough
if(this->size + sizerange >= this->capacity) //if the size + added size are bigger than the capacity
{
this->enlarge(this->capacity + sizerange); //enlarge the array
}
// you should be able to go forward instead of backwards
for(i = index; i < onePastLastEntry ; i++)
{
// move the current element
this->array[i + sizerange] = a[i];
// then copy the new value
this->array[i] = item[i - index];
}
You could actually do the loop from zero, going to onePastLastEntry - index as well, but that makes the math weird:
// you should be able to go forward instead of backwards
for(i = 0; i < onePastLastEntry - index; i++)
{
// now you have to add the index in two places here
this->array[i + index + sizerange] = a[i + index];
// and add the index in the copy as well
this->array[i + index] = item[i];
}
The only possible performance benefit I see is doing less dynamic allocation every time the array gets larger. It is better in most cases to multiply the capacity by 2 every time you need to reallocate.
You have one extra copy in your k for loop. The k index should start at size-1, not size, so you are copying one extra element beyond the end of your array. However, this will provide negligible speedup. If serious performance improvement is needed, you should look into optimizing the enlarge function or use a different data structure than an array.
You can move the elements, instead of copying them:
for(k; k >= index; k--)
{
this->array[k + sizerange] = std::move(a[k]);
}
Another possible improvement, especially for classes that have an expensive default constructor, is to construct T in place, using the move constructor. When you allocate, instead of allocating with new T[], which default constructs every element, allocate raw bytes with new char[] or malloc. Then you can use placement new to move construct the object on the spot.
Related
User has to make an array from any amount of numbers and I need to rearrange the array, so that the elements from EVEN places would move to the start of an array and from UNEVEN places to the end. For example A=[1,2,3,4,5,6] would turn into B=[2,4,6,1,3,5]. Also I need to use POINTERS.... I am very bad at pointers, so help would be very much appreciated.
This is as far as I got myself. I am not using pointers here though, because I don't know how to.. :(
void switcharoo(int a, int b[]){
int temp[a], j=0;
for(int i=1;i<a;i+=2){
temp[j] = b[i];
j++;
}
for(int i=0;i<a;i+=2){
temp[j] = b[i];
j++;
}
b = temp;
}
Oups, you have still to improve your C++ knowledge...
int temp[a] is not valid C++ as you have been told in comment - Variable Length Arrays are a C feature
b is passed as a pointer (an arrays decays to a pointer to its first element when passed to a function). When you write b=temp; at the end of you function, you only change a local copy... which immediately goes out of scope: in short the current code is just a no-op.
array indices start at 0
If you want to train in using pointers, you could do something like that:
void switcharoo(int a, int b[]) {
int *even = new int[a]; // allocate an array of same size
int *odd = even + a / 2; // point at the mid array element
for (int i = 0; i<a - 1; i += 2) {
*odd++ = b[i]; // odd elements in high part
*even++ = b[i + 1]; // even in low part
}
if (0 != a % 2) { // one odd element remains
*odd++ = b[a - 1];
}
even = odd - a; // make even point again to start of allocated array
odd = even; // store a copy
for (int i = 0; i<a; i++) { // copy back in original array
b[i] = *even++;
}
delete[] odd; // and delete the allocated array
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I would like to change the size of array when it exceed its limit. I have created a function for that.
void AddElemenet( int i , int value){
if( i > index - 1){
int tmp = index;
double *new_arr;
while( i > tmp){
tmp*=2
}
new_arr = new double[tmp]();
for( int j = 0; j < index ; j++){
new_arr[j] = arr[j];
}
index = tmp;
delete[] arr;
arr = new_arr;
}
arr[i] = value;
}
index refers to the max size of an array ; and arr is dynamicly allocated array using new itself.
The problem is , that i am assigning arr to a local variable that get destroyed. I tried assignign it as refference or pointer using *arr=*new_arr
but nothing worked so far. How can i change the array using this local variable?
The various bugs in your implementation demonstrate why it is almost always a good idea to use the standard library. It would be very simple to adapt std::vector to this interface.
The essence of your problem is the confusion over what index means. (That's a terrible name for a member variable. It says nothing. Index of what? And actually, it's not an index; it's the size of the array. At least, that's what it should be.)
Suppose that your array has 4 elements, so index is 4 (based on the assumption that it is the size of the array). Now you want to AddElement(4, 42);. The condition in if( i > index - 1) is certainly true: i is 4, and index - 1 is 3. So the reallocation block will be entered. However, the first thing you do is tmp = index; while( i > tmp) tmp *= 2;. i is not greater than tmp -- both of them are 4 -- so the loop will never run and tmp will still be 4. Now you allocate a new array with four elements, copy the existing four elements to it, "update" index to 4 (its current value), and delete the old array. Right afterwards, you attempt to set the element with index 4 to 42. But the array only has four elements, so that is Undefined Behaviour.
Since you have not actually changed the size of the array, or the value of index which indicates its size, your later attempt to print the values of the array will stop at its actual size, ignoring the value you modified outside the storage area of the array (which may belong to some other datastructure, so its value is meaningless anyway.)
If you rename index as size and tmp as new_size, the code is much clearer, and the fix is also clear:
if (i >= size) {
size_t new_size = size;
while (i >= new_size) new_size *= 2; /* NOT > */
double* new_array = new double[new_size]();
for (size_t j = 0; j < size; ++j) new_array[j] = array[j];
array = new_array;
size = new_size;
}
array[i] = value;
This would all have been much simpler and less error-prone if you used a std::vector:
class MyVector {
public:
void AddElement(size_t i, double value) {
if (i >= data_.size()) data_.resize(i + 1);
data_[i] = value;
}
/* Many implementation details omitted */
private:
std::vector<double> data_;
}
std::vector <int> list;
void AddElemenet(int value)
{
list.push_back (value);
}
Just use vector's. Array's size is fixed. Vector's size is dynamic.
I have a 2048x2048 matrix of grayscale image,i want to find some points which value are > 0 ,and store its position into an array of 2 columns and n rows (n is also the number of founded points) Here is my algorithm :
int icount;
icount = 0;
for (int i = 0; i < 2048; i++)
{
for (int j = 0; j < 2048; j++)
{
if (iout.at<double>(i, j) > 0)
{
icount++;
temp[icount][1] = i;
temp[icount][2] = j;
}
}
}
I have 2 problems :
temp is an array which the number of rows is unknown 'cause after each loop the number of rows increases ,so how can i define the temp array ? I need the exact number of rows for another implementation later so i can't give some random number for it.
My algorithm above doesn't work,the results is
temp[1][1]=0 , temp[1][2]=0 , temp[2][1]=262 , temp[2][2]=655
which is completely wrong,the right one is :
temp[1][1]=1779 , temp[1][2]=149 , temp[2][1]=1780 , temp[2][2]=149
i got the right result because i implemented it in Matlab, it is
[a,b]=find(iout>0);
How about a std::vector of std::pair:
std::vector<std::pair<int, int>> temp;
Then add (i, j) pairs to it using push_back. No size needed to be known in advance:
temp.push_back(make_pair(i, j));
We'll need to know more about your problem and your code to be able to tell what's wrong with the algorithm.
When you define a variable of pointer type, you need to allocate memory and have the pointer point to that memory address. In your case, you have a multidimensional pointer so it requires multiple allocations. For example:
int **temp = new int *[100]; // This means you have room for 100 arrays (in the 2nd dimension)
int icount = 0;
for(int i = 0; i < 2048; i++) {
for(int j = 0; j < 2048; j++) {
if(iout.at<double>(i, j) > 0) {
temp[icount] = new int[2]; // only 2 variables needed at this dimension
temp[icount][1] = i;
temp[icount][2] = j;
icount++;
}
}
}
This will work for you, but it's only good if you know for sure you're not going to need any more than the pre-allocated array size (100 in this example). If you know exactly how much you need, this method is ok. If you know the maximum possible, it's also ok, but could be wasteful. If you have no idea what size you need in the first dimension, you have to use a dynamic collection, for example std::vector as suggested by IVlad. In case you do use the method I suggested, don't forget to free the allocated memory using delete []temp[i]; and delete []temp;
I am trying to learn C++ by firstly going through the low level details before I start using abstractions such as std::copy or memcpy. Currently I am stuck in trying to figure out why this code is never assigning into "sortedArray" variable, when looking with debugger I dereference the value from "data" correctly but it is never assigned to "sortedArray". I see value such as "-842150451" instead of "14" for first value. Can you please help me figure out what I am doing wrong ? And any other issues there may be that I do not see or advice would be greatly appreciated !
void swap(int* bigger, int* smaller){
*bigger += *smaller;
*smaller = *bigger - *smaller;
*bigger = *bigger - *smaller;
}
int* bubbleSort(int *data, int size){
bool swapped = true;
int *sortedArray = (int*)malloc(size*sizeof(int));
for (int i = 0; i < size;i++){
*(sortedArray++) = *(data++);
}
while (swapped){
swapped = false;
for (int i = 1; i <= size - 1; i++){
if (sortedArray[i - 1] > sortedArray[i]){
swap(&sortedArray[i - 1], &sortedArray[i]);
swapped = true;
}
}
size--;
}
return sortedArray;
}
*(sortedArray++) = *(data++); modifies the pointer so it no longer points to the start of the allocated memory. So, later on sortedArray[i] is whatever happens to be in memory past the array, and accessing it is undefined behavior.
If you must use pointers, a quick fix is to use a temporary one, like:
int *sortedArray = (int*)malloc(size*sizeof(int));
int* s = sortedArray;
for (int i = 0; i < size;i++){
*s++ = *data++;
}
Another way would be:
int *sortedArray = (int*)malloc(size*sizeof(int));
for (int i = 0; i < size;i++){
sortedArray[i] = data[i];
}
But, the best way would be to use standard containers and algorithms, like vector and sort.
Here's a demo of the first fix in action.
Change
*(sortedArray++) = *(data++);
to
sortedArray[i] = data[i];
You need to leave intact the pointer to the block of memory you allocated, so you can use it (and free it) later.
Note, there is nothing to be gained by using the *(x+y) syntax instead of x[y], they are equivalent but the latter is easier to read.
In C++ you should not use malloc. Instead use new int[size]. For int there is no difference other than reduced risk of making a typo, however for non-trivial types malloc will not construct them correctly.
That is not C++ at all. You can write generic code that takes a begin iterator and an end iterator in order for it to work with any kind of container that supports such semantic.
template<typename IT>
void bubble_sort(IT begin, IT end) {
while (true) {
bool swapped = false;
for (IT i = begin; i != end-1; i = i+1) {
if (*i > *(i+1)) {
std::iter_swap(i, i+1);
swapped = true;
}
}
if (swapped == false) return;
}
}
Live demo
Where std::iter_swap is like std::swap but works on iterators. You can see iterators as a pair of pointers to the beginning and (past the) end of a container.
You first pointer sortedArray points to some allocated memory.
Then in the first for loop you increment the pointer. not it doesn't point to that memory anymore.
Simply use a temporary pointer for the memory copy.
int* t = sortedArray ;
And now use t in your for loop which copies the data.
Instead of the temporary variable, you can rather count the number of times you called sortedArray++ in your for loop.
If you take a look: for (int i = 0; i < size;i++) you will see that the loop took exactly size number of iterations.
Just subtract size from the pointer after the loop and you point back to your allocated memory.
sortedArray -= size ;
I am currently working on a C++ project I have. I am stuck on a function I have to write. The functions name is remove. The purpose of the function is to remove the value in the list at the given index by shifting all elements back one position, -1 replaced the elements at the end of the list. I have finished the shifting portion of this function, i am just stuck on how i put -1 at the end of my array.
Here is my code:
void remove(int vals[], int sz, int index)
{
for(int i = index ; i < (sz-1); ++i)
{
vals[i] = vals[i+1];
}
vals[sz - 1] = -1;
}
If I understand your question correctly I believe you would need:
void remove(int vals[], int sz, int index)
{
//I altered your loop here as the line inside it would have accessed past the
//end your array. I am assuming sz is the number of elements in the array
for(int i = index ; i < sz - 1; ++i)
{
vals[i] = vals[i + 1];
}
//This sets the last element in your array to -1
vals[sz - 1] = -1;
}
Hope this helps.
EDIT: As others have said you may be better using one of the STL containers like std::vector rather than a C-style array if you want to add and remove elements.