VS 2010 std::list.sort函數實現的非遞歸merge sort

td::list.sort()採用的是mergesort算法。

merge sort的遞歸實現非常簡單,一般爲

MergeSort(1,n){

      MergeSort(1,n/2);

      MergeSort(n/2,n);

      Merge(1,n/2,n);

}

下圖爲用一個長度爲16的序列調用MergeSort形成的歸併樹(節點中的m..n是序列的下標,虛三角表示省略的子樹)

 

std::list.sort()雖然採用了merge sort算法,但實現上採用了非遞歸的方式。代碼原文見最後,以下是對於代碼的詳細分析:

_Binlist爲list的數組,數組長度爲26。

while (!empty())保持了以下循環不變量:

1. _Maxbin<=25

2. 如果n屬於[0,_Maxbin),且n!=24,則_Binlist[n]或者爲空,或者保存了已經排好序的2^^n個元素

3. 如果n屬於[0,_Maxbin),且n==24,則_Binlist[n]或者爲空,或者保存了已經排好序的>=2^^n個元素

4. 如果n>=_Maxbin,_Binlist[n]爲空

因此,執行完while後,後續的操作把[0,_Maxbin)範圍的list全部歸併起來,形成了最終的排序序列。

 

這裏有趣的是元素的歸併過程。

從邏輯上,可以認爲_Binlist[n]爲空,則_Binlist[n]取值爲1,否則取值爲0。因此_Binlist形成了一個二進制"0"和"1"的序列,即_Binlist邏輯上形成了一個整數。每次while循環處理一個新的元素,會導致_Binlist的list依次從低向高歸併,歸併的結果相當於向_Binlist整數加1;同時,_Binlist[n]取值爲1或0的含義保持不變。

通過跟蹤可知,std::list.sort()的歸併樹與遞歸調用完全相同。

 

_Binlist數組形成的邏輯整數

 

算法原文:

void sort()

                {       // order sequence, using operator<

                if (2 <= this->_Mysize)

                        {       // worth sorting, do it

                        const size_t _MAXBINS = 25;

                        _Myt _Templist(this->_Alval), _Binlist[_MAXBINS + 1];

                        size_t _Maxbin = 0;

                       

                        while (!empty())

                                {      

                                        // assert _Templist.size() == 0

                                        // sort another element, using bins

                                        // 每次循環處理一個元素

                                _Templist._Splice_same(_Templist.begin(), *this, begin(),

                                        ++begin(), 1);

 

                                size_t _Bin;

                                for (_Bin = 0; _Bin < _Maxbin && !_Binlist[_Bin].empty();

                                        ++_Bin)

                                        {       // merge into ever larger bins

                                        _Binlist[_Bin].merge(_Templist);

                                        _Binlist[_Bin].swap(_Templist);

                                        }

 

                                if (_Bin == _MAXBINS)

                                        _Binlist[_Bin - 1].merge(_Templist);

                                else

                                        {       // spill to new bin, while they last

                                                // assert _Binlist[_Bin].empty()

                                        _Binlist[_Bin].swap(_Templist);

                                        if (_Bin == _Maxbin)

                                                ++_Maxbin;

                                        }

                                }

 

                        // 從前到後合併_Bin數組,最後插入到self

                        for (size_t _Bin = 1; _Bin < _Maxbin; ++_Bin)

                                _Binlist[_Bin].merge(_Binlist[_Bin - 1]);      // merge up

                        splice(begin(), _Binlist[_Maxbin - 1]); // result in last bin

                        }

                }

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章