1. 程式人生 > 其它 >轉載:C++ STL排序演算法

轉載:C++ STL排序演算法

技術標籤:C++

東陽的學習筆記

原文連結:https://www.cnblogs.com/cloudplankroader/p/10434931.html

在介紹排序演算法前,先說明一個可以稱為排序準則的東西,也就是定義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.必須具有等效傳遞性,大致上來說就是如果ab&&bc,那麼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個元素排序

快速排序的一次patation操作

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++;
    }
}

執行結果

img

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

Heap 演算法

即堆排序演算法。heap 可被視為一個以序列式群集實作而成的二叉樹,具有兩大性質。

  1. 第一個元素總是最大
  2. 總是能在對數時間內增加或移除一個元素

heap是實作 priority queue(其內元素會自動排序)的一個理想結構。因此,heap演算法在 priority_queue 容器中有所應用。為了處理 heap, STL提供以下四種演算法:

  1. make_heap() 將某區間內的元素按照某種準則轉化為 heap
  2. push_heap() 對heap增加一個元素
  3. pop_heap() 對著heap取出下一個元素
  4. sort_heap() 將heap轉化為一個已序群集(此後他便不再是heap了)

最後是一個比較詳細的C++演算法庫整理

https://blog.csdn.net/xyqqwer/article/details/81263060