stl中list的sort演算法實現

2021-07-12 07:35:04 字數 4321 閱讀 2745

stl中有乙個std::sort演算法,但它是不支援std::list的,因為list不提供randomiterator的支援,但list自己提供了sort演算法,把list的元素按從小到大的方式來排序,**長度到不長,但真是難以讀懂,後來扣持了一下午終於搞明白了,貼個總結上來。

list::sort的**如下(sgi stl):

[cpp]view plain

copy

template

<

class

_tp, 

class

_alloc>  

void

list<_tp, _alloc>::sort()  

__carry.swap(__counter[__i]);        

if(__i == __fill) ++__fill;  

}   

for(

int__i = 1; __i < __fill; ++__i)  

__counter[__i].merge(__counter[__i-1]);  

swap(__counter[__fill-1]);  

}  }  

行數的確不多,但還真麻煩,我先說一下他是怎麼實現的,但具體為什麼這麼做,我不知道。

比如我們的list裡有如下幾個需要排序的元素:21,45,1,30,52,3,58,47,22,59,0,58。

排序的時候怎麼做,我們先定義若干中轉list在上述**中定義了64個元素的陣列

list<_tp, _alloc> __counter[64]; 其中裡邊存什麼呢?他們都是用來中轉用的

__counter[0]裡存放2(0+1)次方個元素

__counter[1]裡存放2(1+1)次方個元素

__counter[2]裡存放2(2+1)次方個元素

__counter[3]裡存放2(3+1)次方個元素,依次類推

那又是怎麼個存放方法呢?乙個指導原則就是當

第i個元素即__counter[i]的內容個數等於2

(i+1)

次方時,就要把__counter[i]的資料轉移給__count[i+1]。

具體過程如下:

取出第1個數21,放到__counter[0]裡,這時__counter[0]裡有乙個元素,小於2,繼續

__counter[0]: 21

__counter[1]: null

取出第2個數45,放到__counter[0]裡(不是簡單的放,而是排序放,類似兩個list做merge),這時__counter[0]裡有2個元素了,需要把這兩個元素轉移到__counter[1].

__counter[0]: null

__counter[1]: 21,45

取出第3個數1,放到__counter[0]裡,__count[0]與__count[1]都小於規定個數

__counter[0]: 1

__counter[1]: 21,45

取出第4個數30,放到__counter[0]裡,這時__counter[0]的個數等於2了,需要轉移到__counter[1]裡

__counter[0]: null

__counter[1]: 1,21,30,45

但這時__counter[1]裡的個數又等於4了,所有需要把__counter[1]的值轉移到__counter[2]裡,

__counter[0]: null

__counter[1]: null

__counter[2]: 1,21,30,45

然後取出52,放入__counter[0]

__counter[0]: 52

__counter[1]: null

__counter[2]: 1,21,30,45

然後取出3,放入__counter[0]

__counter[0]: 3,52

__counter[1]: null

__counter[2]: 1,21,30,45

這時候需要轉移

__counter[0]: null

__counter[1]: 3,52

__counter[2]: 1,21,30,45

然後取58

__counter[0]: 58

__counter[1]: 3,52

__counter[2]: 1,21,30,45

然後取47

__counter[0]: 47,58

__counter[1]: 3,52

__counter[2]: 1,21,30,45

需要轉移

__counter[0]: null

__counter[1]: 3,47,52,58

__counter[2]: 1,21,30,45

還需要轉移

__counter[0]: null

__counter[1]: null

__counter[2]: 1,3,21,30,47,45,52,58

還需要轉移

__counter[0]: null

__counter[1]: null

__counter[2]: null

__counter[3]: 1,3,21,30,47,45,52,58

然後再取59

__counter[0]: 59

__counter[1]: null

__counter[2]: null

__counter[3]: 1,3,21,30,47,45,52,58

然後取0

__counter[0]: 0,59

__counter[1]: null

__counter[2]: null

__counter[3]: 1,3,21,30,47,45,52,58

需要轉移

__counter[0]: null

__counter[1]: 0,59

__counter[2]: null

__counter[3]: 1,3,21,30,47,45,52,58

最後取58

__counter[0]: 58

__counter[1]: 0,59

__counter[2]: null

__counter[3]: 1,3,21,30,47,45,52,58

腦算流程總算完了,但**還是很難理解,先看乙個幾個相關的函式吧

1.splice:把當前列表的__i位置元素刪除,儲存在__position裡

[cpp]void list::splice(iterator __position, list&, iterator __i)  

[cpp]view plain

copy

void

list::splice(iterator __position, list&, iterator __i)  

2.merge:把引數list的元素合併到當前list,引數list的內容會清空的

[c-sharp]void list<_tp, _alloc>::merge(list<_tp, _alloc>& __x)

/* written     by     maik */

stl中的list被實現為環狀的雙向鍊錶,設定乙個「哨兵」node作為end( )。鑑於list的記憶體分配模型,list不能使用通用的標準sort演算法,而是實現自身的sort,但是list有自己的成員函式sort()可供其自身呼叫,其實際模型是基於合併排序的。普通的mergesort直接將待排序的序列一分為二,然後各自遞迴呼叫mergesort,再使用merge演算法用o(n)的時間將已排完序的兩個子串行歸併,從而總時間效率為n*lg(n)。(mergesort是很好的排序演算法,絕對時間很小,n*lg(n)之前的係數也很小,但是在記憶體中的排序演算法中並不常見,我想可能主要還是因為耗空間太多,也是o(n)).

不過list_sort所使用的mergesort形式上大不一樣:將前兩個元素歸併,再將後兩個元素歸併,歸併這兩個小子序列成為4個元素的有序子串行;重複這一過程,得到8個元素的有序子串行,16個的,32個的。。。,直到全部處理完。主要呼叫了swap和merge函式,而這些又依賴於內部實現的transfer函式(其時間代價為o(1))。該mergesort演算法時間代價亦為n*lg(n),計算起來比較複雜。list_sort中預留了 64個temp_list,所以最多可以處理2^64-1個元素的序列,這應該足夠了。

/* written     by    lamar */

類似2進製,每一次進製都是相鄰高位數值的一半,所以是類2進製地。例如8,低位4滿之後會進4個到8的。

stl中list的sort 函式解析

list不能使用stl演算法sort 必須使用自己的sort member function,因為stl演算法sort 只接受randomaccessiterator,而list提供的是 bidirectional iterators 演算法描述 templatevoid list sort tem...

STL中的sort演算法

上圖表明了關於sort演算法的兩大要點 sort randomacessiterator it1,randomacessiterator it1 即,sort演算法的輸入形參是兩個,而且必須都是隨機迭代器 貌似只有vector和deque滿足?sort預設的排序結果是從小到大。關於stl的sort演...

STL 中list的sort 方法使用總結

1 list中資料型別為基本型別,例如為整數型別排序 include include using namespace std int main return 0 輸出為 2 list中的型別為自定義型別 比方說是乙個自定義的類,那麼如果想為這個類所生成的物件排序的話,因為list.sort 預設排序...