#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
/*
template <class T>
void afis(vector <T> &A) {
for (unsigned i = 0; i < A.size(); ++i)
cout<<A[i]<<' ';
system("pause");
}*/
#define RAD_BYTES 4
#define RAD_MAXB 256
inline int getByte(int x,int rad) { return x >> rad * 8 & 0xFF; }
inline int getByteS(int x,int rad) { int tmp = x >> rad * 8 & 0xFF; return tmp + (tmp < 0x80 ? 0x80 : -0x80); }
inline bool cond(int radix) { return radix == RAD_BYTES - 1; }
//#define getByte(x,rad) (x >> rad * 8 & RAD_MAXB - 1)
/*
inline int getByte(int x,int rad) {
int tmp = x >> rad * 8 & 255;
if(x > 0) tmp += 256;
return tmp;
}
*/
/*
inline uint getByteS(int x,uint rad) {
uint tmp = x >> rad * 8 & RAD_MAXB - 1;
//acu tre sa inversez bitul de semn
return tmp >= 0x80 ? tmp - 0x80 : tmp + 0x80;
//return tmp;
}
//template <class TYPE>
uint (*condition(int radix))(int,uint) {
//return &getByte;
return radix == RAD_BYTES - 1 ? &getByteS : &getByte;
//return (radix & 3) == 3 ? &getByteS : &getByte;
}
*/
void count_sort(vector <int> &A, vector <int> &cnt, int le, int ri, int radix, int (*get)(int,int))
{
vector <int> aux(ri - le + 1);
int i;
for(i = le; i <= ri; ++i)
//cnt[ cond(radix) ? getByteS(A[i], radix) : getByte(A[i], radix) ] ++;
cnt[ get(A[i], radix) ] ++;
for(i = 1; i <= RAD_MAXB; ++i)
cnt [i] += cnt[i - 1];
//vector<int> cnt2(cnt);
for(i = ri; i >= le; --i)
//aux[ cnt[ cond(radix) ? getByteS(A[i], radix) : getByte(A[i], radix) ]-- - 1 ] = A[i];
aux [ cnt[ get(A[i], radix) ] -- - 1 ] = A[i];
for(i = le; i <= ri; ++i) A[i] = aux[i-le];
}
//template <class TYPE>
void msd_radix_r(vector <int> &A, int le, int ri, int radix) {
if(le < ri && radix >= 0) {
vector<int> cnt(RAD_MAXB + 1,0); //fac pe octeti nu pe cifre
//cout<< "radix: " << radix << " " << le << " " <<ri << ":\n";
count_sort(A,cnt,le,ri,radix, cond(radix) ? &getByteS : &getByte); //afis(cnt); afis(A);
for(int i = 0; i < RAD_MAXB; ++i) {
//msd_radix_r(A, le + (i - 1 >= 0 ? cnt[i - 1] : 0), le + cnt[i] - 1, radix - 1);
msd_radix_r(A, le + cnt[i] , le + cnt[i + 1] - 1, radix - 1);
}
}
}
void msd_radix(vector <int> &A) {
/*
vector<int> pos,neg;
for(unsigned i = 0, N = A.size(); i < N; ++i)
A[i] < 0 ? neg.push_back(A[i]) : pos . push_back(A[i]);
A.clear();
msd_radix_r(neg,0,neg.size() - 1,RAD_BYTES - 1);
msd_radix_r(pos,0,pos.size() - 1,RAD_BYTES - 1);
for(unsigned i = 0, n1 = neg.size(); i < n1; ++i) A.push_back(neg[i]);
for(unsigned i = 0, n2 = pos.size(); i < n2 ;++i) A.push_back(pos[i]);
*/
msd_radix_r(A,0,A.size() - 1,RAD_BYTES - 1);
}
int main() {
ifstream fin("algsort.in");
ofstream fout("algsort.out");
vector <int> A;
unsigned N;
fin >> N; A.resize( N );
for(unsigned i = 0; i < N; ++i) fin >> A[i];
msd_radix(A);
//for(int i = 0; i < 20; ++i) {int x = rand() & 255; fout<< x << ' ' << getByte(x,0) << endl; }
//cout << getByte(-1,3);
for(unsigned i = 0; i < N; ++i) fout << A[i] << ' ';
//system("pause");
return 0;
}