C 程式設計筆記之sort

2021-08-01 10:22:57 字數 3316 閱讀 8156

1、sort實現

stl中的sort呼叫了兩個函式,

__introsort_loop:可以避免最壞情況的快速排序;

__final_insertion_sort:插入排序

template

inline

void sort(_randomaccessiter __first, _randomaccessiter __last)

}

為什麼有兩個排序搭配:

這是因為stl實現的策略是當需要排序的元素個數少於某個閾值的時候,就從快速排序轉換成插入排序。

因為資料量很少的時候,插入排序效果並不差,而且關鍵的是不需要遞迴。

現在先看看快速排序的實現:

//lg是2^k <= n中的最大k值

template

inline _size __lg(_size __n)

template

void __introsort_loop(_randomaccessiter __first,

_randomaccessiter __last, _tp*,

_size __depth_limit)

--__depth_limit;

_randomaccessiter __cut =

__unguarded_partition(__first, __last,_tp(__median(*__first,*(__first + (__last - __first)/2),*(__last - 1))));//對於陣列左邊使用while進行遞推

__introsort_loop(__cut, __last, (_tp*) 0, __depth_limit);//對右邊進行遞迴?????????

__last = __cut;

}}

__unguarded_partition:根據pivot將區間分割為兩個子串行,注意該函式是沒有邊界檢查的

template

_randomaccessiter __unguarded_partition(_randomaccessiter __first, _randomaccessiter __last, _tp __pivot)

}

其中的pivot用的是三中值法,這可以避開最壞情況:

就是在頭尾和中點的值進行比較,取中間的值作為pivot。

__median(*_

_first,*(_

_first + (_

_last - _

_first)/2),*(__last - 1)))

插入排序:

為什麼要接近排完序的陣列,還需要分大小進行分段插入排序呢?

template

void __final_insertion_sort(_randomaccessiter __first,

_randomaccessiter __last)

else

__insertion_sort(__first, __last);

}

template

void __insertion_sort(_randomaccessiter __first, _randomaccessiter __last)

__insertion_sort最終又會呼叫__linear_insert

該函式會首先判斷,最小值是否已經在最左邊了,如果不是直接將元素整體後移一位,將新值放在最左邊。

template

inline

void __linear_insert(_randomaccessiter __first, _randomaccessiter __last, _tp*)

else

//否則執行插入排序

__unguarded_linear_insert(__last, __val);

}

unguarded_linear_insert

這個函式輸入乙個迭代器,只要判斷val的值比指標所指的值小,指標就往前移動一格,直至val不小於指標所指值。

插入排序在判斷逆序對同時還要判斷*next是否大於0,也就是邊界的判斷,但是__linear_insert中的第乙個if判斷,已經保證最小值將必然在陣列的最左邊了,所以就不用再判斷是否越界了。

這樣又可以省下比較操作。

template void __unguarded_linear_insert(_randomaccessiter __last, _tp __val) 

*__last = __val;

}

所以為什麼要接近排完序的陣列,還需要分大小進行分段插入排序呢?

大體上還是因為__unguarded_insertion_sort的效率比較高,但是__unguarded_insertion_sort又沒有邊界檢查,所以先用 __insertion_sort來進行確保邊界問題,整個序列的最小值就在最左邊。

2、根據快排思路,自己實現

首先是medianofthree:

選取的三個值將會按照公升序排列,遞增地順序:a[left]—a[middle] ——a[right],顯然,此時a[right]比a[middle]大,所以可以將pivot放置在right-1的位置,這樣就可以使得a[right]此時已經在pivot的右邊了。

const

int medianofthree(vector &nums,int

left,int

right)

void qiucksort(vector

&nums,int left,int right)

while(a[--j] > pivot){}

if(i < j)

swap(a[i],a[j]);

else

break;

}swap(a[i],a[right-1]);//此時i,j交替,i就是右邊區間第乙個值,顯然右邊區間所有值都大於等於pivot,所以更換有利。

quicksort(nums,left,i-1);

quicksort(nums,i+1,right);

}

3、stl的遞迴與遞推

(1)中原始碼中我曾經有些疑問,就是為什麼左邊是遞推右邊是遞迴呢?

其實這跟陣列個數小於閾值後使用插入是乙個道理。為了減少遞迴呼叫的開銷,一半是遞迴一半是遞推,__last = __cu之後,再進行一次while迴圈,最終會呼叫partition進行分割的。

STL學習筆記之sort演算法

stl所提供的各式各樣的演算法中,sort 是最複雜龐大的乙個。這個演算法接受兩個隨機訪問迭代器,然後將區間內的所有元素以漸增方式由小到大重新排列。還有個版本則允許使用者指定乙個仿函式,作為排序標準。stl中的所有關係型容器都擁有自動排序功能,所以不需要sort演算法。序列式容器中的stack,de...

shell程式設計sort

sort 命令對 file 引數指定的檔案中的行排序,並將結果寫到標準輸出。如果 file 引數指定多個檔案,那麼 sort 命令將這些檔案連線起來,並當作乙個檔案進行排序。sort語法 root www sort fbmnrtuk file or stdin 選項與引數 f 忽略大小寫的差異,例如...

C 之sort 函式用法集合

defined in header 對陣列或容器內區間 first,last 中的元素進行特定的排序 template class randomit void sort randomit first,randomit last template class randomit constexpr vo...