-2

I have to solve a problem that consist of sorting a list of number in c++. The condition is :

  1. the positive, and 0 must be sorted ascending
  2. negative numbers- descending

if A = {4,-8,7,-6,0,-7,5} the at the final B = {0,4,5,7,-6,-7,-8 }

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    int i,j,n,A[100],B[100],A_nenegative[100],A_negative[100],aux,m=0,k=0;
    cout<<"max elements"; cin>>n;
    cout<<"elements are"<<endl;
    for(i=0;i<n;i++)
    {
    cin>>A[i];
    }
  for(i=0;i<n;i++)
  for(j=i+1;j<n;j++)
  if(A[i]>A[j])
  {
    aux=A[i];
    A[i]=A[j];
    A[j]=aux;
  }
  for(i = 0; i< n; i++)
    if(A[i]>=0) {
    A_nenegative[i]=A[i];
    B[i]=A_nenegative[i];
    k++;
  }
    for(i=0;i<n;i++)
  for(j=i+1;j<n;j++)
  if(A[i]<A[j])
  {
    aux=A[i];
    A[i]=A[j];
    A[j]=aux;
  }
    for(i=0;i<n;i++)
    if(A[i]<0)
    {
    A_negative[i]=A[i];
    m++;
    }

}

here is where i stopped. I sort positive numbers in A_nenegative and negative numbers in A_negative. So the question is how can attribute to B first- A_nenegative and then A_negative. I try after sorting positive numbers immediate to attribute to B , something like that:

  for(i = 0; i< n; i++)
    if(A[i]>=0) {
    A_nenegative[i]=A[i];
    B[i]=A_nenegative[i];
    k++;
  }

But i don't know what to do next

Cristyan
  • 17
  • 5
  • 3
    So basically you want to [partition](https://en.cppreference.com/w/cpp/algorithm/partition) the original array into negative and non-negative numbers. Then [sort](https://en.cppreference.com/w/cpp/algorithm/sort) each partition, the negative part using absolute values. And then append the two partitions into a new ["array"](https://en.cppreference.com/w/cpp/container/vector). – Some programmer dude Feb 27 '19 at 12:54
  • Is this homework? – z32a7ul Feb 27 '19 at 13:04

5 Answers5

5

Just use predicate.

std::sort(std::begin(a), std::end(a), [](int a, int b) {
        if(a >= 0) {
            if(b >= 0) return a < b;
            else return true;
        }
        else {
            if(b >= 0) return false;
            else return a > b;
        }
    });

Predicate returns true if a needs to go before b in array, false - otherwise.
So, if a >= 0 and b >= 0 --- we check whether a < b (sort non-negative values in ascending order).
if a >= 0 and b < 0 --- then b needs to go after a, because all negative values go after non-negative.
if a < 0 and b >= 0 --- then b needs to go before a.
if a < 0 and b < 0 --- check whether a > b (to sort in descending order).

Daniel Z.
  • 389
  • 2
  • 10
3

Use appropriate predicate with std::sort:

std::sort(std::begin(A), std::end(A), [](int lhs, int rhs) {
    auto score = [](int n){ return std::make_tuple(n < 0, std::abs(n)); }
    return score(lhs) < score(rhs);
});
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • please stay away of std::tuple as is not standard layout. +1 for the conciseness! – KostasRim Feb 27 '19 at 13:15
  • 1
    @KostasRim: Which is the problem with non-standard layout types ? – Jarod42 Feb 27 '19 at 13:21
  • many beginning with that it violates the memory model. Please refer: https://stackoverflow.com/questions/7160901/why-is-c11s-pod-standard-layout-definition-the-way-it-is – KostasRim Feb 27 '19 at 13:30
  • @KostasRim is it possible that you misunderstood something? Standard layout types is a rather restricted set of types. If C++ would allow only those we would loose a lot for no good reason – 463035818_is_not_an_ai Feb 27 '19 at 13:31
  • @user463035818 potentially? But if breaking compatibility is one of your goals then feel free to use `non standard layout`. From my experience, its breaks more than its worth. – KostasRim Feb 27 '19 at 13:33
  • 3
    @KostasRim it breaks nothing, standard layout is required for very special cases only. For example `struct foo { int x; private: int y; };` is not standard layout but using it wont break anything unless you do something that is only allowed for standard layout types... – 463035818_is_not_an_ai Feb 27 '19 at 13:35
  • 1
    @user463035818 Your example is `trivial layout` which is different than `non standard layout` :) I am a little biased here because I have seen non standard layout causing havoc in compiler dependent code but yet again I would agree to your point that if you need the feature you should use it. All in all, cppcoreguidelines do not mention much about layout (except from potentially p.9) so I guess from my side there is nothing to argue about. Thanks for the information and yes there was some misunderstanding from my side -- keep up the insightful replies :) – KostasRim Feb 27 '19 at 14:18
1

I like expressive C++:

#include <array>
#include <iostream>

int main() {
  auto a = std::array<int, 7>{4, -8, 7, -6, 0, -7, 5};

  auto it = std::partition(std::begin(a), std::end(a),
                           [](const int val) noexcept { return val >= 0; });

  std::sort(begin(a), it);
  std::sort(it, std::end(a), std::greater<int>());

  for(const auto& elem : a) {
    std::cout << elem << "\n";
  }

}

KostasRim
  • 2,053
  • 1
  • 16
  • 32
1
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    int n,A[100],B[100],Merge_Array[200],aux;
    cout<<"max elements"; cin>>n;
    cout<<"elements are"<<endl;
    int temp,index_A=0,index_B=0;
    for(int i=0;i<n;i++)
    {
        cin>>temp;
        if(temp>=0){
            A[index_A++]=temp; //One array for positive
        }
        else{
            B[index_B++]=temp; //Another one for negative
        }
    }
    //Sort positive in ascending
    for(int i=0;i<index_A;i++)
    {
        for(int j=i+1;j<index_A;j++)
            if(A[i]>A[j])
             {
                    aux=A[i];
                    A[i]=A[j];
                    A[j]=aux;
            }
    }
     //Sort negative in descending
    for(int i=0;i<index_B;i++)
        for(int j=i+1;j<index_B;j++)
            if(B[i]<B[j])
             {
                    aux=B[i];
                    B[i]=B[j];
                    B[j]=aux;
            }
    //Merge A and B
    for(int i=0;i<index_A;i++){
        Merge_Array[i]=A[i];
    }
    for(int i=index_A,k=0;i<n;i++,k++){
        Merge_Array[i]=B[k];
    }
    //Print the Merged Array
    for(int i=0;i<n;i++){
        cout<<Merge_Array[i];
    }
}

Hi Cristyan. All others have answered your question. But I still see you are following C type coding for C++. In C++ you are free to declare your variables anywhere not necessarily at the start of the function.

Eg:- for(int i=0;;) is feasible.

Moreover, you have not used dynamic arrays. I know for starters using new and delete can be intimidating. But instead, you can use vectors which offers various functionalities, so pointing you to that vectors.

Justice_Lords
  • 949
  • 5
  • 14
0

I would iterate over your input and put every value >= 0 into an array POS and any value < 0 into an array NEG.

Then sort both array ascending and separately and use the absolute value to compare the elements (no effect in POS but required for NEG).

For last push NEG to POS and you have it.

Think thats simple and straight forward.

chris01
  • 10,921
  • 9
  • 54
  • 93