日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

算法与数据结构(快速排序)

發(fā)布時(shí)間:2025/3/21 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法与数据结构(快速排序) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

快速排序 Quick Sort

快速排序是對(duì)冒泡排序的一種改進(jìn)
通過(guò)一趟排序?qū)⑿蛄蟹譃閮蓚€(gè)部分,其中一個(gè)部分的所有數(shù)據(jù)比另一個(gè)部分的所有數(shù)據(jù)都小,然后再分別對(duì)兩個(gè)部分進(jìn)行類似操作(遞歸),直到整個(gè)序列有序

基本思路:

隨機(jī)找出一個(gè)數(shù),或是取第一個(gè)或最后一個(gè)數(shù)為基準(zhǔn)。然后將所有的數(shù)和基準(zhǔn)比較,比基準(zhǔn)小,就放左邊,比基準(zhǔn)大就放右邊,這樣就把一個(gè)序列分成了兩個(gè)子序列。然后按照同樣的方法對(duì)子序列排序


最終,基準(zhǔn)數(shù)左邊的數(shù)都比它小,右邊的數(shù)都比他大

實(shí)現(xiàn):

首先寫(xiě)出在每一層遞歸內(nèi)需要完成的基本操作:

// 左下標(biāo)int l = left;// 右下標(biāo)int r = right;// 基準(zhǔn)數(shù)int pivot = arr[left]; // 保存基準(zhǔn)數(shù)的數(shù)值大小int temp; // 臨時(shí)變量,用來(lái)輔助完成交換操作while(l < r) {// 這個(gè) while 循環(huán)結(jié)束時(shí)找出比基準(zhǔn)數(shù)小或相等的 rwhile(arr[r]>pivot && l<r) {r--;}// 這個(gè) while 循環(huán)找出比基準(zhǔn)數(shù)大的 lwhile(arr[l] <=pivot && l<r) {l++;}//交換 l 和 rif (l < r) {temp = arr[r];arr[r] = arr[l];arr[l] = temp;}}// 如果最終基準(zhǔn)數(shù)和i,j不重合,將基準(zhǔn)數(shù)和i,j所指的數(shù)交換if (left != l) {arr[left] = arr[l];arr[l] = pivot;}

然后考慮遞歸的終止情況,我們會(huì)序列不斷細(xì)分,當(dāng)序列只有最后一個(gè)數(shù)字時(shí),遞歸將終止。此時(shí),我們輸入的 leftleftleftrightrightright 應(yīng)該滿足條件:left≥rightleft \geq rightleftright

因此,最終的代碼為:

public static void quickSort(int[] arr, int left, int right) {// 左下標(biāo)int l = left;// 右下標(biāo)int r = right;// 終止條件if (left >= right) {return;}// 中軸值int pivot = arr[left];int temp;while(l < r) {// 這個(gè) while 循環(huán)結(jié)束時(shí)找出比基準(zhǔn)數(shù)小或相等的 rwhile(arr[r]>pivot && l<r) {r--;}// 這個(gè) while 循環(huán)找出比基準(zhǔn)數(shù)大的 lwhile(arr[l] <=pivot && l<r) {l++;}if (l < r) {temp = arr[r];arr[r] = arr[l];arr[l] = temp;}}// 將基準(zhǔn)數(shù)和i,j所指的數(shù)交換if (left != l) {arr[left] = arr[l];arr[l] = pivot;}quickSort(arr, left, l-1);quickSort(arr, l+1, right);}

時(shí)間復(fù)雜度:

  • 平均時(shí)間復(fù)雜度:

快速排序涉及遞歸調(diào)用,因此該算法的復(fù)雜度和遞歸的時(shí)間復(fù)雜度有關(guān)

遞歸的時(shí)間復(fù)雜度公式為:T(n)=aT(n/b)+f(n)T(n) = aT(n/b) + f(n)T(n)=aT(n/b)+f(n) ,表示一個(gè)規(guī)模為 n 的問(wèn)題被分成規(guī)模為 n/b 的 a 個(gè)子問(wèn)題(在這里,a = 2, b = 2),f(n)f(n)f(n) 表示平分這個(gè)序列所花的時(shí)間,而平分序列需要從頭到尾遍歷,因此 f(n)=O(n)f(n) = O(n)f(n)=O(n)

下面開(kāi)始推導(dǎo):

第一次遞歸

T(n)=2T(n/2)+nT(n) = 2T(n/2) + nT(n)=2T(n/2)+n

第二次遞歸,令 n = n/2

T(n)=2(2T(n/4)+n)+n=22T(n/4)+3nT(n) = 2(2T(n/4) + n) + n\\ = 2^2T(n/4)+3nT(n)=2(2T(n/4)+n)+n=22T(n/4)+3n

第 m 次遞歸,令 n = n/(2^{(m-1)})

T(n)=2mT(n/2m)+mnT(n) = 2^{m}T(n/2^m) + mnT(n)=2mT(n/2m)+mn

而到最后得到 T(1) 時(shí),說(shuō)明公式已經(jīng)遞歸到了最后一步

T(n/2m?1)=T(1)n=2m→m=log(n)T(n)=2log(n)T(1)+nlog(n)=n+nlog(n)=O(nlogn)T(n/2^{m-1}) = T(1) \\ n = 2^m \rightarrow m = log(n)\\ T(n) = 2^{log(n)}T(1) + nlog(n) = n + nlog(n) = O(nlogn) T(n/2m?1)=T(1)n=2mm=log(n)T(n)=2log(n)T(1)+nlog(n)=n+nlog(n)=O(nlogn)

  • 最壞時(shí)間復(fù)雜度:

當(dāng)基準(zhǔn)數(shù)就是最大或最小數(shù)時(shí),每一次都需要從同一邊遍歷數(shù)組,這時(shí)就相當(dāng)于一個(gè)冒泡排序,所以最壞時(shí)間復(fù)雜度為 O(n2)O(n^2)O(n2)

空間復(fù)雜度:

在每一次遞歸中,空間復(fù)雜度都是 O(1)O(1)O(1)

在最優(yōu)情況下,遞歸 logn 次(每一次正好平分),因此為 O(logn)O(logn)O(logn)

在最壞情況下,遞歸 n 次(每一次都是 n-1 和 1 這樣分),因此為 O(n)O(n)O(n)

穩(wěn)定性:

因?yàn)榭焖倥判驗(yàn)榇騺y數(shù)字間的順序,所以快速排序是不穩(wěn)定的


相關(guān)章節(jié)
第一節(jié) 簡(jiǎn)述
第二節(jié) 稀疏數(shù)組 Sparse Array
第三節(jié) 隊(duì)列 Queue
第四節(jié) 單鏈表 Single Linked List
第五節(jié) 雙向鏈表 Double Linked List
第六節(jié) 單向環(huán)形鏈表 Circular Linked List
第七節(jié) 棧 Stack
第八節(jié) 遞歸 Recursion
第九節(jié) 時(shí)間復(fù)雜度 Time Complexity
第十節(jié) 排序算法 Sort Algorithm
第十一節(jié) 冒泡排序 Bubble Sort
第十二節(jié) 選擇排序 Select Sort
第十三節(jié) 插入排序 Insertion Sort
第十四節(jié) 冒泡排序,選擇排序和插入排序的總結(jié)
第十五節(jié) 希爾排序 Shell’s Sort
第十六節(jié) 快速排序 Quick Sort
第十七節(jié) 歸并排序 Merge Sort

代碼實(shí)現(xiàn)

/*** 分治法解決快排問(wèn)題:* 1. 分解:將數(shù)組A[p..r]劃分為兩個(gè)子數(shù)組A[p..q-1]和A[q+1..r],* 使得A[p..q-1]中的每個(gè)元素都小于A[q],而A[q+1..r]中的每個(gè)元素都大于A[q]。* 2. 解決:遞歸調(diào)用快速排序,對(duì)子數(shù)組進(jìn)行快排。* 3. 合并:由于快排是原地排序,因此不需要合并步驟。*/#include <iostream> #include <vector> #include <algorithm> using namespace std;/*** @brief (單向移動(dòng))分解函數(shù),將數(shù)組劃分為A[p..q-1]和A[q+1..r],* 使得A[p..q-1]中的每個(gè)元素都小于A[q],而A[q+1..r]中的每個(gè)元素都大于A[q]。* * @param nums * @param p * @param r */ int partition(vector<int>& nums, int p, int r) {int value = nums[r]; // 將最后一個(gè)元素作為主元int i = p-1; // 設(shè)置i的初始值,i會(huì)始終指向有序序列中最后一個(gè)比主元小的數(shù)for (int j=p;j<r;j++) { // 注意此處j!=r,因?yàn)閞是主元if (nums[j] <= value) {swap(nums[++i], nums[j]); }}swap(nums[++i], nums[r]); // 最后將主元放到正確的位置,即nums[i+1]return i; }void quickSort(vector<int>& nums, int p, int r) {if (p < r) {int q = partition(nums, p, r);quickSort(nums, p, q-1);quickSort(nums, q+1, r);} }// test int main(int argc, char const *argv[]) {vector<int> nums = {1,2,6,7,8,9,3,4,5};quickSort(nums, 0, nums.size()-1);for (auto num : nums) {cout << num << endl;}return 0; }

總結(jié)

以上是生活随笔為你收集整理的算法与数据结构(快速排序)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。