1. 程式人生 > 實用技巧 >幾種經典演算法排序整理(未完成)

幾種經典演算法排序整理(未完成)

目錄

排序演算法

氣泡排序

氣泡排序(Bubble Sort)是一種簡單的排序演算法。它重複地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個演算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端。

演算法描述

  1. 比較相鄰的元素。如果元素大小關係不正確,就交換它們兩個;
  2. 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對;
  3. 針對所有的元素重複以上的步驟,除了最後一個;
  4. 重複步驟1~3,直到排序完成。

動圖演示

程式碼實現

void bubbleSort(int array[], const int len) {
	for (int i = 0; i < len - 1; i++) {
		for (int j = 0; j < len - i - 1; j++) {
			if (array[j] > array[j+1]) {
				int temp = array[j];
				array[j] = array[j + 1];
				array[j + 1] = temp;
			}
		}
	}
}

優化:如果某一次遍歷沒有資料交換了,那麼就做一個標記,跳出迴圈。

//改進版
void bubbleSort2(int array[], const int len) {
	for (int i = 0; i < len - 1; i++) {
		bool flag = false;
		for (int j = 0; j < len - i - 1; j++) {
			if (array[j] > array[j + 1]) {
				int temp = array[j];
				array[j] = array[j + 1];
				array[j + 1] = temp;
				flag = true;
			}
		}
		if (!flag) {
			break;   // 若沒發生交換,則說明數列已有序。
		}
	}
}

優化2:記錄某次遍歷的時候最後發生資料交換的位置,後面的資料已經排好序,那麼迴圈的範圍就可以縮小了。
未完待續

選擇排序

選擇排序(Selection Sort)是一種簡單直觀的排序演算法。它的工作原理如下,首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

演算法描述

  1. 未排序的數列中找到最小(or最大)元素,然後將其存放到數列的起始位置;
  2. 從剩餘未排序的元素中繼續尋找最小(or最大)元素,然後放到已排序序列的末尾;
  3. 以此類推,直到所有元素均排序完畢;

動圖演示

演算法分析

選擇排序的主要優點與資料移動有關。如果某個元素位於正確的最終位置上,則它不會被移動。選擇排序每次交換一對元素,它們當中至少有一個將被移到其最終位置上,因此對n個元素的序列進行排序總共進行至多n-1次交換。在所有的完全依靠交換去移動元素的排序方法中,選擇排序屬於非常好的一種。

表現最穩定的排序演算法之一,因為無論什麼資料進去都是O(n2)的時間複雜度,所以用到它的時候,資料規模越小越好。唯一的好處可能就是不佔用額外的記憶體空間了吧。理論上講,選擇排序可能也是平時排序一般人想到的最多的排序方法了吧。

程式碼實現

void selectionSort(int arr[], int n) {
	for (int i = 0; i < n - 1; i++) {
		int min = i;
		for (int j = i + 1; j < n; j++) {
			if (arr[min] > arr[j]) {
				min = j;
			}
		}
		if (min != i) {
			int tmp = arr[i];
			arr[i] = arr[min];
			arr[min] = tmp;
		}
	}
}

插入排序

插入排序(Insertion-Sort)的演算法描述是一種簡單直觀的排序演算法。它的工作原理是通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃描,找到相應位置並插入。具體說明如下:

設有一組關鍵字{K1, K2,…, Kn};排序開始就認為 K1 是一個有序序列;讓 K2 插入上述表長為 1 的有序序列,使之成為一個表長為 2 的有序序列;然後讓 K3 插入上述表長為 2 的有序序列,使之成為一個表長為 3 的有序序列;依次類推,最後讓 Kn 插入上述表長為 n-1 的有序序列,得一個表長為 n 的有序序列。

演算法描述

  1. 從第一個元素開始,該元素可以認為已經被排序
  2. 取出下一個元素,在已經排序的元素序列中從後向前掃描
  3. 如果該元素(已排序)大於新
    元素,將該元素移到下一位置
  4. 重複步驟 3,直到找到已排序的元素小於或者等於新元素的位置
  5. 將新元素插入到該位置後
  6. 重複步驟 2~5

動圖演示

演算法分析

插入排序在實現上,通常採用in-place排序(即只需用到O(1)的額外空間的排序),因而在從後向前掃描過程中,需要反覆把已排序元素逐步向後挪位,為最新元素提供插入空間。

程式碼實現

void InsertionSort(int arr[], int n) {
	for (int i = 1; i < n; i++) {
		int j = i - 1;
		int tmp = arr[i];
		//比這個值大的,都向後移動
		while (arr[j] > tmp) {
			arr[j + 1] = arr[j];
			j--;
		}
		//插入
		arr[j + 1] = tmp;
	}
}

希爾排序

希爾排序(Shell Sort)於1959年由Shell發明,第一個突破O(n2)的排序演算法,是簡單插入排序的改進版。它與插入排序的不同之處在於,它會優先比較距離較遠的元素。希爾排序又叫縮小增量排序。

希爾排序可以看作是一個氣泡排序或者插入排序的變形。希爾排序在每次的排序的時候都把陣列拆分成若干個序列,一個序列的相鄰的元素索引相隔的固定的距離gap,每一輪對這些序列進行冒泡或者插入排序,然後再縮小gap得到新的序列一一排序,直到gap為1。

演算法描述

先將整個待排序的記錄序列分割成為若干子序列分別進行直接插入排序,具體演算法描述:

  1. 選擇一個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
  2. 按增量序列個數k,對序列進行k 趟排序;
  3. 每趟排序,根據對應的增量ti,將待排序列分割成若干長度為m 的子序列,分別對各子表進行直接插入排序。僅增量因子為1 時,整個序列作為一個表來處理,表長度即為整個序列的長度。

動圖演示


演算法分析

希爾排序的核心在於間隔序列的設定。既可以提前設定好間隔序列,也可以動態的定義間隔序列。動態定義間隔序列的演算法是《演算法(第4版)》的合著者Robert Sedgewick提出的。

程式碼實現