简体   繁体   中英

Please explain this function

The code below is used to sort the int array in ascending or descending order

//codes borrowed from learncpp.com
#include<iostream>
#include<algorithm>
using namespace std;
void SelectionSort(int *anArray, int nSize, bool(*pComparison)(int, int)) {
    for(int iii=0; iii<nSize; iii++) {
        int nCurrent = iii;
        for(int jjj=iii+1; jjj<nSize; jjj++) {
            if(pComparison(anArray[nCurrent], anArray[jjj]))
                nCurrent = jjj;
            }
        swap(anArray[nCurrent], anArray[iii]);
    }
}
bool Ascending(int nX, int nY) {
    return nY>nX;
}
bool Descending(int nX, int nY) {
    return nY<nX;
}
bool EvensFirst(int nX, int nY) {
    if((nX%2)&&!(nY%2))
        return false;
    if(!(nX%2)&&(nY%2))
        return true;
    return Ascending(nX, nY);
}
void PrintArray(int *pArray, int nSize) {
    for(int kkk=0; kkk<nSize; kkk++)
        cout << pArray[kkk] << " ";
    cout << endl;
}
int main() {
    int anArray[9] = {3, 5, 1, 8, 9, 4, 6, 2, 7};
    SelectionSort(anArray, 9, EvensFirst);
    PrintArray(anArray, 9);
    return 0;
}

Printing Result is 9 7 5 3 1 8 6 4 2 instead of 2 4 6 8 1 3 5 7 9

Can anyone here please explain how does the bool function EvensFirst work?

The main thing in this program is the use of funtion pointer. bool(*pComparison)(int, int) is a pointer to a function which returns bool type values and takes as parameter 2 int values. You can check the different outputs SelectionSort(anArray, 9, Ascending); or SelectionSort(anArray, 9, Descending); (if you have coded the selection sort function correctly).

Note: Based on different function pointer this general sorting routine will give different outputs. And the rest of the routine is basic sorting routine swapping the values of min or max to current element.

bool EvensFirst(int nX, int nY) {
    if((nX%2)&&!(nY%2)) //if nX is odd and nY is even the 
//nY should be in first position. So to change the order return false
        return false;
    if(!(nX%2)&&(nY%2))//if nX is even and nY is odd the 
//nX should be in first position. So to retain the order return true
        return true;
    return Ascending(nX, nY);// both even or both odd return the ascending function's output.
}

If nx is even the if we divide it by 2 it will give remainder of 0. For example, 12 12%2=0

34%2=0

9%2=1 ----> that's why this is odd.

Every odd number can be written in the form 2m+1 Now if we divide this number by 2 we will get remainder of 1 as 1st part is giving remainder 0.

Even number the explanation is same even number is represented by 2m .So when divided by 2 it will give remainder 0.

if((nX%2)&&!(nY%2))  
       return false;
if nX is even it nX%2=0 and if nY is odd then ny%2=1
So expressin becomes
if(0 && 1)-->which evaluates to false and go to next condition. 

Few wxamples to clarify your idea--

Check if x is even

if(x%2==0) 
  //x is even.

Also can be written as
if(!x%2)
  //x is even.

Check if x is odd

 if(x%2==1)
      // x is odd
    Also can be written as

    if(x%2)
      // x is odd.

Check if x and y are both even

   if(!x%2 && !y%2)
    //both even

check if either of one is even

 if(!x%2 || !y%2)
    //either of them is even

The operator modulo % returns the remainder of the division of its operands. It can be used to check if a number is even or odd, because if the remainder of x/2 is 0 it means that x is even. That means that if x%2=0 than x is even, else it is odd.


Here's how EvensFirst works :

bool EvensFirst(int nX, int nY) {
    if((nX%2)&&!(nY%2)) //if nX is even and nY is odd
        return false;   //returns false
    if(!(nX%2)&&(nY%2)) //if nX is odd and nY is even
        return true;    //returns true
    //if they are both odd or even returns the result of ascending
    return Ascending(nX, nY); //true if nY > nX 
}

Here's how you use EvensFirst :

void SelectionSort(int *anArray, int nSize, bool(*pComparison)(int, int) {
    for(int iii=0; iii<nSize; iii++) {   //for each number in the array
        int nCurrent = iii;
        for(int jjj=iii+1; jjj<nSize; jjj++) {  //for each following elemnt
            if(pComparison(anArray[nCurrent], anArray[jjj])) //compare the two elements
                nCurrent = jjj; 
            }
        swap(anArray[nCurrent], anArray[jjj]); //and switch their positions if they are in the wrong order
    }
}

Quote from The Standard:

Tthe binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined; otherwise (a/b)*b + a%b is equal to a. If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined (74)

(74) According to work underway toward the revision of ISO C, the preferred algorithm for integer division follows the rules defined in the ISO Fortran standard, ISO/IEC 1539:1991, in which the quotient is always rounded toward zero.

Example:

11 % 3 = 2 , because 11 = 3*3 + 2

Now, operation modulo-2 can give us only two possible results: 0 or 1. Also:

1) For any given even number N , N % 2 will always give 0. That's because even numbers are by definition multiplications of 2.

2) For any given odd number M , M % 2 will always give 1. That's because any even number can be defined as 2K + 1 , where K is an N0 (natural number or zero).

Because of the above, we can use x % 2 expression as logical condition, because in C/C++ "0 is false, everything other is true".

So:

if(x%2)
{
  //x%2 != 0, which means x%2 = 1, which means x is an odd number
}
else
{
  //x%2 == 0, which means x is an even number
}

Now, let's go back to your EvensFirst function:

bool EvensFirst(int nX, int nY)
{
    if((nX%2)&&!(nY%2))
        return false;
    if(!(nX%2)&&(nY%2))
        return true;
    return Ascending(nX, nY);
}

This function accepts two arguments: nX and nY and it returns true if nX should be placed before nY (false otherwise). First, it checks the condition (nX%2)&&!(nY%2) . This condition essentially means:

"Check, if nX is an odd number and nY is an even number."

If it evaluates to true, function returns false - evens are taken first, so nY should be placed before nX ).

Then, it checks for the second condition: !(nX%2)&&(nY%2) , which means:

"Check, if nX is an even number and nY is an odd number."

If it evaluates to true, function returns true - evens are taken first, so nX should be placed before nY .

If both these conditions evaluated to false, it means that either both of them are odd or both are evens. In this case, functions compares them using "Ascending" comparison - lower number will be taken first.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM