Java中經常使用的幾種排序算法

如下列出Java中經常使用的幾種排序算法,只是簡單實現了排序的功能,還有待改進,望指教(如下均假設數組的長度爲n):java

1)冒泡排序:算法

依次比較相鄰的兩個元素,經過一次比較把未排序序列中最大(或最小)的元素放置在未排序序列的末尾。數組

public class BubbleSort {
 public static void sort(int data[]) {
  for (int i = 0; i < data.length -1; i++) {
   for (int j = 0; j < data.length - i - 1; j++) {
    if (data[j] > data[j + 1]) {
     int temp = data[j];
     data[j] = data[j + 1];
     data[j + 1] = temp;
    }
   }
  }
 }
}

 

2)選擇排序:數據結構

每一次從待排序的數據元素中選出最小(或最大)的一個元素,順序放在已排好序的數列的最後,直到所有待排序的數據元素排完。ide

public class SelectionSort {
 public static void sort(int data[]) {
  int minVal;
  int minIndex;
  for (int i = 0; i < data.length - 1; i++) {
   minVal = data[i];
   minIndex = i;
   for (int j = i + 1; j < data.length; j++) {
    if (data[j] < minVal) {
     minVal = data[j];
     minIndex = j;
    }
   }
   if (minVal != data[i] && minIndex != i) {
    data[minIndex] = data[i];
    data[i] = minVal;
   }
  }
 }
}

注:冒泡排序與選擇排序有點相似,都是先經過依次比較將最小/大的元素放到最後;不一樣的是冒泡排序一次操做中,每次比較後,若須要都進行位置交換;而選擇排序是每次比較以後,將最小的值的位置記錄下來,最後與末尾位置交換。ui


3)插入排序:spa

將數列分爲有序和無序兩個部分,每次處理就是將無序數列的第一個元素與有序數列的元素從後往前逐個進行比較,找出插入位置,將該元素插入到有序數列的合適位置中
.net

public class InsertionSort {
 public static void sort(int data[]) {
  for (int i = 1; i < data.length; i++) {
   for (int j = i; j > 0; j--) {
    if (data[j] < data[j - 1]) {
     int temp = data[j];
     data[j] = data[j - 1];
     data[j - 1] = temp;
    }
   }
  }
 }
}

注:插入排序的特色是從序列的第二個元素開始,與第一個元素排序,完成一輪;第二輪從第三個元素,依次與前面比較,而後排序, 其實就是作冒泡排序。指針


4)歸併排序:排序

將兩個(或兩個以上)有序表合併成一個新的有序表,即把待排序序列分爲若干個子序列,每一個子序列是有序的。而後再把有序子序列合併爲總體有序序列。排序過程以下:
(1)申請空間,使其大小爲兩個已經排序序列之和,該空間用來存放合併後的序列
(2)設定兩個指針,最初位置分別爲兩個已經排序序列的起始位置
(3)比較兩個指針所指向的元素,選擇相對小的元素放入到合併空間(注:若是是降序排列則選擇相對較大的元素放入到合併空間),並移動指針到下一位置
(4)重複步驟3直到某一指針達到序列尾
(5)將另外一序列剩下的全部元素直接複製到合併序列尾

public class MergeSort {
 public static void sort(int data[], int start, int end) {
  if (start < end) {
   int mid = (start + end) / 2;
   sort(data, start, mid);
   sort(data, mid + 1, end);
   merge(data, start, mid, end);
  }
 }
 public static void merge(int data[], int start, int mid, int end) {
  int temp[] = new int[end - start + 1];
  int i = start;
  int j = mid + 1;
  int k = 0;
  while (i <= mid && j <= end) {
   if (data[i] < data[j]) {
    temp[k++] = data[i++];
   } else {
    temp[k++] = data[j++];
   }
  }
  while (i <= mid) {
   temp[k++] = data[i++];
  }
  while (j <= end) {
   temp[k++] = data[j++];
  }
  for (k = 0, i = start; k < temp.length; k++, i++) {
   data[i] = temp[k];
  }
 }
}

例如:降序排{10,5,9,6}分爲{10,5},{9,6}而後{5,10},{6,9}而後{5,6,9,10}。


5)快速排序:

經過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的全部數據都比另一部分的全部數據都小,而後再按此方法對這兩部分數據分別進行快速排序,整個排序過程能夠遞歸進行,以此達到整個數據變成有序序列。

public class QuickSort {
 public static void sort(int data[], int start, int end) {
  if (end - start <= 0) {
   return;
  }
  int last = start;
  for (int i = start + 1; i <= end; i++) {
   if (data[i] < data[start]) {
    int temp = data[++last];
    data[last] = data[i];
    data[i] = temp;
   }
  }
  int temp = data[last];
  data[last] = data[start];
  data[start] = temp;
  sort(data, start, last - 1);
  sort(data, last + 1, end);
 }
}

示例

假設用戶輸入了以下數組:

下標

0

1

2

3

4

5

數據

6

2

7

3

8

9

建立變量i=0(指向第一個數據), j=5(指向最後一個數據), k=6(賦值爲第一個數據的值)。

咱們要把全部比k小的數移動到k的左面,因此咱們能夠開始尋找比6小的數,從j開始,從右往左找,不斷遞減變量j的值,咱們找到第一個下標3的數據比6小,因而把數據3移到下標0的位置,把下標0的數據6移到下標3,完成第一次比較:

下標

0

1

2

3

4

5

數據

3

2

7

6

8

9

i=0 j=3 k=6

接着,開始第二次比較,此次要變成找比k大的了,並且要從前日後找了。遞加變量i,發現下標2的數據是第一個比k大的,因而用下標2的數據7和j指向的下標3的數據的6作交換,數據狀態變成下表:

下標

0

1

2

3

4

5

數據

3

2

6

7

8

9

i=2 j=3 k=6

稱上面兩次比較爲一個循環。

接着,再遞減變量j,不斷重複進行上面的循環比較。

在本例中,咱們進行一次循環,就發現i和j「碰頭」了:他們都指向了下標2。因而,第一遍比較結束。獲得結果以下,凡是k(=6)左邊的數都比它小,凡是k右邊的數都比它大:

下標

0

1

2

3

4

5

數據

3

2

6

7

8

9

若是i和j沒有碰頭的話,就遞加i找大的,尚未,就再遞減j找小的,如此反覆,不斷循環。注意判斷和尋找是同時進行的。

而後,對k兩邊的數據,再分組分別進行上述的過程,直到不能再分組爲止。

注意:第一遍快速排序不會直接獲得最終結果,只會把比k大和比k小的數分到k的兩邊。爲了獲得最後結果,須要再次對下標2兩邊的數組分別執行此步驟,而後再分解數組,直到數組不能再分解爲止(只有一個數據),才能獲得正確結果。

相關文章
相關標籤/搜索