Sort descending for negative numbers, and ascending for positive ones in same array

I had an interesting question: Given an array that contains unique integers. Write a function that sorts the array such that the negative numbers appear before the positive ones. The negative numbers are ordered in descending order, and the positive numbers in ascending order. And no helper arrays can be used - meaning that it all needs to be sorted "in-place"

Example:

int arr[] = {12, 56, -9, 4, -8, 46, 3, 7, -16, 78, 69};

would result in -8 -9 -16 3 4 7 12 46 56 69 78

I was able to write a simple program that first sorts everything in ascending order, in addition to keeping a tally of the quantity negative numbers. Afterward, I swap the first and last position of negative numbers and proceed till the end of all them... and lastly, I return the array.

Is there a more elaborate/efficient way of doing this.

Here is my code currently:

int *negDescPosAsc(int *arr, int size)
{
    //treat negative numbers differently than positive numbers
    //sort negative numbers in descending order
    //sort positive numbers in ascending order
    //return the sorted array
    int negCount = 0;
    for (int i = 0; i < size; i++)
    {

        //do normal sort then reverse the negatives
        for (int j = 0; j < size - 1; j++)
        {
            if (*(arr + j) > *(arr + j + 1))
            {
                if (*(arr + j) < 0)
                {
                    negCount++;
                }
                int temp = *(arr + j);
                *(arr + j) = *(arr + j + 1);
                *(arr + j + 1) = temp;
            }
        }
    }

    int i = 0;
    while (negCount > 0)
    {
        int temp = *(arr + i); //store the value of the current element
        *(arr + i) = *(arr + negCount); //replace the current element with the last element
        *(arr + negCount) = temp; //replace the last element with the current element
        negCount--; //decrement the negative count
        i++; //increment the index
    }
    

    return arr;
}

You can change the default compare function to suite this problem. Then you can use qsort, or std::sort or your own sorting method. I'll demonstrate with std::sort:

    std::vector<int> items = {12, 56, -9, 4, -8, 46, 3, 7, -16, 78, 69};
    auto comp = [](int A, int B) { return (A < 0 && B < 0) ? B < A : A < B; };
    std::sort(items.begin(), items.end(), comp);
    for (auto item : items) cout << item << " ";
    cout << endl;

The output is: -8 -9 -16 3 4 7 12 46 56 69 78

Here we check if both the numbers are negative. If they are, we reverse the comparison.

C equivalent:

int compare(const void *_A, const void *_B)
{
    int A = *(const int *)_A, B = *(const int *)_B;
    return (A < 0 && B < 0) ? B > A : A > B;
}

int main()
{
    int count = 11;
    int items[] = {12, 56, -9, 4, -8, 46, 3, 7, -16, 78, 69};
    qsort(items, count, sizeof(int), compare);
    for (int i = 0; i < count; ++i) printf("%i ", items[i]);
    printf("\n");
}

Yes, there's a simpler and more efficient way, is to use the qsort() standard library function:

#include <stdio.h>
#include <stdlib.h>

int compare(const void *ap, const void *bp)
{
    const int *aref = ap, *bref = bp, a = *aref, b = *bref;

    /* negative numbers go first. */
    if (a < 0 && b >= 0) return -1;
    if (a >= 0 && b < 0) return +1;

    /* then the absolute value of number wins. */
    return abs(a) - abs(b);
}

int main()
{
    int arr[] = {12, 56, -9, 4, -8, 46, 3, 7, -16, 78, 69};
    size_t arr_sz = sizeof arr / sizeof arr[0];

    qsort(arr, arr_sz, sizeof *arr, compare);

    char *sep ="";
    for (int i = 0; i < arr_sz; ++i) {
        printf("%s%d", sep, arr[i]);
        sep = ", ";
    }
    printf("\n");
}

That produces:

$ a.out
-8, -9, -16, 3, 4, 7, 12, 46, 56, 69, 78
$ _