STL 優先隊列的自訂比較函數與 sort() 等泛型演算法的自訂比較函數的區別

來源:互聯網
上載者:User

標籤:ble   sort   優先   style   contain   template   繼承   effective   body   

前言

  

  最近在刷演算法題,常常需要自訂比較函數作為作為函數對象送入 stl 中,遇到了下面的問題:

   泛型演算法 sort() 的比較函數是這麼寫: 

//sort() 實現元素間關係為遞增的比較函數struct cmp{    bool operator () (const T& a, const T& b) const    {        return a.x < b.x;    }};//或者這樣bool operator < (const T& a, const T& b) const {    return a.x < b.x;   }

 

  而優先隊列裡的比較函數是這麼寫:

//priority_queue 實現元素間關係為遞增(實現最小堆)的比較函數struct cmp {
   DataType x;
bool operator () (const T& a, const T& b) const { return a.x > b.x; }}//或者這樣struct T { Type_2 x; friend bool operator < (const T&a, const T& b) const { return a.x > b.x; }}

 

  同樣是實現元素的遞增關係即 “前驅 < 後繼”,為什麼一個是 “a.x < b.x”,一個是"a.x > b.x" 呢?

 

分析 sort() 

 

  先拿 sort() 進行分析,排序類的泛型演算法很多,它們的 cmp 寫法是相似的,這裡先看一份冒泡排序實現遞增關係如 <1, 2, 3 ..> 的寫法,法一:當傳入的 class compare 是cmp 是這個函數對象時,它會重載 () 使得 *current 、*next 進行 “<” 比較 ,如果兩個元素的關係不滿足 “<” ,則交換。

#include <iostream> template <class BidirectionalIt, class Compare> //雙向迭代器void bubble_sort(BidirectionalIt first, BidirectionalIt last, Compare comp) {    for (; first != last; --last)         for (BidirectionalIt current = first, next = first; ++next != last; ++current)             if (!comp(*current, *next))                 std::swap(*current, *next); } }//可以這麼寫struct cmp {    bool oprator ()(int a, int b) {         return a < b;     }};//或者這麼寫bool cmp (int a, int b){    return a < b;}    

 

  一言以蔽之,就是元素將按照 cmp 中定義的邏輯關係進行排列。

  雖然 sort() 是用 快排+堆排+插入實現的而並非冒泡,但是原理是一樣。

 

分析 priority_queue 

  

  現在我們再來看看優先隊列。

  STL優先隊列模板:priority_queue<Type, Container, Functional> ,參數分別對應的是 元素類型、容器類型、比較函數。

  注意,優先隊列不是 STL 的容器,而是由 底層容器 vector/deque 實現,預設情況下它利用 MAX-HEAP 實現,而 MAX-HEAP 是 vector 實現的完全二叉樹,這樣的東西稱為適配器 (adapter)。

  在優先隊列中預設優先順序高的先出隊列,具體操作是使用函數對象 less<> 重載了 “<”,所以這裡優先順序的高低是由 “<” 確定的,所以當我們按下面的形式寫:

priority_queue<int> pQueue;

  通過操作符 < 知道元素關鍵字大的優先順序高,此時是最大堆。若每次從堆頂取一個元素,最後得到一個序列,那麼序列中元素的關係是遞減的。

  我們想要讓元素的關係是遞增該怎麼做?

   第一種辦法是使用與 less<>作用相反的函數對象 greater<> 。

  第二種辦法就是使用自訂比較函數,通過它實現對自訂資料類型的優先順序的定義。

    2-1. 通過重載 operator < 操作符以比較元素的優先順序

struct T{    DataType key;    friend bool operator < (const T& a, const T& b) {        return a.key > b.key;    }};

    邏輯是這樣:假設 a.key > b.key 為 TRUE ,由於預設是最大堆,此時優先隊列會認為 a < b ,即 b 的優先順序比 a 高,所以 b會被先出隊,這樣就實現了關鍵字小的元素先出隊。最後輸出的序列是按關鍵字遞增的。

    2-2. 通過重載 operator () 以定義元素的優先順序。

struct cmp{    bool operator () (const Type& a, const Type& b) const {        return a.x > b.x;    }};

    邏輯和 2-1 是一樣的。這裡重載了 () 的目的是使得 cmp 成為像 less<> 一樣的函數對象(實質上是繼承了 less<>) ,作為新的比較比較級的規則以 priority_queue 第三個參數的形式傳入 priority_queue 中。

   

總結

 

  優先隊列的“比較級”概念與”由MAX-HEAP實現“這一特性,使得自訂比較函數中需要這麼寫: "a.x>b.x" 。

 

延伸閱讀

 

  永遠讓比較函數對相等的值返回false(來自Effective C++)

  C++中的 sort 使用自訂比較函數的具體運行過程是怎樣的呢?

 

STL 優先隊列的自訂比較函數與 sort() 等泛型演算法的自訂比較函數的區別

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.