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

//swap、2つの値を入れ替えるだけ（ソートで必須）
void swap(int *x, int *y){
	int tmp = *x;
	*x = *y;
	*y = tmp;
}

//reverse、配列を逆順にする（演習0）
//前と後ろをswapしていくだけ。半分まででOK。
void reverse(int *a, int n){
	for(int i = 0; i < n/2; i++){
		swap(&a[i], &a[n-1-i]);
	}
}

//printA、配列を出力するだけ（確認用）
void printA(int *a, int n){
	for(int i = 0; i < n; i++){
		printf("%d ", a[i]);
 	}
	printf("\n");
}

//バブルソート（BubbleSort）
//隣同士を比べて逆ならswap。これをn回繰り返すだけ。
//大きいのが後ろに“浮く”イメージ。
//O(n^2) → 2重ループだから。
void bubble_sort(int *a, int n){
	for(int i = 0; i < n-1; i++){ //後ろからi個は確定
		for(int j = 0; j < n-1-i; j++){ //隣同士を比較
			if(a[j] > a[j+1]){
				swap(&a[j], &a[j+1]);
			}
		}
	}
}

//選択ソート（SelectionSort）
//未整列の中から最小値を探して、先頭と入れ替えるだけ。
//毎回「最小値の位置」を探す必要がある。
//O(n^2) → 最小値探しがO(n)、それをn回。
void selection_sort(int *a, int n){
	for(int i = 0; i < n-1; i++){
		int min_i = i; //ひとまずi番目を最小と仮定
		for(int j = i+1; j < n; j++){
			if(a[j] < a[min_i]){
				min_i = j;
			}
		}
		swap(&a[i], &a[min_i]); //見つけた最小値と入れ替え
	}
}

//挿入ソート（InsertionSort）
//手札を並べるイメージ。左側は整列済みとして扱う。
//a[i] を一時保存して、適切な位置まで後ろにずらす。
//ほぼ整列済みのデータには超強い。
//O(n^2) → ずらす処理が最大n回、それをn回。
void insertion_sort(int *a, int n){
	for(int i = 1; i < n; i++){
		int key = a[i]; //挿入したい値
		int j = i - 1;
		while(j >= 0 && a[j] > key){ //keyより大きいのを後ろへ
			a[j+1] = a[j];
			j--;
		}
	a[j+1] = key; //ここが挿入位置
	}
}

int main(void){
	int n;
	scanf("%d", &n);

	int *a = (int *)malloc(sizeof(int) * n);
	for(int i = 0; i < n; i++){
		scanf("%d", &a[i]);
	}

	//ここで好きなソートを試す（コメント切り替え）
	//bubble_sort(a, n);
	//selection_sort(a, n);
	insertion_sort(a, n);

	printA(a, n);

	free(a);
  	return 0;
}
