I am trying to get the nth largest number of an array, I tried to sort the array then access the nth number by indexing; I have written this code:
#include <iostream>
using namespace std;
int largest(int a[],int k){
for (int i=0;i<=(sizeof(a)/sizeof(*a));i++){
for (int j=i+1;j<=(sizeof(a)/sizeof(*a));j++){
if(a[j]>a[i]){
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
return a[k-1];
}
int main()
{
int a[]={3,2,1,0,5,10};
int m=largest(a,4);
cout<<m<<endl;
return 0;
}
and when I print out m it appears to be 5 while it is expected to be 2, when I tried to replace int m=largest(a,4); with m=largest(a,1); it printed 2 so it appears that he prints the index of the array a but without sorting it, any idea?
The problem lies in the use of sizeof(a)/sizeof(*a) to get the number of elements of the array. sizeof(a) is the size of a pointer.
You need to pass the size of the array to the function.
int largest(int a[], int size, int k){
for (int i=0;i<size;i++){
for (int j=i+1;j<size;j++){
...
}
}
}
and call it with
int m = largest(a, 6, 4);
There are three problems with your code.
First, when you pass the array as an argument to your function, it decays into a pointer. So the function can never know the size of the array without additional information. It is main()'s job to find the size of the array and pass that information along to largest().
Second, you have an off-by-one error in your code, because you are attempting to iterate from 0 to the number of elements in the array.
The following will work:
#include <iostream>
using namespace std;
int largest(int a[],int k, int n){
for (int i = 0; i < n; i++){
for (int j = i + 1; j < n; j++){
if (a[j] > a[i]){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
return a[k-1];
}
int main()
{
int a[] = {3, 2, 1, 0, 5, 10};
int k = 4;
int m = largest(a, k, sizeof a/ sizeof *a);
cout << m << endl;
}
At last but not least, you have nasty side effects in your function. If you have a function that is supposed to find the largest element of the array, it shouldn't modify the entire array in order to do so.
You can make a copy of the original array and sort it. Or you can implement a k-element sort algorithm. Either way you shouldn't change user data just to find some statistic from it.
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a[]={3,2,1,0,5,10};
std::sort(a, a+6, greater<int>() ); // Sort an array of 6 elements in greatest-first order.
cout<<a[3]<<endl; // Show the 4th element from the front.
return 0;
}
UPD: There are STL algorithm to use: std::nth_element.
#include <iostream>
#include <algorithm>
int main(){
int arr[] = {54, 897, 87, 4, 6,987};
size_t length = 6, k = 3;
std::cout<<std::nth_element(arr, arr + k, arr + length, std::greater<int>());
}
Also, if you want to implement it by yourselt you can do such thing based on quick sort:
#include <iostream>
#include <algorithm>
template<class T>
T largest_k(T* a, size_t left, size_t right, size_t k) {
if(left>=right)
return a[k-1];
size_t i = left, j = right;
T middle = a[ i + (j-i) / 2 ];
do {
while ( a[i] > middle ) i++;
while ( a[j] < middle ) j--;
if (i <= j) {
std::swap(a[i], a[j]);
i++; j--;
}
} while ( i<=j );
// We need to go deeper only for needed part of a
if ( k<=j+1 )
return largest_k(a, left, j, k);
if ( k>= i )
return largest_k(a, i, right, k);
}
int main()
{
int arr[] = {54, 897, 87, 4, 6,987};
size_t length = 6, k = 3;
std::cout<<largest_k<int>(arr, 0, length-1, k);
}
Related
I'm a C++ beginner and I'm stuck on my course assignment because I can't wrap my head around how to modify values of an array passed to a function.
Honestly, we haven't reached the topic about arrays yet in class, but I recall some basic functionalities related to them and I wanted to solve the exercise using arrays because it's surely a smarter way to do it then the easy version of the assignment without them (that I've already solved). I've looked online for some references but clearly I'm missing something important.
The assignment states:
In this exercise you’ll investigate a simple scheme for encrypting and decrypting data. A company that wants to send data over the Internet has asked you to write a program that will encrypt the data so that it may be transmitted more securely. All the data is transmitted as four-digit integers. Your application should read a four-digit integer entered by the user and encrypt it as follows:
Replace each digit with the result of adding 7 to the digit and getting the remainder after dividing the new value by 10.
Then swap the first digit with the third, and swap the second digit with the fourth.
Then print the encrypted integer.
And my attempt is this:
main.cpp
#include "encrypt.h"
#include <iostream>
const size_t size{4};
int main () {
int arrEncrypt[size] = {1, 2, 3, 4};
swap(arrEncrypt[size]);
encrypt(arrEncrypt[size]);
printArr(arrEncrypt[size]);
}
encrypt.h
#ifndef ENCRYPT_H
#define ENCRYPT_H
void encrypt(int a[]);
void swap(int a[]);
void printArr(int a[]);
#endif
encrypt.cpp
#include <iostream>
#include "encrypt.h"
const size_t num{4};
// Replace each digit with the result of adding 7 to the digit and getting the remainder after dividing the new value by 10.
void encrypt(int arr[::num]) {
for (int k = 0; k < ::num; k++) {
arr[k] = (arr[k] + 7) % 10;
}
}
// Then swap the first digit with the third, and swap the second digit with the fourth.
void swap(int arr[::num]) {
int box[1] = {0};
for (int k = 0; k < (::num / 2); k++) {
box[1] = arr[k];
arr[k] = arr[k+2];
arr[k+2] = box[1];
}
box[1] = arr[0];
arr[0] = arr[2];
arr[2] = box[1];
box[1] = arr[1];
arr[1] = arr[3];
arr[3] = box[1];
}
// Then print the encrypted integer.
void printArr(int arr[::num]) {
for (int k = 0; k < ::num; k++) {
std::cout << arr[k] << " ";
}
}
The swap function has some problems in the algorithm probably because I tried printing the for loop output and I get just one random value, while the bit manually written is working fine. I don't know why.
This program clearly doesn't work because every time I pass the array to a function it is always the one declared in main and not an array modified by the functions. I tried pointing to the array passed to the functions but I think I messed it up because I got a bunch of errors - moreover, I've read that taking the address of a built-in array to pass it to a function is not needed and I can simply pass the built-in array’s name because the called function can modify all the elements of an array in the caller, unless the function precedes the corresponding built-in array parameter with const to indicate that the elements should not be modified. But I don't get why in my program it doesn't work.
Thanks in advance for anyone who would take their time to help me out, I really appreciate it.
An array can't be passed to a function by value, only by reference or pointer. In your case, a parameter like int a[] is really just syntax sugar for a pointer int *a. But you are not actually calling the functions with a pointer, you are indexing into arrEncrypt and passing an individual int instead (using an index that is out of range!).
Get rid of the array indexing at the call sites. An array decays into a pointer to its 1st element when it is referred to by just its name.
Also, such parameters don't carry size information, so you have to pass the array size explicitly in a separate parameter.
Try this instead:
#include "encrypt.h"
const size_t size{4};
int main () {
int arrEncrypt[size] = {1, 2, 3, 4};
swap(arrEncrypt, size);
encrypt(arrEncrypt, size);
printArr(arrEncrypt, size);
}
encrypt.h
#ifndef ENCRYPT_H
#define ENCRYPT_H
void encrypt(int a[], int size);
void swap(int a[], int size);
void printArr(int a[], int size);
#endif
encrypt.cpp
#include <iostream>
#include <stdexcept>
#include "encrypt.h"
// Replace each digit with the result of adding 7 to the digit and getting the remainder after dividing the new value by 10.
void encrypt(int arr[], int size) {
if (!arr || size < 0) throw invalid_argument("");
for (int k = 0; k < size; k++) {
arr[k] = (arr[k] + 7) % 10;
}
}
// Then swap the first digit with the third, and swap the second digit with the fourth.
void swap(int arr[], int size) {
if (!arr || size < 4) throw invalid_argument("");
int box;
for (int k = 0; k < (size / 2); k++) {
box = arr[k];
arr[k] = arr[k+2];
arr[k+2] = box;
}
box = arr[0];
arr[0] = arr[2];
arr[2] = box;
box = arr[1];
arr[1] = arr[3];
arr[3] = box;
}
// Then print the encrypted integer.
void printArr(int arr[], int size) {
if (!arr) throw invalid_argument("");
for (int k = 0; k < size; k++) {
std::cout << arr[k] << " ";
}
}
That being said, consider using std::vector instead, eg:
#include "encrypt.h"
int main () {
std::vector<int> arrEncrypt = {1, 2, 3, 4};
swap(arrEncrypt);
encrypt(arrEncrypt);
printArr(arrEncrypt);
}
encrypt.h
#ifndef ENCRYPT_H
#define ENCRYPT_H
#include <vector>
void encrypt(std::vector<int> &a);
void swap(std::vector<int> &a);
void printArr(const std::vector<int> &a);
#endif
encrypt.cpp
#include <iostream>
#include <utility>
#include <stdexcept>
#include "encrypt.h"
// Replace each digit with the result of adding 7 to the digit and getting the remainder after dividing the new value by 10.
void encrypt(std::vector<int> &arr) {
for (size_t k = 0; k < arr.size(); k++) {
arr[k] = (arr[k] + 7) % 10;
}
}
// Then swap the first digit with the third, and swap the second digit with the fourth.
void swap(std::vector<int> &arr) {
if (arr.size() < 4) throw invalid_argument("");
for (size_t k = 0; k < (a.size() / 2); k++) {
std::swap(arr[k], arr[k+2]);
}
std::swap(arr[0], arr[2]);
std::swap(arr[1], arr[3]);
}
// Then print the encrypted integer.
void printArr(const std::vector<int> &arr) {
for (size_t k = 0; k < arr.size(); k++) {
std::cout << arr[k] << " ";
}
}
Or std::array, eg:
#include "encrypt.h"
int main () {
std::array<int, size> arrEncrypt = {1, 2, 3, 4};
swap(arrEncrypt);
encrypt(arrEncrypt);
printArr(arrEncrypt);
}
encrypt.h
#ifndef ENCRYPT_H
#define ENCRYPT_H
#include <array>
#include <iostream>
#include <utility>
// Replace each digit with the result of adding 7 to the digit and getting the remainder after dividing the new value by 10.
template<typename T, size_t N>
void encrypt(std::array<T, N> &arr) {
for (size_t k = 0; k < N; k++) {
arr[k] = (arr[k] + 7) % 10;
}
}
// Then swap the first digit with the third, and swap the second digit with the fourth.
template<typename T, size_t N>
void swap(std::array<T, N> &arr) {
if (N < 4) throw invalid_argument("");
for (size_t k = 0; k < (N / 2); k++) {
std::swap(arr[k], arr[k+2]);
}
std::swap(arr[0], arr[2]);
std::swap(arr[1], arr[3]);
}
// Then print the encrypted integer.
template<typename T, size_t N>
void printArr(const std::array<T, N> &arr) {
for (size_t k = 0; k < N; k++) {
std::cout << arr[k] << " ";
}
}
#endif
The arguments arrEncrypt[size] in the function main() is bad because
It is out-of-range because the array arrEncrypt has only size elements and its valid indice are 0 to size-1.
The functions are expecting pointers, but an integer is passed.
The element box[1] used in the function swap() is out-of-range because the array box has only one element. Since it looks you are using only the element box[1] from the array box, you should stop using array here and instead of that you should use simple variable box.
In the function main(), you should pass the array (or a pointer to the first element of the array converted from the array) to the function:
int main () {
int arrEncrypt[size] = {1, 2, 3, 4};
swap(arrEncrypt);
encrypt(arrEncrypt);
printArr(arrEncrypt);
}
In the function swap(), you should stop using out-of-range "element":
void swap(int arr[::num]) {
int box = 0;
for (int k = 0; k < (::num / 2); k++) {
box = arr[k];
arr[k] = arr[k+2];
arr[k+2] = box;
}
box = arr[0];
arr[0] = arr[2];
arr[2] = box;
box = arr[1];
arr[1] = arr[3];
arr[3] = box;
}
For instance I have an array:
array[5] = {-3, 4, 5, 1, -2}
I am trying to sort it as {1, -2, -3, 4, 5}.
I tried doing bubble sort with abs value but that did not work.
There are plenty of ways to sort like that, and one of the most easiest, in fact, is to use, the std::sort() function from <algorithm>... (Just remember to set up your compiler for C++11 or above)
Create an advanced_absolute function (As pointed out in comments):
constexpr auto min_abs(int x)
{
return x < 0 ? signed(unsigned(-1)) - signed(unsigned(x) + 1U) : x;
}
And sort:
std::sort(std::begin(array), std::end(array), [](int const num1, int const num2) -> bool
{
return (num1 == INT_MIN ? min_abs(num1) : std::abs(num1)) < (num2 == INT_MIN ? min_abs(num2) : std::abs(num2));
});
and include these at the top...
#include <algorithm>
#include <iterator> // This is already included the <iostream> and other headers dependent on this header...
You can use the following code:
#include <stdio.h>
#include <stdlib.h>
#define size 5
void swap(int *xp, int *yp)
{
int temp = *xp;
*xp = *yp;
*yp = temp;
}
void bubbleSort(int arr[], int n)
{
int i, j;
for (i = 0; i < n-1; i++)
for (j = 0; j < n-i-1; j++)
if (abs(arr[j]) > abs(arr[j+1]))
swap(&arr[j], &arr[j+1]);
}
int main()
{
int array[size] = {-3, 4, 5, 1, -2};
bubbleSort(array, size);
for (int i=0; i<size; i++)
{
printf("%d ", array[i]);
}
return 0;
}
It can give you a better understanding of how things would work at fine grain level.
Bubblesort function in C is taken from here
Following ruk's idea, but simplified:
#include <algorithm>
#include <iterator>
#include <cstdlib>
// ...
std::sort(std::begin(array), std::end(array), [](int const num1, int const num2)
{
// Don't call std::abs(INT_MIN), just return the correct value directly.
if (num1==INT_MIN) return false; // First, because INT_MIN<INT_MIN==false
if (num2==INT_MIN) return true;
// If we get here, neither value is INT_MIN so we can safely call std::abs
return (std::abs(num1) < std::abs(num2));
});
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.
I have question regarding the code I found on Internet which uses a deque for finding the max of the element --
#include <iostream>
#include <deque>
using namespace std;
void test(int arr[], int n)
{
std::deque<int> Qi(n);
int i;
for (i = 0; i < n; ++i)
{
while ( (!Qi.empty()) && arr[i] >= arr[Qi.back()])
Qi.pop_back(); // Remove from rear
Qi.push_back(i);
}
cout << arr[Qi.front()];
}
// Driver program to test above functions
int main()
{
int arr[] = {12, 1, 78, 90, 57, 89, 56};
int n = sizeof(arr)/sizeof(arr[0]);
test(arr, n);
return 0;
}
My Question is how is Qi.front() giving the right index when I have not done any Qi.push_front() ?
But the following code gives me a 0
void test(int arr[], int n)
{
std::deque<int> Qi(n);
int i;
for (i = 0; i < n; ++i)
{
Qi.push_back(i);
}
cout << arr[Qi.front()];
}
Sorry If I am sounding stupid .. New to deques ...
Thanks
std::deque<int> Qi(n); creates a deque with n elements, all zero. The push_back operations add further elements at the back, so afterwards the deque has 2 * n elements. Qi.front() is identical to Qi[0].
All this is well-documented, e.g. here.
I'm trying to write quicksort and understand the algorithm. I understand the 3 basic principles of quick sort
The element a[i] is in its final place in the array for some i.
None of the elements in a[l], a[i1] is greater than a[i].
None of the elemtns in a[i+1],..., a[r] is less than a[i].
I think I'm missing something about this algorithm. Any guidance much appreciated.
My first question is l and r, those are the min and max of the array? or is it any place within the left and right side of the array.
#include <iostream>
using namespace std;
void quicksort(int a[], int l , int r);
int partition(int a[], int l, int r);
void exchange(int a[], int i, int j);
int main()
{
const int MAX_ARRAY = 9;
// Quicksort
// Array of integers
int numArray[MAX_ARRAY] = {25,10,25,34,38,7,6,43,56};
for ( int i = 0 ; i < MAX_ARRAY ; i++)
{
cout << numArray[i] << endl;
}
quicksort(numArray, 4, 7);
// Call quicksort
for ( int i = 0 ; i < MAX_ARRAY ; i++)
{
cout << numArray[i]<< endl;
}
system("pause");
return 0;
}
void quicksort(int a[], int l , int r)
{
//
if (r <= l) {return;} // The max position and least position are now overlapping
int i = partition(a, l, r); // send the array and the two positions to partition
// i gives me the next position
quicksort(a,l,i-1); // sort left side
quicksort(a,i+1,r); // sort right side
}
int partition(int a[], int l, int r)
{
//Declarations
int i = l-1, j = r; int v = a[r];
for(;;) // Infinite ForLoop
{
// go through till you find a value in the array that is less than v = our pivot
while(a[++i] < v) ;
while (v < a[--j]) if (j == 1) break; // THis condition is to go thorugh and check for a number that is larger than v then if j is not at 1 then we break
if ( i >= j) break; // Overlap array
exchange(a, i , j); // swap the values
}
exchange(a,i,j); // swap the values
return i;
}
void exchange(int a[], int i, int j )
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
My first question is l and r, those are the min and max of the array? or is it any place within the left and right side of the array.
No, those are the left and right borders of the current sub-array being sorted. I have no idea why you invoke method with parameters 4 and 7: it means none of the elements before 4-th or after 7-th will be sorted.
first, quicksort(numArray, 4, 7); should be quicksort(numArray, 0, 8);
second, to make it a little bit faster, you can set a cutoff number like 10 on which you switch to insertion sort. Insertion sort is faster than quick sort for small input.