關係是有序對的集合c++
如下均假設R是集合A上的二元關係:算法
設R是集合A上的一個關係,若是R是自反的、反對稱的和可傳遞的,則稱R是集合A的偏序關係,簡稱偏序,記做「≤」。這裏的符號不只僅指咱們以前學過的具體符號,而是偏序的符號,固然小於等於號(對應的關係)自己是典型的偏序關係。
通常將一個集合A和定義在其上的偏序關係R一塊兒稱爲偏序集。
wiki定義:https://en.wikipedia.org/wiki/Partially_ordered_set#Strict_and_non-strict_partial_orders
對於集合A中的元素x和y而言,若是有序對<x, y>或者<y, x>屬於偏序關係R,則稱x和y是可比較的(comparable),不然稱x和y是不可比較的(incomparable)。若是集合A中的任意兩個元素之間是可比較的,則稱偏序關係R爲全序關係(total order)。數組
對於一個偏序集A,R,若是對於A中的任意兩個元素x和y,有序對<x, y>和<y, x>至少有一個屬於關係R,則稱R爲序關係,A和R一塊兒稱爲全序集合/有序集。和上面的定義本質上是同樣的。數據結構
舉例:一個偏序集而不是全序集的例子,集合的包含關係,兩個集合間多是不可比較的。函數
上述定義的偏序集能夠認爲是非嚴格的,主要是爲了與下面的嚴格偏序集作對比:
一個嚴格偏序關係須要具備以下性質:
反自反性,傳遞性和反對稱性。記做小於號符號,和上面的定義相似,這裏僅做爲一個符號使用,固然咱們熟悉的小於號對應的關係是典型的嚴格偏序關係。flex
若是一個嚴格偏序集(集合A與定義在集合A上的嚴格偏序關係R)的關係R知足:若是A上的元素x,y,z,x和y是不可比較的,y和z是不可比較的,則x和z是不可比較的。那麼稱這樣的關係爲嚴格弱序關係,也就是說具備可傳遞的不可比較性。ui
一個等價關係應該具備以下性質:
自反性,傳遞性,對稱性。
注意到,嚴格弱序集上的不可比較的關係(incomparability relation)是一種等價關係。 // 我的猜想,官方說法很模糊。
證實:
//注意理解,不可比較關係是依附於某個關係定義的,便是關係的關係。
//自反性:x和x是不可比較的,由於嚴格弱序是反自反的,因此!(xRx) && !(xRx)爲真。
//傳遞性:!(xRy) && !(yRx)爲真,!(yRz) && !(zRy)爲真,則因爲嚴格弱序關係的額外性質,便可傳遞的不可比較性,所以!(xRz) && !(zRx)爲真,不可比較關係是傳遞的
//對稱性:!(xRy) && !(yRx)爲真,則因爲邏輯運算左右兩側交換不影響結果,所以不可比較關係是對稱的。
因此說嚴格弱序關係的定義保證了定義在其上的不可比較關係是等價關係。
wiki : https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderingsurl
以上是前導知識,如今看下今天要說的c++中的一個concept:Compare。這個concept在c++的標準庫中普遍涉及並使用,例如關聯容器set和map中,算法sort中等等,url : https://en.cppreference.com/w/cpp/named_req/Compare
具體的requirements見上連接便可,總的來講就是知足Compare的類的對象是一個函數對象,等同於關係,其兩個參數等同於元素,這個關係應該是一個嚴格弱序關係。code
注意標準中的這句話:Note: comp
induces a strict total ordering on the equivalence classes determined by equiv
這個嚴格弱序關係在equiv定義的等價類上是一個嚴格全序關係
//equiv就是上文中的不可比較關係(也是等價關係),原集合能夠被劃分爲不一樣的等價類,每一個等價類是一個子集合,該集合中的元素兩兩等價。
這其實很好理解,只要x和y來自不一樣的等價類,那麼<x, y>或者<y, x>至少有一個屬於嚴格弱序關係的集合--由於根據定義都不屬於的話x和y確定在一個等價類中。對象
所以,當你爲map和set以及可重複版本提供自定義類型的key時,以及對自定義類型的對象進行sort排序時(不管使用默認版本仍是提供比較函數,由於默認版本最終仍是要調用operator<)都要注意,你定義的關係須要知足嚴格弱序關係。
以後會舉一個例子說明,這種狀況並很多見,並且有時候比較複雜和隱晦。
以前寫過一個將三維物體體素化的程序(數值模擬中也叫網格剖分),該程序準備工做部分的主要流程以下:
void StlEntity::init_topo() { //1.遍歷三角面片,構造三角面片索引表 //構造點索引表,記錄每一個點所在的三角面片索引 _create_tria_set_and_point_set_(); //合併相同點,並繼承所屬三角面片信息 _merge_point_set_(); //此時節點合併完成,且每一個節點所屬於的三角面片的索引更新完成。 //爲每一個三角面片設置頂點索引 _set_point_index_of_tria_set_(); //構建邊索引集合 _create_edge_set_(); //合併重複邊 _merge_edge_set_(); //給每一個三角面和點設置邊索引 _set_edge_index_for_tria_and_point_set_(); //拓撲檢查 topo_check(); }
準備部分主要是將STL格式文件中的數據讀入內存,而後經過分析和處理構建等價的內部表示,最後進行拓撲檢查。這麼作的緣由主要有兩個,其一是後續的體素化過程的一些處理須要特殊的數據結構支持,其二是爲了進行拓撲檢查,由於當三維實體特徵十分複雜時特別容易出現STL缺陷,例如縫隙,多餘三角面片,空洞等等,這些缺陷須要被儘早識別出來並處理掉,不然後續的算法會發生錯誤。
其中第二部分合並相同點,須要對三維點的集合作一個排序,讓三維空間中同一個點在數組中相鄰,而後經過一遍掃描工做就能夠合併相同點了。注意,理論上相同的點在表示上並不必定是相等的,由於STL文件的轉換自己具備偏差,並且導入內存時計算機表示浮點數自己會損失精度,那麼咱們如何提供三維空間點的operator<函數,才能正確使用std::sort呢?
下面是個人實現:
struct point { double x; double y; double z; ... bool operator<(const point& other) const { if (x < other.x) { return true; } if (x == other.x && y < other.y) { return true; } if (x == other.x && y == other.y && z < other.z) { return true; } return false; } ... };
下面證實上述operator<定義的關係在三維空間點組成的集合中是一個嚴格弱序關係。
綜上,operator<定義的關係在三維空間點組成的集合中是一個嚴格弱序關係。