sorting arrays in C++ [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
1.
const int nSize=6;
int anArray[nSize]={ 30, 60, 20, 50, 40, 10 };
for(int nStartIndex=0;nStartIndex<nSize;nStartIndex++)
{
int nSmallestIndex=nStartIndex;
for(int nCurrentIndex=nStartIndex+1;nCurrentIndex<nSize;nCurrentIndex++)
{
if(anArray[nCurrentIndex]<anArray[nStartIndex])
nSmallestIndex=nCurrentIndex;
}
swap(anArray[nStartIndex],anArray[nSmallestIndex]);
}
2.
const int nSize=6;
int anArray[nSize]={ 30, 60, 20, 50, 40, 10 };
for(int nStartIndex=0;nStartIndex<nSize;nStartIndex++)
{
int nSmallestIndex=nStartIndex;
for(int nCurrentIndex=nStartIndex+1;nCurrentIndex<nSize;nCurrentIndex++)
{
if(anArray[nCurrentIndex]<anArray[nSmallestIndex])
nSmallestIndex=nCurrentIndex;
}
swap(anArray[nStartIndex],anArray[nSmallestIndex]);
}
why do they give different results although nSmallestIndex equals to nStartIndex?
first code results {10,30,20,40,50,60}
second code results {10,20,30,40,50,60}

The logic in code sampe 1 is wrong and that's why it gives the wrong answer. In your second loop, you want to find the smallest element from [nStartIndex, nSize). But you only compare the current one with anArray[nStartIndex]. At the end you get nSmallestIndex equal to the last element smaller than anArray[nStartIndex].
For code sample two, the logic is right. You save the current smallest index in nSmallestIndex and use the updated version to compare in the if statement,
if(anArray[nCurrentIndex]<anArray[nSmallestIndex])
btw, the sorting method in this code is O(N^2) which is not good generally. It is also noted by others here C++ STL has facilities to do this better and portable.

There is a wrong condition inside your inner loop in the first example: if(anArray[nCurrentIndex]<anArray[nStartIndex]). Use nSmallestIndex instead of nStartIndex.
But in C++ you can do it in one line:
std::sort( anArray, anArray + nSize, std::less<int>() );
If you want to do it in C just use this code:
const int nSize=6;
int anArray[nSize]={ 30, 60, 20, 50, 40, 10 };
int Compare(const void* a ,const void* b)
{
return ( *(int*)a > *(int*)b ) ? 1 : ( ( *(int*)a < *(int*)b ) ? -1 : 0 );
}
...
qsort( anArray, nSize, sizeof( int ), &Compare );

Because nSmallestIndex equals to nStartIndex only at the begining of the second for, after some iteration nSmallestIndex can change but nSmallestIndex won't change because there are not the same variable

The idea behind selection sort is to find the smallest/largest element and position it to a proper index
Clearly your first algo's inner for loop
for(int nCurrentIndex=nStartIndex+1;nCurrentIndex<nSize;nCurrentIndex++)
{
if(anArray[nCurrentIndex]<anArray[nStartIndex])
nSmallestIndex=nCurrentIndex;
}
Never compares with new smaller index, it just compares the iterating number with original smaller value.
Whereas in 2nd algo's inner loop
for(int nCurrentIndex=nStartIndex+1;nCurrentIndex<nSize;nCurrentIndex++)
{
if(anArray[nCurrentIndex]<anArray[nSmallestIndex])
nSmallestIndex=nCurrentIndex;
}
It updates the smallestIndex and hence correctly find the smallest value for a swap.

why do they give different results although nSmallestIndex equals to nStartIndex?
The only difference betweent the two pieces of code:
< if(anArray[nCurrentIndex]<anArray[nStartIndex])
---
> if(anArray[nCurrentIndex]<anArray[nSmallestIndex])
So the conditional is different on nSmallestIndex and nStartIndex. But these values are not the same in the two pieces of code:
See the lines:
if(anArray[nCurrentIndex]<anArray[<VALUE>])
nSmallestIndex=nCurrentIndex;
// ^^^^^^^^^^^^^^^ Assignment changes the value.

Related

How to handle this odd and even bubble sorting error? [closed]

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 last month.
Improve this question
I wanna ask why the even side of the odd&even bubble sort will raise a zsh:abort error in VScode? Is it because it is out of range? If so, does that mean that I have to precisely modify the range? Thank you!
#include <iostream>
using namespace std;
int main()
{
int a[10];
for (int i=0;i<10;i++)
{
cin>>a[i];
}
//First, sort odd and even numbers
int l=0,r=9;//point to the two ends of the array
while (l<=r)
{
bool leftIsOdd=a[l]%2==1;
bool rightIsEven=a[r]%2==0;
//move the two pointers from ends to middle
if (leftIsOdd)
{
l++;
}
else if (rightIsEven)
{
r--;
}
//since it's a symmetric array, with 5 odd and 5 even, we can swap when both sides get stuck
//Q:If we have 4 odd numbers and 6 even numbers, is the approach OK?
else if (!leftIsOdd && !rightIsEven)
{
int temp=a[l];
a[l]=a[r];
a[r]=temp;
}
}
//perform bubble sort for left odd part
int start=0,end=l;
for (int i=start; i<end-1;i++)
{
for (int j=start+1;j<end-i;j++)
{
if (a[j-1]>a[j])
{
int temp=a[j];
a[j]=a[j-1];
a[j-1]=temp;
}
}
}
//now bubble the right even side
start=l,end=10;
for (int i=start; i<end-1;i++)
{
for (int j=start+1;j<start+end-i;j++)
# # # //Why j<start+end-1 would produce error?
{
if (a[j-1]>a[j])
{
int temp=a[j];
a[j]=a[j-1];
a[j-1]=temp;
}
}
}
for (int i=0;i<10;i++)
{
cout<<a[i]<<' ';
}
return 0;
}
I tried putting index j out of the expected range, and received zsh:abort error.
If you initialize the input array a with 10,9,8,7,6,5,4,3,2,1 as you mentioned then when you reach the "// now bubble the right even side" loop you will initialize start to 5 and end to 10. If you write j<start+end-1 then this will allow j to be as large as 13. (i.e. j must be less than 14). You will then try to access a[13], but a has only 10 elements. Therefore, if you are lucky, you will get some kind of memory access error when you run the program and it will crash.
I don't know why you want to replace the expression j<start+end-i (which seems to work, with the expression j<start+end-1 which causes a crash.
You could probably make the crash happen a lot easier just by including the line a[13]=0; after you declare and initialize a.
When you are using arrays it is your responsibility to ensure that all array accesses are valid. When you ask "does that mean that I have to precisely modify the range" the answer is "yes, definitely!"

How to set part of the array to be the same value in C++?

I would like to set a integer array with the value of the first 100 elements to be 1 and the value of another 100 elements to be -1. I have seen the tutorial to set all the elements to be the same value only. How can I set some of the array elements to be the same value while the others have different values?
Since you have not posted any code, i presume that all you want is to set the 1st 100 elements to 1 and the next 100 to -1, for that you can use std::vector. All you need to do is to fill up the container with respect to your logic. In naive terms you can do the following :
#include <vector>
int main()
{
std::vector<int> intArray;
for( int i=0; i < 200; i++ )
{
if( i < 100 )
{
intArray.emplace_back(1);
}
else
{
intArray.emplace_back(-1);
}
}
}
Or you can also do this( as mentioned in comments ) :
int main ()
{
std::vector<int> intArray(200);
std::fill(intArray.begin(), intArray.end() - 100, 1);
std::fill(intArray.begin() + 100, intArray.end(), -1);
}
There is no function for partial filling of an array (or container).
Comment on the questions clearly show that std::fill is an option. You can also try memset(); all these fill the array completely.
You will have to make your own function if you want to fill partially. One of the implementations can be:
void fill(int *a,int size = 200){ fill(a,a+size/2,1); fill(a+size/2,a+size,0);} //Fills 100 with 0 and next 100 with 1.

FIXED Trying fix broken code on reversing an array

So I got this code sample that needs fixing. From what I can gather it takes an array, reverses it and then counts all the elements within it. Here is the code.
//-------------------------------------------------------------------
void ReverseTheArray( const short *pArrayStart, const int nArrayByteLength )
{
const short *pArrayEnd = (pArrayStart + nArrayByteLength);
while(pArrayStart != pArrayEnd)
{
short tmp = *pArrayStart;
*pArrayStart = *pArrayEnd;
*pArrayEnd = tmp;
pArrayStart++;
pArrayEnd--;
}
}
//-------------------------------------------------------------------
int CountTheArrayContents( const short *pArrayStart, int nNumEntries )
{
assert(nNumEntries-- > 0);
int nCount = 0;
for(unsigned uArrayIndex = nNumEntries; uArrayIndex >= 0; uArrayIndex--)
{
nCount += pArrayStart[uArrayIndex];
}
return nCount;
}
const short g_nSomeNumbers[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
//-------------------------------------------------------------------
int main()
{
short *pDataArray = new short[10];
memcpy(pDataArray, g_nSomeNumbers, sizeof(g_nSomeNumbers));
ReverseTheArray(pDataArray, 10*sizeof(short));
int nCount = CountTheArrayContents(pDataArray, 10);
printf("Sum total is %0.02f\n", nCount);
return 0;
}
I have ideas of what the problems are but can't seem to figure out a simple solution to the problem, one that doesn't require rewriting the entire code. If anyone can read this and see how the errors can be fixed it would be much appreciated.
I'm going to mention some things that I think are causing problems.
All the parameters and the pArrayEnd variable in the ReversTheArray() function are all const but are trying to be changed within the while loop, which is throwing an error. Should the const's be removed? Is there a reason const's would be used for this?
If the const's are remove a runtime error happens when trying to run the for loop in the CountTheArrayContents() function expressing an unhandled exception and saying "Access violation reading location 0x003DFFFE". Drawing a complete blank on that one.
Again any help on the code would be very much appreciated and I couldn't thank you guys enough.
PS. This is a challenge to create a reverse and accumulate function so I'm looking for a fix for the code and not a removal of the two functions. Thank you
PSS. Thanks to everyone who answered. I'm glad I did this (this being the first problem that I've posted about myself) and you've all been a huge help. I've got to say I've learnt alot.
Adding the actual length in bytes will add too many because pointer arithmetic is defined in terms of units of the size of the type pointed to. That is, pArrayEnd becomes &pDataArray[10 * sizeof(short)] instead of &pDataArray[10]. You don't need to multiply by sizeof(short) when calling the reversal function. Alternatively, you can divide nArrayByteLength by sizeof(short) when calculating the initial value of pArrayEnd.
The second issue is the fact that you only have 10 elements (0..9) allocated, meaning &pDataArray[10] would be one element beyond the array. The reversal function then tries to assign data to this unallocated area of memory, which can cause problems. The function should initialize pArrayEnd as shown, but immediately after, it should decrement pArrayEnd by 1. This way you won't be assigning to memory that might not belong to you. Beware of pArrayStart == pArrayEnd before you decrement pArrayEnd. An alternative test would be to ensure nArrayByteLength != 0.
Another problem is if the array has an even number of elements, and you try to do a reversal. If it does have an even number (like 10), pArrayStart will point to pDataArray[4], pArrayEnd will point to pDataArray[5], and after the data is assigned, pArrayStart++ will make pArrayStart point to pDataArray[5] and pArrayEnd-- point to pDataArray[4]. Then (6,3), (7,2), (8,1), (9,0), ... In other words, pArrayStart will never be equal to pArrayEnd in such a case. Instead, you should ensure that pArrayStart < pArrayEnd.
Hope this helps!
Also, any reason for not using std:: reverse? Just wondering.
Edit
The accumulation function can be rewritten as the following, which will avoid the issue with the assert macro while doing the same thing:
int CountTheArrayContents( const short *pArrayStart, int nNumEntries )
{
int count = 0;
assert(nNumEntries);
while (nNumEntries--)
count += pArrayStart[nNumEntries];
return count;
}
Hopefully count doesn't overflow.
If all you're trying to do is reverse the contents of the array and accumulate the result, std::reverse and std::accumulate will do the trick (per the suggestion by #chris). Here's an example, which maintains the dynamically allocated short*. A better solution would use std::vector or std::array.
#include <algorithm>
#include <numeric>
#include <stdio.h>
#include <memory.h>
const short g_nSomeNumbers[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
int main()
{
short *pDataArray = new short[10];
memcpy(pDataArray, g_nSomeNumbers, sizeof(g_nSomeNumbers));
std::reverse(pDataArray, pDataArray+10);
int nCount = std::accumulate(pDataArray, pDataArray+10, 0);
for( size_t i=0; i<10; ++i )
printf("%d ", pDataArray[i]);
printf("\n");
printf("Sum total is %d\n", nCount);
delete [] pDataArray;
return 0;
}
This prints
9 8 7 6 5 4 3 2 1 0
Sum total is 45

explanation of this recursive function [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 8 years ago.
Improve this question
hey there can anyone tell me how this function work ?!
for function and void function :
int countoccu(int array[],int value,int lower,int upper)
{
int counter=0;
if(lower==upper)
if (array[lower]==value)
return 1;
else
return 0;
else
counter = counter + countoccu(array, value, lower+1, upper);
if (array[lower]==value)
counter++;
return counter;
};
can anyone explain this for me
the output will be 3
void main()
{
int array[5]={3,7,3,3,11};
cout << countoccu(array,3,0,4) << endl;
}
It's a very stupid way to count number of value occurrences, for a given array, in given [upper, lower] range, using recurrence.
(If I understood it good.)
This looks like a homework, so I'll leave figuring it how it happens to you. My hint would be analyze code line by line, with a paper-sheet-pencil debugger.
int countoccu(int array[],int value,int lower,int upper){
int counter=0;
// Check if the end of the array is reached
if(lower==upper)
// Is the last element the "value" we are looking for?
if (array[lower]==value)
// Yes, so count it
return 1;
// No, don't count it
else return 0;
// Not the end of the array
else
// Move the position to the next item in the array and count it and all the following values that equals "value"
counter=counter+countoccu(array,value,lower+1,upper);
// Is the current item equal to the value being counted?
if (array[lower]==value)
// Yes, so count it
counter++;
return counter;
In your example you will get these calls:
countoccu(array,3,0,4) = 1+0+1+1+0 = 3
countoccu(array,3,1,4) = 0+1+1+0 = 2
countoccu(array,3,2,4) = 1+1+0 = 2
countoccu(array,3,3,4) = 1+0 = 1
countoccu(array,3,4,4) = 0 = 0
Though the function is written badly its principle of the work is simple. It checks whether the element with lower index is equal to the given value. If so it increases the count and adds the count for the array starting from the next index after index lower that is lower + 1 (calling itself at this time with lower + 1).
I would rewrite the function the following way
/* constexpr */ size_t count( const int a[], size_t n, int value )
{
return ( n == 0 ? 0 : ( ( a[0] == value ) + count( a + 1, n - 1, value ) ) );
}
I commented specifier constexpr because I think you do not know its meaning. So it may be omited.

Count the number of matching elements in two arrays C++

I'm working on a homework assignment for Comp Sci I, and I've tried literally everything I could find on the internet and in my textbook in an attempt to count the number of matching elements in two C++ arrays. I simply can't find a way to make my code count the number of matching elements in two arrays of the same size (same value, same position). For instance, if array1 has 5, 4, 3, 2, 1, and array2 has 1, 2, 3, 4, 5, there is one matching element, the 3. How can I get my code to perform this seemingly simple task?
Couldn't find an answer anywhere. My textbook only shows how to see if the arrays match exactly without counting the number of matches, and I haven't been able to find anyone else with this exact question for C++.
Here's my function so far:
int matchCounter(int lottery[5], int user[5], int matches, int SIZE)
{
int count = 0;
for (count < SIZE; count++;)
{
if (lottery[count] == user[count])
{
matches++;
}
}
return matches;
} // end matchCounter
SIZE is a constant that equals 5, by the way. It would seem that this should work, but every time I run the program, it displays 0 matches, even in there are some matches. If anyone could help me out, I would be forever in your debt. Seriously, there's got to be some incredibly simple thing I'm just not seeing. Thanks for you help in advance.
Your for statement is garbled. Try this:
int matchCounter(int lottery[5], int user[5], int matches, int SIZE)
{
for (int count = 0; count < SIZE; count++)
{
...
For reason why your program always fails: count++ is put in the position of the condition in the for loop, so every time this for loop is executed, count is evaluated and considered to be the condition, and then count is incremented by 1. However, every time count starts from 0 (as in int count = 0;), so the for loop actually never gets executed, and matches remain zero.
EDIT:
From your source code, you're not using your return value, which is also suggested by #jimhark. Change the function signature to:
int matchCounter(int lottery[5], int user[5], int SIZE)
And call with:
matches = matchCounter(lottery, user, 5);
Otherwise, your return value of the function matchCounter is ignored, while int matches only plays the role of a local variable in the function.
Read this about why the matches doesn't work: http://www.cs.utsa.edu/~wagner/CS2213/swap/swap.html (in a similar setting)
Since this is a homework, I will try to point the errors without giving the solution.
The form of a for loop is:
for (INIT; COND; STEP) {
BODY;
}
which is equivalent to:
INIT;
while (COND) {
BODY;
STEP;
}
The way you did, your INIT is count < SIZE, which doesn't do anything. Your "COND" is count++, which returns 0 on the first iteration. As you may know, 0 is false, in the context of a boolean. Therefore, your for loop body is not being executed at all.
Also, you should not pass matches as an argument. It should be a local variable initialized with 0.
Your may not be using your return value. Change sig to:
int matchCounter(int lottery[5], int user[5], int SIZE)
{
matches = 0;
And make sure your're calling with:
matches = matchCounter(lottery, user, 5);
If you need a running sum, use:
matches += matchCounter(lottery, user, 5);
In any case matchCounter doesn't care what running total is, so why pass it in?
Also you may need to sort the lists first.
Maybe this can help:
int matches=0;
for(int i=0;i<ARRAY.SIZE;i++) {
for(int j=0;j<ARRAY.SIZE;j++) {
if(arr1[i]==arr2[j]) {
matches++;
arr2[j]=NULL;
}
}
}