#include <iostream>
#include<fstream>
using namespace std;
ifstream in("radixsort.in");
ofstream out("radixsort.out");
void insertie_directa(int v[],int n)
{
int i,j,x;
for(i=2; i<=n; i++)
{
x=v[i];
j=i-1;
while(j>=1 && v[j]>x)
{
v[j+1]=v[j];
j--;
}
v[j+1]=x;
}
}
void selectie_directa(int v[], int n)
{
int i, j, k, min;
for (i = 1; i <= n-1; i++)
{
k = i;
min = v[i];
for (j = i+1; j <= n; j++)
{
if (v[j] < min)
{
k = j;
min = v[j];
}
}
v[k] = v[i];
v[i] = min;
}
}
void bubblesort(int v[],int n)
{
int ok,i;
do
{
ok=1;
for(i=1; i<n; i++)
if(v[i]>v[i+1])
{
v[i]=v[i]+v[i+1]-(v[i+1]=v[i]);
ok=0;
}
}
while(ok==0);
}
void shell_sort (int v[], int n)
{
int j;
for (int gap = n / 2; gap > 0; gap /= 2)//
{
for (int i = gap; i < n; ++i)
{
int temp = v[i];
for (j = i; j >= gap && temp < v[j - gap]; j -= gap)
{
v[j] = v[j - gap];
}
v[j] = temp;
}
}
}
void shell_sort2(int v[],int n)
{
int i,j,aux,gap;
int gaps[8]= {701,301,132,57,23,10,4,1};// Marcin Ciura's gap sequence
for(gap=0; gap<8; gap++)
{
for(i=gaps[gap]; i<n; i++)
{
aux=v[i];
for(j=i; j>=gaps[gap] && v[j-gaps[gap]]>aux; j-=gaps[gap])
v[j]=v[j-gaps[gap]];
v[j]=aux;
}
}
}
int partitie(int a[],int l, int r)
{
int i,j, p, t;
p = a[r];
i = l - 1;
for(j =l; j <= r-1; j++)
{
if(a[j] <= p)
{
i++;
t = a[j];
a[j] = a[i];
a[i] = t;
}
}
t = a[i+1];
a[i+1] = a[r];
a[r] = t;
return i+1;
}
void quicks(int v[],int l,int r)
{
int q;
if (l < r)
{
q=partitie(v,l, r);
quicks(v,l,q-1);
quicks(v,q+1,r);
}
}
void inserareheap(int a[],int n,int t)
{
int j,k,heap;
j=t;
heap=0;
while(2*j+1<n && !heap)
{
k=2*j+1;
if(k<n-1 && a[k]<a[k+1])
k++;
if(a[j]<a[k])
{
swap(a[j],a[k]);
j=k;
}
else
heap=1;
}
}
void heapsort(int a[], int n)
{
int t,r;
for(t=(n-1)/2; t>=0; t--)
inserareheap(a,n,t);
r=n-1;
while(r>0)
{
swap(a[0],a[r]);
inserareheap(a,r,0);
r--;
}
}
void interclasare(int a[],int p,int m,int q)
{
int i=p,j=m+1,k=0;
int b[100];
while(i<=m && j<=q)
if(a[i]<a[j])
b[k++]=a[i++];
else b[k++]=a[j++];
while(i<=m)
b[k++]=a[i++];
while(j<=q)
b[k++]=a[j++];
for(i=p; i<=q; i++)
a[i]=b[i-p];
}
void mergesort(int a[],int p,int q)
{
if(q>p)
{
int m=(p+q)/2;
mergesort(a,p,m);
mergesort(a,m+1,q);
interclasare(a,p,m,q);
}
}
int getMax(int arr[], int n)
{
int mx = arr[0];
for (int i = 1; i < n; i++)
if (arr[i] > mx)
mx = arr[i];
return mx;
}
void countSort(int arr[], int n, int exp)
{
int output[n]; // output array
int i, count[10] = {0};
// Store count of occurrences in count[]
for (i = 0; i < n; i++)
count[ (arr[i]/exp)%10 ]++;
// Change count[i] so that count[i] now contains actual
// position of this digit in output[]
for (i = 1; i < 10; i++)
count[i] += count[i - 1];
// Build the output array
for (i = n - 1; i >= 0; i--)
{
output[count[ (arr[i]/exp)%10 ] - 1] = arr[i];
count[ (arr[i]/exp)%10 ]--;
}
// Copy the output array to arr[], so that arr[] now
// contains sorted numbers according to current digit
for (i = 0; i < n; i++)
arr[i] = output[i];
}
// The main function to that sorts arr[] of size n using
// Radix Sort
void radixsort(int arr[], int n)
{
// Find the maximum number to know number of digits
int m = getMax(arr, n);
// Do counting sort for every digit. Note that instead
// of passing digit number, exp is passed. exp is 10^i
// where i is current digit number
for (int exp = 1; m/exp > 0; exp *= 10)
countSort(arr, n, exp);
}
int main()
{
int i,n,v[10000000];
in>>n;
for(i=0; i<n; i++)
in>>v[i];
radixsort(v,n);
for(i=0; i<n; i++)
out<<v[i]<<" ";
return 0;
}