Passing Array to Class Method for Selection Sort - c++

I'm supposed to use this to sort an array.
template <class T>
class Selection
{
private:
T* ptr;
public:
Selection(T len)
{
cout << "Allocating Selection ptr\n";
//allocate memory for the pointer
ptr = new T;
*ptr = len;
};
T getobj(void)
{
return *ptr;
};
static SelectionSort(T arr[], int n)
{
//pos_min is short for position of min
T pos_min, temp;
for (int i = 0, j; i < n - 1; i++)
{
pos_min = i;//set pos_min to the current index of array
for (j = i + 1; j < n; j++)
{
if (arr[j] < arr[pos_min])
pos_min = j;
}
//pos_min keeps track of the index that min is in
//if pos_min no longer equals i than a smaller value must have been found
if (pos_min != i)
{
temp = arr[i];
arr[i] = arr[pos_min];
arr[pos_min] = temp;
}
}
};
};
Created the array in main:
int arr1[10] = { 1, 2, 7, 4, 5 };
int m = sizeof(arr1) / sizeof(arr1[0])
Have no idea how to pass the array to the SelectionSort function in class Selection (it was void but I was trying stuff out with static because internet. So far everything I've tried leaves me with about 10-13 fatal errors)
None of which I understand.
What is the syntax to pass arr1 to the SelectionSort within Class Selection?

Firstly, try to change type of pos_min in SelectionSort function from T to int and add a void as a return value of this function.
Then, try to create an object of class Selection with type name in angle brackets, initialise an array and put it in class method. I mean try to do like this:
Selection<double> sel(5);
double ar[] = {5, 4, 3, 2, 1};
sel.SelectionSort(ar, 5);

Related

Swap array elements depending on function (given as argument) return

I have a problem with function that takes: array, size of that array and function (or lambda), and then sort given array depending of what function given in argument returns. For example:
int a1[] = {1,2,3,4,5,6};
part(a1,6,isEven); // where isEven is simple function for checking if element is even
Should return:
[ 2 4 6 1 5 3 ]
I already write this like that, where im retur new, sorted array:
template <typename T, typename FUN>
size_t part(T* arr, size_t size, FUN f) {
T new_arr[size] = {};
int first = 0;
int last = size - 1;
int index = 0;
bool changed = false;
for(int i = 0; i < size; i++){
if(f(arr[i])){
new_arr[first] = arr[i];
first++;
} else {
if(!changed){index = i;}
new_arr[last] = arr[i];
last--;
}
}
for(int j = 0; j < size; j++){
std::cout << new_arr[j] << " ";
}
return new_arr;
}
But I have to do this without using any other array. And it has to be done in one loop.
You were nearly there.
You must not use an additional array. But in line T new_arr[size] = {}; you try to do this. And, this will not work, because this is a VLA (Variable Lenth Array). VLAs are not part of the C++ language. Some compilers accept VLAs as extension, but, if you tell them to compile C++, then also those will reject it. In C++ the size of an array must be known at compile time. It must be a constant.
So, since you anyway work with pointers, you can also use new to allocate temporary memory. Then simply replace the above line with T* new_arr = new T[size]{};
And, you must not forget to delete the allocated memory. Or, you could copy the new data at the end of the function to the original and then delete the temporaray memory there.
So, in my opinion not the best approach. Anyway, the C++ standard library has the functions partition and stable_partition.
Anyway. Please see below:
#include <iostream>
#include <algorithm>
template <typename T, typename FUN>
T* part(T* arr, size_t size, FUN f) {
T* new_arr = new T[size]{};
int first = 0;
int last = size - 1;
int index = 0;
bool changed = false;
for (int i = 0; i < size; i++) {
if (f(arr[i])) {
new_arr[first] = arr[i];
first++;
}
else {
if (!changed) { index = i; }
new_arr[last] = arr[i];
last--;
}
}
return new_arr;
}
int main() {
int data[]{ 1,2,3,4,5,6 };
int *p = part(data, (sizeof(data) / sizeof(data[0])), [](const int i) {return i % 2 == 0; });
for (int i = 0; i < (sizeof(data) / sizeof(data[0])); ++i)
std::cout << p[i] << ' ';
delete[]p;
}

Function to delete an element from an array not working

I wanted to write a function which upon being called deletes an element from an array given that the parameters passed in the deleteArray function were the array, its length and the value of the element to be deleted.
Tried breaking out of the for loop while transversing through the array if the element was found and then tried using i's value in another for loop to replace the current elements with their next element.
like array[j] = array[j + 1]
Here is the code:
#include <iostream>
using namespace std;
void deleteElement(int[], int, int);
int main() {
int array1[] = { 1, 4, 3, 5, 6 };
int length = sizeof(array1) / sizeof(array1[0]); //For length of array
deleteElement(array1, length, 4);
cout << "\nIn main function\n";
for (int i = 0; i < length; i++) {
cout << array1[i];
}
return 0;
}
void deleteElement(int array2[], int length, int element) {
int i = 0;
for (int i; i < length; i++) {
if (array2[i] == element) {
for (int j = i; j < length; j++) {
array2[j] = array2[j + 1];
}
break;
}
}
if (i == (length - 1)) {
cout << ("Element doesn't exist\n");
}
cout << "Testing OP in deleteElement\n";
for (int i = 0; i < length; i++) {
cout << array2[i];
}
}
Expected:
Testing OP in deleteElement
14356
In main function
1356
Actual:
Testing OP in deleteElement
14356
In main function
14356
The problem is rather silly:
At the beginning of deleteElement(), you define i with int i = 0;, but you redefine another variable i as a local index in each for loop. The for loop introduces a new scope, so the int i definition in the first clause of the for loop defines a new i, that shadows the variable with the same name defined in an outer scope.
for (int i; i < length; i++) {
And you do not initialize this new i variable.
There are 2 consequences:
undefined behavior in the first loop as i is uninitialized. The comparison i < length might fail right away.
the test if (i == (length - 1)) { tests the outer i variable, not the one that for iterated on. Furthermore, the test should be if (i == length) {
There are other issues:
the nested for loop iterates once too many times: when j == length - 1, accessing array[j + 1] has undefined behavior.
you do not update length, so the last element of the array is duplicated. You must pass length by reference so it is updated in the caller's scope.
Here is a corrected version:
#include <iostream>
using namespace std;
void deleteElement(int array2[], int& length, int element);
int main() {
int array1[] = { 1, 4, 3, 5, 6 };
int length = sizeof(array1) / sizeof(array1[0]); //For length of array
deleteElement(array1, &length, 4);
cout << "\nIn main function\n";
for (int i = 0; i < length; i++) {
cout << array1[i] << " ";
}
return 0;
}
void deleteElement(int array2[], int& length, int element) {
int i;
for (i = 0; i < length; i++) {
if (array2[i] == element)
break;
}
if (i == length) {
cout << "Element doesn't exist\n";
} else {
length -= 1;
for (; i < length; i++) {
array2[i] = array2[i + 1];
}
}
cout << "Testing OP in deleteElement\n";
for (i = 0; i < length; i++) {
cout << array2[i] << " ";
}
}
If you use the algorithm function std::remove, you can accomplish this in one or two lines of code without writing any loops whatsoever.
#include <algorithm>
#include <iostream>
void deleteElement(int array2[], int& length, int element)
{
int *ptr = std::remove(array2, array2 + length, element);
length = std::distance(array2, ptr);
}
int main()
{
int array1[] = { 1, 4, 3, 5, 6 };
int length = sizeof(array1) / sizeof(array1[0]); //For length of array
deleteElement(array1, length, 4);
for (int i = 0; i < length; ++i)
std::cout << array1[i];
}
Output:
1356
Note that we could have written the deleteElement function in a single line:
void deleteElement(int array2[], int& length, int element)
{
length = std::distance(array2, std::remove(array2, array2 + length, element));
}
Basically, std::remove moves the removed element to the end of the sequence, and returns a pointer to the beginning of the removed elements.
Thus to get the distance from the beginning of the array to where the removed elements are located, usage of std::distance is done to give us our new length.
To remove only the first found element, std::find can be used, and then std::copy over the elements, essentially wiping out the item:
void deleteElement(int array2[], int& length, int element)
{
int *ptr = std::find(array2, array2 + length, element);
if ( ptr != array2 + length )
{
std::copy(ptr+1,array2 + length, ptr);
--length;
}
}
int main()
{
int array1[] = { 1, 4, 3, 5, 4, 6, 9 };
int length = sizeof(array1) / sizeof(array1[0]); //For length of array
deleteElement(array1, length, 4);
for (int i = 0; i < length; ++i)
std::cout << array1[i];
}
Output:
135469
There is no need for multiple loops in deleteElement. Additionally, your removal will fail to remove all elements (e.g. 4 in your example) if your array contains more than one 4, e.g.
int array1[] = { 1, 4, 3, 4, 5 };
You can simplify your deleteElement function and handle removing multiple occurrences of element simply by keeping a count of the number of times the element is found and by using your counter as a flag to control removal, e.g.:
void deleteElement(int array2[], int& length, int element)
{
int found = 0; /* flag indicating no. element found */
for (int i = 0; i < length; i++) { /* iterate over each element */
if (array2[i] == element) { /* check if matches current */
found += 1; /* increment number found */
continue; /* get next element */
}
if (found) /* if matching element found */
array2[i-found] = array2[i]; /* overwrite elements to end */
}
length -= found; /* update length based on no. found & removed */
}
Updating your example main() to show both pre-delete and post-delete, you could do something like the following:
int main (void) {
int array1[] = { 1, 4, 3, 4, 5 };
int length = sizeof array1 / sizeof *array1; //For length of array
cout << "\nBefore Delete\n";
for (int i = 0; i < length; i++)
cout << " " << array1[i];
cout << '\n';
deleteElement(array1, length, 4);
cout << "\nAfter Delete\n";
for (int i = 0; i < length; i++)
cout << " " << array1[i];
cout << '\n';
}
Example Use/Output
Which in the case where you array contains 1, 4, 3, 4, 5 would result in:
$ ./bin/array_del_elem
Before Delete
1 4 3 4 5
After Delete
1 3 5
While you are using an array of type int (of which there are many in both legacy and current code), for new code you should make use of the containers library (e.g. array or vector, etc...) which provide built in member functions to .erase() elements without you having to reinvent the wheel.
Look things over and let me know if you have further questions.
This is because the length of the array is never updated after deleting. Logically the length should decrease by 1 if the element was deleted.
To fix this, either
Pass the length by reference and decrease it by 1 if the element is actually deleted. OR
Return from the deleteElement some value which indicates that the element was deleted. And based of that, decrease the value of length in the main function.
Recalculating the array length will not help because the element is not actually deleted in memory. So the memory allocated to he array remains same.
Other issues:
The first for loop in deleteElement should run till j < length - 1.
The for loop creates a local variable i, which shadows the i variable in outer scope, so the outer i is never updated and always remains = 0

Set value by default in first position in index array

Im trying set an array to have always same value in first position, but idk how to do that. for example array[10] always array[0] = 100, then continue add ohters number like: array[100,1,2,3.....], loop array[100,1,2,3.....] etc.
int main() {
int arrayNumber[10];
while (true)
{
for (int i = 0; i < 10; i++)
{
arrayNumber[0] = 100;
printf("%d\n", arrayNumber[i]);
Sleep(100);
}
}
}
Set the first value outside the loop and start the loop at 1.
arrayNumber[0] = 100;
for (int i = 1; i < arraysize; i++)
{
arrayNumber[i] = i;
}
int main() {
int arrayNumber[10] = {100};
for (int i = 1; i < 10; i++) {
arrayNumber[i] = i;
}
}
The first operator above declares the array and initializes the first it's element with the value 100, then the loop fills other elements with 1, 2, 3, ..., 9.
Since your asked about C++ let introduce C++-like solution below.
#include <numeric>
int main() {
int arrayNumber[10] = {100};
std::iota(arrayNumber + 1, arrayNumber + 10, 1);
}
Here the function iota fills the passed range in the array with sequentially increasing values, starting with 1.

Integer Array Slicing

I was reading through this thread Array slicing in c++ and came close to what I was looking for but not exactly. I want to remove the first 3 elements from an int array.
What I Have Now:
void shiftArray(int *arr, int size) {
for (int i = 0; i < size - 3; i++) {
arr[i] = arr[i + 3];
arr[i + 3] = -1; // can't re size array so set them to -1
}
}
What I Want:
int* shiftArray(int *arr, int size) { // return type can stay void if possible
return arr[3::]; // python
}
Is it possible to have a non iterative approach to shift the first three elements to the end with value -1 and move the rest of the elements up to take their place?
You can use std::rotate and std::fill:
std::fill( std::rotate(arr, std::begin(arr) + 3, std::end(arr)), std::end(arr), -1);
http://coliru.stacked-crooked.com/a/b3e0557ee0481162
... but, its not as elegant as php :-)
[edit]
above requires C++11 below is compatible with older C++ standard versions:
template<typename T, size_t n>
void left_shift(T (&arr)[n], size_t left_shift){
assert(left_shift < n);
std::fill( std::rotate(arr, arr + left_shift, arr + n), arr + n, -1);
}
left_shift(arr, 3);
http://coliru.stacked-crooked.com/a/c09c27e3ebd60952
It sounds like you want to remove the first 3 elements in-place, using a resizeable array.
A resizeable array in C++ is called std::vector. The constructs std::array, and C-style arrays, are not resizeable.
In generic form the code could be:
template<size_t N, typename T>
void erase_start( std::vector<T> &arr )
{
if ( arr.size() <= N )
arr.clear();
else
arr.erase( arr.begin(), arr.begin() + N );
}
There isn't a pre-potted vector member function to erase based on count, it only takes iterators. But you could make such a function easily enough.
The invocation could look like:
std::vector<int> vec = { 1, 2, 3, 4, 5, 6, 7 };
erase_start<3>(vec);
use this function it simply delete the old one and return new int array pointer by shifted cells, I want just mention something shiftStartIndex is where you want to shift from until end of array so the new size of array will be (size - shiftStartIndex) this prevent array to get out of index, I hope this be useful.
int *shiftArray(int *, int, int);
int main()
{
int size = 6;
int *b = new int[size]{ 1, 2, 3, 4, 5, 6 };
int shiftStartIndex = 3;
b = shiftArray(b, size, shiftStartIndex);
int newSize = size - shiftStartIndex;
for (int i = 0; i < newSize; i++)
{
cout << b[i] << " ";
}
cin.ignore();
return 0;
}
int *shiftArray(int *arr, int size, int stIndex)
{
int *a = new int[size - stIndex];
for (int i = 0; i < size - stIndex; i++)
{
a[i] = arr[i + stIndex];
}
delete[] arr;
return a;
}

How to Delete all the element which are at some index of first array and the index is taken from second array?

I want to Write a function which takes 2 arrays-
One array is the source array and the other array is the array of indices.
I want to delete all those elements present at the indices of the source array taking the indices from the second array.
Suppose First array is : {12,5,10,7,4,1,9} and index array is : {2,3,5}.
Then the elements at index 2,3,5. i.e. 10, 7 and 1 are deleted from first array.
So first array becomes : {12,5,4,9}.
If the indices array is sorted,then my O(N) solution is:
#include<iostream>
using namespace std;
int main()
{
int arr[]={12,5,10,7,4,1,9},n=7,indices[]={2,3,5},m=3;
int j=0,k=0;
for(int i=0;i<n,k<m;i++)
{
if(i!=indices[k])
arr[j++]=arr[i];
else
k++;
}
for(i=0; i<j; i++)
cout<<arr[i]<<" ";
return 0;
}
How to do it in O(n) if the indices array is not sorted ?
According to the comments:
Is there any value that will never appear in arr but is representable by int?
You can take that as int max.
Now you can use removeIndices
#include<iostream>
#include<limits>
int removeIndices(int* arr, int n, int* indices, int m){
const int NEVER_IN_ARRAY = std::numeric_limits<int>::max();
for(int i = 0; i < m; i++)
arr[indices[i]] = NEVER_IN_ARRAY;
for(int from = 0, to = 0; from < n; from++)
if(arr[from] != NEVER_IN_ARRAY)
arr[to++] = arr[from];
return n - m;
}
int main(){
int arr[] = {12, 5, 10, 7, 4, 1, 9}, n = 7, indices[] = {2, 3, 5}, m = 3;
int newSize = removeIndices(arr, n, indices, m);
for(int i = 0; i < newSize; i++)
std::cout << arr[i] << " ";
return 0;
}
Edit: With
#include<algorithm>
#include<functional>
We can do:
int removeIndices(int* arr, int n, int* indices, int m){
const int NEVER_IN_ARRAY = std::numeric_limits<int>::max();
std::for_each(indices, indices + m, [arr](int index){ arr[index] = NEVER_IN_ARRAY; });
int* p = std::remove_if(arr, arr + n, std::bind2nd(std::equal_to<int>(), NEVER_IN_ARRAY));
return p - arr;
}
loop thru filter array and mark dead elements with tombstones
create a new array, and copy step-by-step while skipping tombstones
if it's possible use a tombstone value, for example if it is guranteed that -1 doesn't appear in the input then -1 can be the tombstone value
if this is not possible use an array of boolean markers, init them to false
in-place filtering after marking:
for(int i=0,j=0;j<n;i++,j++){
if( a[j] == TOMBSTONE ){
i--; // the loop will add +1
continue;
}
if(i==j)
continue; // skip, no need to write
arr[i]=arr[j];
}
arr input length: n
arr new length: i
May be you want something like this:
#include<iostream>
#define INVALID 99999 //to mark the elements who will disappear
using namespace std;
int main()
{
int arr[] = {0,1,2,3,4,5,6,7,8,9,10};
int indices = {3,1,5};
int indices_len = 3;
int arr_len = 3;
for(int i=0; i<indices_len; i++){
arr[indices[i]] = INVALID;
}
int invalid_count=0;
for(int i=0; i<arr_len; i++){
if(arr[i] == INVALID){
invalid_count++;
}
arr[i-invalid_count] = arr[i];
}
return 0;
}
You must add the result to a new array 1-just iterate over all all elements if the index is in the to delete array continue else copy it to the new array, you can look at the CArray class from MFC it has RemoveAt method
PseudoCode
int old_arr[MAX_SIZE], new_arr[MAX_SIZE];
bool to_del[MAX_SIZE] = {0};
int index_to_del[MAX_SIZE];
for (size_t i = 0; i < MAX_SIZE; ++i)
to_del[index_to_del[i]] = true;
size_t new_size = 0;
for (size_t i = 0; i < MAX_SIZE; ++i)
if (!to_del[i])
new_arr[new_size++] = old_arr[i];
Edit
The above snippet consumes extra space.
If we had to do it in-place, then every time, we delete an element we will have to shift all consecutive elements by 1. In worst case, this could be O(n**2). If you want to do it in-place without yourself copying array elements, you could use vector.
If deletes outnumber reads, then consider using multiset
Here is a solution that does it in-place, does not allocate memory on the heap, does not require flag values, and does it in O(N+M) time:
#include <cstddef>
template<std::size_t N>
std::size_t removeIndices( int(&src)[N], std::size_t srcSize, int const* removal, std::size_t removeSize )
{
bool remove_flags[N] = {false};
for( int const* it = removal; it != removal+removeSize; ++it ) {
remove_flags[*it] = true;
}
int numberKept = 0;
for( int i = 0; i < srcSize; ++i ) {
if( !remove_flags[i] ) {
if (numberKept != i)
src[numberKept] = src[i];
++numberKept;
}
}
return numberKept;
}
Note that it needs full access to the source array, because I create a temporary stack buffer of bool that is the same size. In C++1y, you'll be able to do this without that compile time knowledge using variable length arrays or similar types.
Note that some compilers implement VLAs via (hopefully partial) C99 compatibility already.