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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

STL sort解析

發(fā)布時間:2024/4/17 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STL sort解析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

從上學(xué)接觸到編程開始,到工作了幾年。有關(guān)排序算法的內(nèi)容反反復(fù)復(fù)有接觸,但是要說每一種排序算法的細(xì)節(jié)都能說清,那就有難度了。

一來算法難度有深有淺。有比較簡單的冒泡,插入,也有復(fù)雜的堆排序,快排這些。

二來排序算法實(shí)際上成型已久,是個套路的東西。

三來平時工作用不到每一種算法。實(shí)際數(shù)據(jù)不多的時候用冒泡足夠了。數(shù)據(jù)多時,用快排足夠了。

關(guān)聯(lián)容器內(nèi)部有自動排序,序列容器中只有vector,deque的迭代器是隨機(jī)位置迭代器(RandomAccessIterators),因此只有vector和deque能使用std::sort()。

后面講快排會講為什么sort()必須是隨機(jī)位置迭代器。

?

今天看到一個實(shí)際工作中經(jīng)常用到的例子,但是平時沒有注意它的原理。

這個例子有助于加深對排序的理解。便是STL里面的sort()算法。

?

sort()是有策略進(jìn)行排序。具體規(guī)則如下:

// 1.數(shù)據(jù)量大時Quick Sort(快排)
// 2.分段時數(shù)據(jù)量小于門檻,改用Inserition Sort(插入排序)
// 3.遞歸層次太深,改用Heap Sort(堆排序)

里面使用了3種排序。既有復(fù)雜度O(n*n)的插入排序,也有復(fù)雜度O(nlogn)的快排和堆排序。

先分別來看這3種排序。從簡單的插入排序開始吧。

?

插入排序

假設(shè)待排序的序列是a[0..n - 1],總共n個數(shù)據(jù)。

1)a[0]是已排序的序列,a[i, n - 1]是未排序的序列。令i = 1。

2)取a[i]插入到有序序列合適位置,使得新序列有序。

3)重復(fù)2步驟,直到i == n - 1。

外層循環(huán)是從1到n-1,內(nèi)層循環(huán)是找插入位置,無需遍歷所有位置,當(dāng)a[j - 1]?< a[j]即可停止,否則繼續(xù)找位置,同時交換a[j - 1],a[j]的位置。

void InsertSort(int *a, int count) {if (count <= 1){return;}for (int i = 1; i < count; ++i){for (int j = i; j >= 0 && a[j - 1] > a[j]; j--){swap(a[j - 1], a[j]);}} }

有兩層循環(huán),算法復(fù)雜度是O(n*n)? 。穩(wěn)定不穩(wěn)定,取決于中間的判斷條件。a[j - 1] > a[j]則是穩(wěn)定的,條件變成a[j - 1] >= a[j]則是不穩(wěn)定的。

?

快速排序

快排的核心是分治法

1.如果序列S中數(shù)據(jù)的數(shù)量是0或者1。結(jié)束。

2.取S中的任意一個數(shù)字,當(dāng)作樞紐v

3.將S分割成兩段L,R,使得L中的元素全部小于等于v,R中的元素全部大于等于v。

4.將L,R遞歸執(zhí)行快排。

其中第2步,選取一個數(shù)字做樞紐。可以是任意的數(shù)字,通常用的是median-of-three。從首尾和中間數(shù)中,選擇中值。

比如序列:1,4,5,7,9,8,3。那么1,7,3中選3作為樞紐來對序列進(jìn)行分割。

為了能快速取出中間元素,迭代器必須支持隨機(jī)位置(RandomAccess)。

三個數(shù)取中值的函數(shù),只有畫線段標(biāo)位置,容易看出a,b,c三者的大小關(guān)系。

int median(int a, int b, int c) {if (a < b){if (b < c){return b; // a < b < c }else{if (a < c){return c; // a < c <= b }else{return a; // c <= a < b }}}else{if (b < c){if (a < c){return a; // b <= a < c }else{return c; // b < c < a }}else{return b; // c <= b <= a }} }

再來看分割算法:

令first指向頭元素,last指向尾元素。first向尾端移動,last向頭端移動。

當(dāng)first大于等于樞紐時,停止。當(dāng)last小于等于樞紐時,停止。

檢查first,last是否交錯(first >= last),如果交錯返回first。如果沒有交錯,first,last各自向中央移動一個位置。

重復(fù)上面的步驟。

最終返回的first是右半部分的起點(diǎn)。左半部分全部小于等于樞紐,右半部分全部大于等于樞紐。

來看代碼,RandomAccessIter可以理解成一個普通指針。

int* partition(int *first, int *last, int pivot) {while (true){while (*first < pivot) first++;while (*last > pivot) last--;if (first >= last) return first;swap(*first, *last);first++;last--;} }

?

?

引用:

1.《STL源碼剖析》

2.《MoreWindows白話經(jīng)典算法之七大排序第2版》

轉(zhuǎn)載于:https://www.cnblogs.com/yao2yaoblog/p/7443804.html

總結(jié)

以上是生活随笔為你收集整理的STL sort解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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