關於資料結構演算法中的比較排序(一)(附Java程式碼實現)
阿新 • • 發佈:2018-12-14
現在已經是10月份,秋招正在進行,不知道是不是有的人會和我一樣正在瘋狂的複習起資料結構,在這裡我將就常見的幾種比較排序做一些簡單的解析,同時附上具體的程式碼實現。
1.氣泡排序
氣泡排序通常是我們最先接觸道的比較排序的一種,具體排序步驟如下:
1.比較相鄰的元素,如果前一個比後一個大(小),就把它們兩個調換位置;
2.對每一對相鄰元素做同樣的工作,從開始從開始第一對到結尾的最後一對。這步做完後,最後的元素會是最大(小)的數,為已排序元素;
3.針對所有未排序元素重複上述步驟,直至沒有任何一對數字需要比較為止,得到即為已排序列;
public void bubbleSort(int[] array) { int l = array.length; for (int j = 0; j < l; j++) { for (int i = 0; i < l - j; i++) { // 依次比較相鄰的兩個元素,使較大的那個向後移 if (array[i] > array[i + 1]){ //此方法用來表示交換array陣列中第i個和第i+1個元素的值 swapData(array, i, i + 1); } } } }
2.選擇排序
一種非常好理解的演算法,故名思意,就是要不斷從未排序元素中選擇出最大(小)元素,具體排序步驟如下:
1.在序列中尋找最大(小)元素,放到序列的起始位置作為已排序序列;
2.從剩餘未排序元素中繼續尋找最大(小)元素,放到已排序序列的末尾;
3.重複步驟直至所有元素排序完畢。
public void selectionSort(int[] array){ int l = array.length; for (int i = 0; i < l; i++){ int min = i; for (int j = i + 1; j < l; j++){ if (array[j] < array[min]){ min = j; } } // 放到已排序序列的末尾,該操作很有可能把穩定性打亂,所以選擇排序是不穩定的排序演算法 if (min != i){ swaphData(array, min, i); } } }
3.插入排序
類比抽撲克牌,牌堆為未排序序列,手牌中為已排序列,抽一張牌,與手中的牌逐一進行比較,比較後插入對應位置,接著再抽一張牌,直至牌堆無牌可抽,排序即完成,具體步驟如下:
1.從第一個元素開始,該元素可以認為已經被排序; 2.取出下一個元素,在已經排序的元素序列中從後向前掃描; 3.如果該元素(已排序)大於新元素,將該元素移到下一位置; 4.重複步驟3,直到找到已排序的元素小於或者等於新元素的位置; 5.將新元素插入到該位置後; 6.重複步驟2~5。
//普通的插入排序 public void insertionSort(int[] array) { int l = array.length; for (int i = 1; i < l; i++){ //先獲取一個數據 int get = array[i]; int j = i - 1; //將獲取的資料右向左進行比較 while (j >= 0 && array[j] > get){ // 如果該手牌比抓到的牌大,就將其右移 array[j + 1] = array[j]; j--; } array[j + 1] = get; // 直到該手牌比抓到的牌小(或二者相等),將抓到的牌插入到該手牌右邊(相等元素的相對次序未變,所以插入排序是穩定的) } }
//使用二分法對插入排序進行優化
public void insertionSortDichotomy(int[] array){
int l = array.length;
for (int i = 1; i < l; i++){
// 右手抓到一張撲克牌
int get = array[i];
// 拿在左手上的牌總是排序好的,所以可以用二分法
int left = 0;
// 手牌左右邊界進行初始化
int right = i - 1;
while (left <= right){
int mid = (left + right) / 2;
if (array[mid] > get)
right = mid - 1;
else
left = mid + 1;
}
// 將欲插入新牌位置右邊的牌整體向右移動一個單位
for (int j = i - 1; j >= left; j--){
array[j + 1] = array[j];
}
// 將抓到的牌插入手牌
array[left] = get;
}
}