本文将介绍几种基本的排序算法,如冒泡排序,选择排序,插入排序,希尔排序,归并排序。
首先写好交换两个元素的模板:
private void exch(int[] a, int lo, int hi) {
int temp = a[lo];
a[lo] = a[hi];
a[hi] = temp;
}
冒泡排序:
冒泡排序是最简单的排序方法,即将元素两两之间相比较,然后进行排序,算法的代码如下;
public void sort(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
for (int j = i + 1; j < a.length; j++) {
if (a[i] > a[j]) {
exch(a, i, j);
}
}
}
}
但是此种冒泡排序有种缺陷,即两两排序的时候可能会将相对比较小的值换到后面,这样的话又增加了交换的次数,如果是从后面开始往前进行比较的话就不会存在这种情况,同时,在从后往前进行两两比较的时候,如果在某次进行两两相比较之时已经处于有序状态,那么即可以退出循环,不再比较。
改进代码:
public void sort(int[] a) {
boolean flag = true; //flag判断是否进行了交换
for (int i = 0; i < a.length - 1 && flag == true; i++) { //若未进行交换,则退出循环
flag = false;
for (int j = a.length - 2; j >= i; j--) {
if (a[j] > a[j + 1]) {
exch(a, j, j + 1);
flag = true;
}
}
}
}
选择排序:
顾名思义,选择排序,即先选择好序列中的最小元素,然后交换之。换言之,也就是比较的次数并没有发生多少,但是只交换一次,比冒泡排序稍好一些。
/**
* 定义一个下标min,若值比a[min]小,则令min为相应的下标值,再将a[min]与a[i]交换即可
* @param a
*/
public void sort(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
int min = i;
for (int j = i + 1;j < a.length; j--) {
if (a[min] > a[j]) {
min = j;
}
}
if(min != i){
exch(a, i, min);
}
}
}
插入排序:
插入排序就像是扑克牌抓牌一样,当抓到一张较小的牌的时候,需要将它插到比它大的(两者之间的差最小的)牌的左边,并且将牌相应的向右移动。代码如下:
public void sort(int[] a) {
for(int i = 1; i < a.length; i++){
for(int j = i; j > 0 && (a[j] < a[j - 1]); j--){
exch(a, j, j - 1);
}
}
}
希尔排序:
第一个将时间复杂度突破到O(n*n)之下的。依然是使用的插入排序,也就是在插入排序的基础之上选定一段距离进行插入排序。
public void sort(int[] a) {
int h = 1;
while(h < a.length / 3){
h = 3 * h + 1;
}
while(h >= 1) {
for (int i = h; i < a.length; i++) {
for (int j = i; j >= h && (a[j] < a[j - h]); j -= h) {
exch(a, j, j - h);
}
}
h = h / 3;
}
}
归并排序:
将一个序列分成两段,分别进行排序,然后再整体排序。
private static int[] temp;
public void sort(int[] a) {
temp = new int[a.length];
sort(a, 0, a.length - 1);
}
private void sort(int[] a, int lo, int hi){
if(lo >= hi){return;}
int mid = (lo + hi) / 2;
sort(a, lo, mid);
sort(a,mid + 1, hi);
merge(a, lo, mid, hi);
}
private void merge(int[] a, int lo, int mid, int hi){
for(int i = lo; i <= hi; i++){
temp[i] = a[i];
}
int i = lo;
int j = mid + 1;
for(int k = lo; k <= hi; k++) {
if(i > mid){a[k] = temp[j++];}
else if(j > hi){a[k] = temp[i++];}
else if(temp[i] > temp[j]){
a[k] = temp[j++];
}else{
a[k] = temp[i++];
}
}
}