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...