I'm having a hard time with this little project of mine; can someone help me out? I am trying to take a pointer to an array, a number, and remove the number if it is present in the array. If the number is removed, the array shrinks. Please note at the time of running removeNumber size = 6.
main
{
int size = 5; // setting array size
int *a = new int[size]; // allocating dynamic array
// initializing array
a[0] = 0; a[1] = 10; a[2] = 20; a[3] = 30; a[4] = 40;
removeNumber(a, 10, size);
}
And now the prototype:
void removeNumber(int *& arrayPtr, int number, int &size)
{
int index = check(arrayPtr, number, size);
int *newArray = new int[size - 1];
if (index != -1)
{
for (int i = number; i <= size; ++i)
newArray[i] = *&arrayPtr[i + 1];
delete[] arrayPtr;
arrayPtr = newArray;
size -= 1;
}
}
Check for reference:
int check(int *arrayPtr, int number, int size)
{
for (int i = 0; i < size; i++)
{
if (arrayPtr[i] == number) return i;
}
return -1;
}
The function is wrong. First of all it has a memory leak in case when the target value is not found in the array.
void removeNumber(int *& arrayPtr, int number, int &size)
{
int index = check(arrayPtr, number, size);
int *newArray = new int[size - 1];
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (index != -1)
{
//...
}
}
Secondly there is used incorrect range of indices
for (int i = number; i <= size; ++i)
^^^^^^ ^^^^^^^^^
newArray[i] = *&arrayPtr[i + 1];
^^^^^^
And you could write this expression *&arrayPtr[i + 1] simpler just like arrayPtr[i + 1].
You forgot to copy the elements of the original array before the index index. number is not a valid index.
Also it would be better if the function returned a Boolean value saying whether the operation was successful or not. You can change the size of the array in the calling function if the call was successful.
So I would write the function like
bool removeNumber( int * &arrayPtr, int n, int value )
{
int index = check( arrayPtr, number, size );
if ( index != -1 )
{
int *tmp = new int[size - 1];
int i = 0;
for ( ; i < index; ++i ) tmp[i] = arrayPtr[i];
for ( ; i < size - 1; i++ ) tmp[i] = arrayPtr[i+1];
delete [] arrayPtr;
arrayPtr = tmp;
}
return index != -1;
}
It is ok to reinvent the wheel in order to learn. However you should be aware of the standard way to handle this: using std::vector along with std::remove/std::remove_if (defined in #include <algorithm>) would make your life much simpler, with the benefit of a performant implementation.
void removeNumber(std::vector<int>& vec, int number) {
vec.erase(std::remove(std::begin(vec), std::end(vec), number),
std::end(vec));
// If you really want to shrink the vector, you can call...
vec.shrink_to_fit();
}
I also made a little demo to show you that it works as intended.
Your problem is here:
for (int i = number; i <= size; ++i)
First of all you start the iteration from the value of the number that you searched(in your case 10) and as a result you will not enter the for loop.So the correct starting value of i is the first number of the array which is 0.Then this line of code here:
newArray[i] = *&arrayPtr[i + 1];
doesn't even make sense(as a thought process not syntactically), but what i think you want to do here is just copy the correct element from the old array to the new one.
A correct implementation of the previous is the following code:
void removeNumber(int *& arrayPtr, int number, int &size)
{
int index = check(arrayPtr, number, size);
if (index != -1)
{
int *newArray = new int[size - 1];
int i = 0,j=0; //i for the old array and j for the new
while(i < size)//while we are in bounds
{
if(i==index)//if the index is the index of the given element
{ //skip this number
i++;
continue;
}
newArray[j++] = arrayPtr[i++];//copy the correct number to the correct position
}
delete[] arrayPtr;
arrayPtr = newArray;
size -= 1;
}
}
Related
I want to resize the array multiple times.It does that the first time but after that, it throws me an error. When I do it the second time, I get an error _CrtIsValidHeapPointer(PUserData). Can someone help me out?
int main()
{
int size = 8;
int *arr = new int[size];
arr[1] = 25;
arr[2] = 30;
int count = 0; //to check size
for (int i = 0; i < size; i++)
{
count = count + 1;
}
cout << count << endl;
resize(arr, size);
int new_count = 0; //to confirm size change
for (int i = 0; i < size; i++)
{
new_count = new_count + 1;
}
cout << new_count << endl;
resize(arr, size);
int new_count2 = 0; //to confirm size change
for (int i = 0; i < size; i++)
{
new_count2 = new_count2 + 1;
}
cout << new_count2 << endl;
return 0;
}
void resize(int *a,int &size)
{
int newsize = 2 * size;
int *arr_new = new int[newsize];
for (int i = 0; i < size; i++) //copy everything
{
arr_new[i] = a[i];
}
size = newsize; //new value of size
delete [] a;
a = arr_new; //Pointer pointing to new array
delete arr_new;
}
There are two problems with this code:
void resize(int *a,int &size)
{
[...]
delete [] a;
a = arr_new; //Pointer pointing to new array
delete arr_new; // huh????
}
The first problem is that you are calling the delete operator twice; the first call deletes the old array (which makes sense), but then you attempt to delete the newly allocated array also (via delete arr_new). How is the caller going to able to use the newly allocated array when resize() has already deleted it before it returned?
The second problem is that you set a to point to the new array (i.e. a = arr_new;) but a is a local function-argument that goes out of scope when resize() returns, so the calling code will never see its new value. I think you want this instead:
void resize(int * & a,int &size) // note the & before a!
Passing a by reference will allow the caller to see a's new value after resize() returns.
For this program I have three data files. The first has a list of numbers, the second is a list of numbers with an add (A) or delete (D) command. I have to put the numbers from the first file into the third file, then update the final file based on the commands and numbers in the second file. The third file cant have duplicates and must be sorted while values are being inserted. Here are the functions I have, I'm having difficulty getting the items stored into the array without duplicates. The array must be statically sized, I did a #define of max size 2000 which is more than enough to handle the numbers I need. Thanks so much! If I should upload the main let me know, but I'm fairly certain the problem lies in one of these functions.
int search(int value, int list[], int n) // returns index, n is logical size of array
{
int index = -1;
for(int i = 0; i < n; i++)
{
if(value == list[i])
{
index = i;
return index;
}
}
return index;
}
void storeValue(int value, int list[], int& n)
{
int i = n;
for(; i > 0 && list[i - 1] < value; i--)
{
list[i] = list[i - 1];
}
list[i] = value;
n++;
}
void deleteValue(int loc, int list[], int n)
{
if(loc >= 0 && loc < n)
{
for(int i = loc; i < n - 1; i++)
list[i] = list[i +1];
n--;
}
}
UPDATE: Now duplicates are being stored, but only for some numbers.
For example: my 3rd file is: 1,2,8,8,9,101,101,104,etc.
The output should be: 1,2,8,9,101,104,etc
value: value to be inserted
list[]: array being modified (must be static)
n: logical size of array
I can't figure out why some numbers are duplicated and others aren't
In my main, I run the search function and if a -1 is returned (the value isn't already found) then I run the storeValue function.
Here are my updated functions:
int search(int value, int list[], int n) // returns index
{
int index = -1;
for(int i = 0; i < n; i++)
{
if(value == list[i])
{
index = i;
return index;
}
}
return index;
}
void storeValue(int value, int list[], int& n)
{
int i = n;
for(; i > 0 && list[i - 1] > value; i--)
{
list[i] = list[i - 1];
}
list[i] = value;
n++;
}
void deleteValue(int loc, int list[], int& n)
{
if(loc >= 0 && loc < n)
{
for(int i = loc; i < n; i++)
{
if (i == loc)
{
list[i] = list[i + 1];
i++;
}
}
n--;
}
}
In your deleteValue function, you are deleting the value, but will end up with a duplicate because you are just reassigning the current index to the next value. For example, if you have the array:
char array[3] = [1, 2, 3];
and you wanted to delete the second integer, your function currently would output this:
[1, 3, 3]
What you want to do is make a new array and loop through your entire list, making sure to leave out the last element like so:
char* deleteValue(int loc, int list[], int n)
{
char* newArray[n - 1];
if (loc >= 0 && loc < n)
{
for (int i = 0; i < n - 1; i++)
{
if (i == loc) // You have arrived at the element that needs to be deleted
{
newArray[i] = list[i + 1];
i++; // So we skip over the deleted element
}
else
newArray[i] = list[i];
}
}
return newArray;
}
And this should take care of the case where the last value is duplicated.
void insert(int*arr, int element,int index)
{
if (index < SIZE)
{
arr[index] = element;
}
else
{
int* new_array = new int[SIZE + 1];
int i = 0;
for (i = 0; i < SIZE; i++)
{
new_array[i] = arr[i];
}
new_array[i] = element;
SIZE++;
printArray(new_array);
}
}
I have made an insert function in C++ that will insert values at specific indices of the array.After index gets increased I made a new array and copied values from the smaller array into it.
Problem is that printArray function which is just looping to print the array does well when it is called inside the insert function otherwise when I called printArray from the main last value of the array was garbage why is that?
You need to delete the old array and return the new array in its place, e.g.:
void insert(int* &arr, int element, int index) // <<< make `arr` a reference so that we can modify it
{
if (index < SIZE)
{
arr[index] = element;
}
else
{
int* new_array = new int[SIZE + 1];
for (int i = 0; i < SIZE; i++)
{
new_array[i] = arr[i];
}
new_array[SIZE] = element;
SIZE++; // <<< NB: using a global for this is not a great idea!
delete [] arr; // <<< delete old `arr`
arr = new_array; // <<< replace it with `new_array`
}
}
LIVE DEMO
Note that all this explicit low level management of your array goes away if you start using proper C++ idioms, such as std::vector<int> instead of C-style int * arrays.
Input :
A[4] = {0,4,-1,1000} - Actual Array
P[4] = {1,0,3,2} - Order to be reshuffled
Output:
A[4] = {4,0,1000,-1}
Condition : Don't use an additional array as memory. Can use an extra variable or two.
Problem : I have the below program in C++, but this fails for certain inputs of array P.
#include<iostream>
using namespace std;
void swap(int *a_r,int *r)
{
int temp = *r;
*r = *a_r;
*a_r = temp;
}
int main()
{
int A[4] = {0,4,-1,1000};
int P[4] = {3,0,1,2};
int value = A[0] , dest = P[0];
for(int i=0; i<4;i++)
{
swap(&A[dest],&value);
dest = P[dest];
}
for(int i=0;i<4;i++)
cout<<A[i]<<" ";
}
Since you've got a spare array called P kicking around, and there isn't anything in the question as quoted that stipulates it must be treated as a constant array, you could do:
for (i = 0; i < 4; i++)
P[i] = A[P[i]];
for (i = 0; i < 4; i++)
A[i] = P[i];
If you're not allowed to modify P, then you have to work a lot harder (and you also have to work a lot harder if the data type of A is not the same as, or compatible with, the type of P).
However, I fear this is a sleight-of-hand trick that doesn't really answer the question; it gets the job done, but doesn't answer the question.
First of all, I really like Jonathan's solution, but I feel like I can add some interesting ideas too.
The main observation is that array P consists of several loops.
Let's consider p = {1, 4, 3, 2, 0, 5}. There're three loops: 0 => 1 => 4 => 0, 2 => 3 => 2 and 5 => 5. And to replace variables alongside one loop we need no additional memory at all. We just go through it like this
do {
a[i] = a[p[i]];
i = p[i];
} while (i != first_i);
(The last element needs to be taken special care of, though.) The full working version:
for (int i = 0; i < n; ++i) {
if (p[i] < 0) {
// been at index 'i' already
continue;
}
// new loop found
int j = i;
int first_value = a[i]; // to be put in last position in the chain
int prev_j; // we always store previous 'j' index
do {
a[j] = a[p[j]];
prev_j = j;
j = p[j]; // move to next 'j'
p[prev_j] = -1; // mark element as processed
} while (i != j);
a[prev_j] = first_value;
}
The only problem with my solution is that it uses p array to mark element as 'processed'. Some interviewers may consider it ok, others - not, depending on the solution they have in mind.
int _tmain(int argc, _TCHAR* argv[])
{
A[4] = {0,4,-1,1000}
P[4] = {1,0,3,2}
int temp = arr2[0];
for(int i=0;i<4;i++)
{
for(temp = P[i];i<3;temp = P[temp])
{
if(temp >= i)
{
int data;
data = A[i];
A[i] = A[temp];
A[temp] = data;
break;
}
}
}
_getch();
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
A[4] = {0,4,-1,1000}
P[4] = {1,0,3,2}
int temp = arr2[0];
for(int i=0;i<4;i++)
{
for(temp = P[i];i<3;temp = P[temp])
{
if(temp >= i)
{
int data;
data = A[i];
A[i] = A[temp];
A[temp] = data;
break;
}
}
}
_getch();
return 1;
}
Slightly modified to calculate dest value
int main()
{
int A[4] = {0,4,-1,1000};
int P[4] = {3,0,1,2};
int value = A[0], dest = P[0];
for(int i=0; i<4-1;i++)
{
int count=0;
dest = P[i];
while(dest<i){ //if P[i] points to lower value, it got swapped with some other position.
dest = P[dest];
}
swap(&A[dest],&A[i]);
}
for(int i=0;i<4;i++)
cout<<A[i]<<" ";
cout<<"\n";
}
Could argue that it goes against the spirit of the question - but can use multiple stack instances (from a run-time perspective) of a single local variable (code perspective). Being allowed to mutate P is just as uncertain, so, FWIW - a recursive answer...
template <int N>
void shuffle(int (&a)[N], int p[], int i = -1)
{
if (++i < N)
{
int result = a[p[i]];
shuffle(a, p, i);
a[i] = result;
}
}
I would like to sort an array in ascending order using C/C++. The outcome is an array containing element indexes. Each index is corespondent to the element location in the sorted array.
Example
Input: 1, 3, 4, 9, 6
Output: 1, 2, 3, 5, 4
Edit: I am using shell sort procedure. The duplicate value indexes are arbitrarily chosen based on which duplicate values are first in the original array.
Update:
Despite my best efforts, I haven't been able to implement a sorting algorithm for an array of pointers. The current example won't compile.
Could someone please tell me what's wrong?
I'd very much appreciate some help!
void SortArray(int ** pArray, int ArrayLength)
{
int i, j, flag = 1; // set flag to 1 to begin initial pass
int * temp; // holding variable orig with no *
for (i = 1; (i <= ArrayLength) && flag; i++)
{
flag = 0;
for (j = 0; j < (ArrayLength - 1); j++)
{
if (*pArray[j + 1] > *pArray[j]) // ascending order simply changes to <
{
&temp = &pArray[j]; // swap elements
&pArray[j] = &pArray[j + 1]; //the problem lies somewhere in here
&pArray[j + 1] = &temp;
flag = 1; // indicates that a swap occurred.
}
}
}
};
Since you're using C++, I would do it something like this. The SortIntPointers function can be any sort algorithm, the important part is that it sorts the array of pointers based on the int that they are pointing to. Once that is done, you can go through the array of pointers and assign their sorted index which will end up in the original position in the original array.
int* intArray; // set somewhere else
int arrayLen; // set somewhere else
int** pintArray = new int*[arrayLen];
for(int i = 0; i < arrayLen; ++i)
{
pintArray[i] = &intArray[i];
}
// This function sorts the pointers according to the values they
// point to. In effect, it sorts intArray without losing the positional
// information.
SortIntPointers(pintArray, arrayLen);
// Dereference the pointers and assign their sorted position.
for(int i = 0; i < arrayLen; ++i)
{
*pintArray[i] = i;
}
Hopefully that's clear enough.
Ok, here is my atempt in C++
#include <iostream>
#include <algorithm>
struct mycomparison
{
bool operator() (int* lhs, int* rhs) {return (*lhs) < (*rhs);}
};
int main(int argc, char* argv[])
{
int myarray[] = {1, 3, 6, 2, 4, 9, 5, 12, 10};
const size_t size = sizeof(myarray) / sizeof(myarray[0]);
int *arrayofpointers[size];
for(int i = 0; i < size; ++i)
{
arrayofpointers[i] = myarray + i;
}
std::sort(arrayofpointers, arrayofpointers + size, mycomparison());
for(int i = 0; i < size; ++i)
{
*arrayofpointers[i] = i + 1;
}
for(int i = 0; i < size; ++i)
{
std::cout << myarray[i] << " ";
}
std::cout << std::endl;
return 0;
}
create a new array with increasing values from 0 to n-1 (where n is the length of the array you want to sort). Then sort the new array based on the values in the old array indexed by the values in the new array.
For example, if you use bubble sort (easy to explain), then instead of comparing the values in the new array, you compare the values in the old array at the position indexed by a value in the new array:
function bubbleRank(A){
var B = new Array();
for(var i=0; i<A.length; i++){
B[i] = i;
}
do{
swapped = false;
for(var i=0; i<A.length; i++){
if(A[B[i]] > A[B[i+1]]){
var temp = B[i];
B[i] = B[i+1];
B[i+1] = temp;
swapped = true;
}
}
}while(swapped);
return B;
}
create a new Array and use bubble sort to rank the elements
int arr[n];
int rank[n];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(arr[i]>arr[j])
rank[i]++;
The rank of each element will be rank[i]+1 to be in the order of 1,2,....n
Well, there's a trival n^2 solution.
In python:
newArray = sorted(oldArray)
blankArray = [0] * len(oldArray)
for i in xrange(len(newArray)):
dex = oldArray.index(newArray[i])
blankArray[dex] = i
Depending on how large your list is, this may work. If your list is very long, you'll need to do some strange parallel array sorting, which doesn't look like much fun and is a quick way to introduce extra bugs in your code.
Also note that the above code assumes unique values in oldArray. If that's not the case, you'll need to do some post processing to solve tied values.
Parallel sorting of vector using boost::lambda...
std::vector<int> intVector;
std::vector<int> rank;
// set up values according to your example...
intVector.push_back( 1 );
intVector.push_back( 3 );
intVector.push_back( 4 );
intVector.push_back( 9 );
intVector.push_back( 6 );
for( int i = 0; i < intVector.size(); ++i )
{
rank.push_back( i );
}
using namespace boost::lambda;
std::sort(
rank.begin(), rank.end(),
var( intVector )[ _1 ] < var( intVector )[ _2 ]
);
//... and because you wanted to replace the values of the original with
// their rank
intVector = rank;
Note: I used vectorS instead of arrays because it is clearer/easier, also, I used C-style indexing which starts counting from 0, not 1.
This is a solution in c language
#include <stdio.h>
void swap(int *xp, int *yp) {
int temp = *xp;
*xp = *yp;
*yp = temp;
}
// A function to implement bubble sort
void bubbleSort(int arr[], int n) {
int i, j;
for (i = 0; i < n - 1; i++)
// Last i elements are already in place
for (j = 0; j < n - i - 1; j++)
if (arr[j] > arr[j + 1])
swap(&arr[j], &arr[j + 1]);
}
/* Function to print an array */
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 98};
int arr_original[] = {64, 34, 25, 12, 22, 11, 98};
int rank[7];
int n = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, n);
printf("Sorted array: \n");
printArray(arr, n);
//PLACE RANK
//look for location of number in original array
//place the location in rank array
int counter = 1;
for (int k = 0; k < n; k++){
for (int i = 0; i < n; i++){
printf("Checking..%d\n", i);
if (arr_original[i] == arr[k]){
rank[i] = counter;
counter++;
printf("Found..%d\n", i);
}
}
}
printf("Original array: \n");
printArray(arr_original, n);
printf("Rank array: \n");
printArray(rank, n);
return 0;
}