C++STL排序算法


在介紹排序算法前,先說明一個可以稱為排序准則的東西,也就是定義strict weak ordering,其意義如下:

1.必須是非對稱的,對operator < 而言,如果x<y是true,則y<x為false。對判斷式op()而言,若op(x,y)為true,則op(x,y)為false。

2.必須是可傳遞的,對operator < 而言,如果x<y是true且y<z為true,則x<z為true。對判斷式op()而言,若op(x,y)為true且op(y,z)為true。

op(x,z)為true。

3.必須是非自反的,對operator < 而言,x<x永遠是false。對判斷式op()而言,op(x,x)永遠為false。

4.必須具有等效傳遞性,大致上來說就是如果a==b&&b==c,那么a=c。

STL的排序算法

stl提供了幾種算法來對區間內的元素排序,一般分為完全排序(full sorting)和局部排序(partial sorting)。在可以達到使用目的的情況下,優先使用后者,因為其效能更高。但由於一些關聯式容器(set,map)和無序容器等不提供random-access iterator,所以不適用於這些排序算法。

但值得注意的是,對全體元素進行一次性排序通常比”始終維護它們保持排序狀態“效率要高,所以具體使用何種容器還要看你所需要的是什么。

排序算法頭文件

#include<algorithm>

1.完全排序

void sort(random_access_iterator_beg,random_access_iterator_end) void sort(random_access_iterator_beg,random_access_iterator_end,binary_predicate op) void stable_sort(random_access_iterator_beg,random_access_iterator_end) void stable_sort(random_access_iterator_beg,random_access_iterator_end,binary_predicate op)
  • 在這里有sort()和stable_sort(),它們默認的第一形式都是用operator < 對區間[beg,end)內的所有元素排序。
  • sort()和stable_sort()的第二形式使用binary predicate作為排序准則,也就是使用者自己去定義的排序准則。
  • 注意,op必須針對元素值定義出strict weak ordering,也就是本文開篇所介紹的內容。
  • sort()與stable_sort()的區別在於,后者更加穩定,保證相等的元素的相對次序在排序后不發生改變。

時間復雜度:

sort():平均復雜度nlogn,最壞n^2。

stable_sort():若內存足夠,則就是nlogn,不會變化。若沒有足夠內存,則復雜度是2nlogn。

比較常用的sort結構體排序

#include<iostream> #include<algorithm>
using namespace std; struct node { int num1,num2; }arr[10000]; bool cmp(node a,node b)//自定義比較准則
{ return a.num1<b.num1;//以num1較小者優先排列
} int main() { arr[0]={1,2}; arr[1]={2,1}; arr[2]={3,4}; arr[3]={4,3}; sort(arr,arr+4,cmp);//嚴格按照要求傳入參數
    for(int i=0;i<4;++i) { cout<<arr[i].num1<<" "; } cout<<endl; for(int i=0;i<4;++i) { cout<<arr[i].num2<<" "; }
return 0; }

 

2.局部排序

void partial_sort(random_access_iterator_beg,random_access_iterator_sortend,random_access_iterator_end) void partial_sort(random_access_iterator_beg,random_access_iterator_sortend,random_access_iterator_end,binary_predicate op)

 

  • 第一形式以operator < 對[beg,end)區間內元素進行排序,使[beg,sortend)區間內元素處於有序狀態。
  • 第二形式使用binary predicate作為排序准則,也就是使用者自己去定義的排序准則。
  • 除了與sort所需要注意的相同外,partial_sort()並不對全部元素排序,你傳入的參數分別是排序首部,排序尾部,整體區間尾部。它會按照你所指示的區間進行排序,不用進行多余的操作。
  • 如果sortend等於end的話,那么partial_sort()會對整個序列排序,平均而言其性能不及sort(),但最差情況則優於sort()。

時間復雜度:在線性與nlogn之間。

3.根據第n個元素排序

void nth_element(random_access_iterator_beg,random_access_iterator_nth,random_access_iterator_end) void nth_element(random_access_iterator_beg,random_access_iterator_nth,random_access_iterator_end,binary_predicate op)

 

兩種形式都對[beg,end)區間內的元素排序,使第n個位置上的元素就位,也就是說,在位置n之前的元素都小於等於它,所有之后的元素都大於等於它。這樣,你就得到了”根據n位置上的元素“分割開來的兩個子序列,第一子序列的元素統統小於第二子序列的元素,但是處於無序狀態。同樣的,該算法也提供自定義排序准則。

時間復雜度:平均為線性。

nth_element操作舉例

#include<iostream> #include<algorithm>
bool cmp(int a,int b) { return a>b; } using namespace std; int main() { int a[]={1,5,6,2,9,7,3,4,10,8}; int elem=a[2]; nth_element(a, a+3, a+10);//第一種形式,默認為<
    int i=0; while(a[i]<elem) { cout<<a[i]<<" "; i++; } cout<<endl; int b[]={1,5,6,2,9,7,3,4,10,8}; nth_element(b,b+3,b+10,cmp);//傳入重載函數
    int j=0; while(b[j]>elem) { cout<<b[j]<<" "; j++; } }

 運行結果

由此可見雖然分割出了序列,但順序是打亂的。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM