冒泡排序、插入排序、選擇排序這三種算法的時間複雜度都爲 $O(n^2)$,只適合小規模的數據。今天,咱們來認識兩種時間複雜度爲 $O(nlogn)$ 的排序算法——歸併排序(Merge Sort)和快速排序(Quick Sort),他們都用到了 分治思想,很是巧妙。
遞推公式: merge_sort(p…r) = merge(merge_sort(p…q), merge_sort(q+1…r)) 終止條件: p >= r 不用再繼續分解
// O(n(logn)) void Merge_Sort(float data[], int left, int right, float sorted_data[]) { if(left < right) { int mid = (left + right) / 2; Merge_Sort(data, left, mid, sorted_data); Merge_Sort(data, mid+1, right, sorted_data); Merge_Array(data, left, mid, right, sorted_data); } } void Merge_Array(float data[], int left, int mid, int right, float temp[]) { int i = left, j = mid + 1; int k = 0; // 從子數組的頭開始比較 while(i <= mid && j <= right) { if (data[i] <= data[j]) { temp[k++] = data[i++]; } else { temp[k++] = data[j++]; } } // 判斷哪一個子數組還有元素,並拷貝到 temp 後面 while(i <= mid) { temp[k++] = data[i++]; } while(j <= right) { temp[k++] = data[j++]; } // 將 temp 中的數據拷貝到原數組對應位置 for(i = 0; i < k; i++) { data[left+i] = temp[i]; } }
$$ T(1) = C $$
$$T(n) = 2*T(\frac{n}{2}) + n, n>1$$
$$T(n) = 2*T(\frac{n}{2}) + n$$
$$ = 2*[2*T(\frac{n}{4}) + \frac{n}{2}] + n = 4*T(\frac{n}{4}) + 2*n $$
$$= 4*[2*T(\frac{n}{8}) + \frac{n}{4}] + 2*n = 8*T(\frac{n}{8}) + 3*n $$
$$......$$
$$= 2^k * T(\frac{n}{2^k}) + k * n$$
$$......$$
當 $\frac{n}{2^k} = 1$時, $k = log_2n$,代入上式得:
$$ T(n) = n * C + nlog_2n$$
用大 O 標記法來表示,歸併排序的時間複雜度爲 $O(nlogn)$。
遞推公式: quick_sort(p…r) = quick_sort(p…q-1) + quick_sort(q+1, r) 終止條件: p >= r
// O(n(logn)) void Quick_Sort(float data[], int left, int right) { if (left < right) { int i = left, j = left; int pivot = data[right]; for (j = left; j < right; j++) { if (data[j] < pivot) { int temp = data[i]; data[i] = data[j]; data[j] = temp; i++; } } data[j] = data[i]; data[i] = pivot; Quick_Sort(data, left, i-1); Quick_Sort(data, i+1, right); } }
// O(n(logn)) void Quick_Sort(float data[], int left, int right) { if (left < right) { int i = left, j = right; int pivot = data[i]; while(i < j) { while(i < j && data[i] <= pivot) // 從左往右找到第一個比 pivot 大的數 { i++; } if(i < j) { data[j--] = data[i]; } while(i < j && data[j] >= pivot) // 從右往左找到第一個比 pivot 小的數 { j--; } if(i < j) { data[i++] = data[j]; } } data[i] = pivot; // i=j Quick_Sort(data, left, i-1); Quick_Sort(data, i+1, right); } }
獲取更多精彩,請關注「seniusen」!
編程