編寫c++經常需要使用sort進行排序,有可能是簡單的陣列、數字vector或者是複雜一點的存放物件的vector。
c++為了滿足使用者的需求,在algorithm裡面封裝了sort泛型演算法。所以使用時,必須#include < algorithm>
template void sort (randomaccessiterator first, randomaccessiterator last);
template void sort (randomaccessiterator first, randomaccessiterator last, compare comp);
可以看見,sort原型分為兩個,區別在於第乙個函式有兩個引數,第乙個函式有三個引數。
其中兩個函式都有的是 randomaccessiterator 是隨機訪問迭代器,first是初始位置,last是末尾位置,預設使用迭代器引用的 operator < 進行排序。
第二個函式,前兩個引數一樣,也是用來說明從哪兒到哪兒排序。第三個引數是compare,意思是使用comp這個「方法」對物件進行排序。comp可以是函式物件或者是函式指標,具體使用請看後面。
使用兩個引數這應該是最普遍也是最簡單的情景,如果只有兩個引數,預設使用 operator < 對陣列排序,結果為公升序。
對陣列排序:
int arr = ;
sort(arr, arr + 9);
需要注意的是,這裡傳入的是迭代器,所以要傳入頭指標和末尾指標(最後乙個待排元素的後乙個位置)
對vector排序:
vectorarr;
for (int i = 9; i > 0; i--)
arr.push_back(i);
sort(arr.begin(), arr.end());
這裡直接傳入vector的begin和end兩個迭代器就對整個vector完成了排序。
物件排序
如果只使用兩個引數的話,要對物件排序,那麼只能依靠過載運算子來實現。而且必須過載的是<關係運算子。
class test ;
test(int x) : value(x) {};
// 過載運算子
bool operator < (const test& t)
};...
vectorarr;
for (int i = 9; i > 0; i--)
sort(arr.begin(), arr.end());
這樣,就根據test類中value的值來公升序排物件的順序了。
那麼有讀者肯定會問,如果我想要降序排列,或者我有我自己的比大小規則,或者對於物件我不想過載運算子怎麼辦呢?
那麼這裡就要用到我們sort的第三個引數了,之前提到了,第三個引數是決定以什麼「方法」進行排序的。可以傳入函式物件和函式指標。那麼這個引數如何填入,如何編寫便成了最主要的問題。
假如我們還是存的之前那個類,唯一的區別是,我不再過載運算子了,那要怎麼辦呢?
class test ;
test(int x) : value(x) {};
};
那麼,我們可以自己自定義編寫比較函式,來決定兩個元素是如何比較的。
bool cmp_func(const test& t1, const test& t2)
vectorarr;
for (int i = 9; i > 0; i--)
sort(arr.begin(), arr.end(), cmp_func);
如上,定義了乙個cmp_func,直接將sort的第三個引數指定為cmp_func就可以對迭代器引用區的元素進行排序。例如這裡可以實現根據test中value的值來實現公升序排列這些物件了。
當然,也可以通過修改比較函式來實現降序。
bool cmp_func(const test& t1, const test& t2)
函式物件其實很簡單,可以很好的代替函式指標,但它理解起來非常簡單,過載了()運算子的物件就叫函式物件。之所以叫函式物件,是因為它的呼叫可以和函式看起來一樣。
class test ;
test(int x) : value(x) {};
// 過載運算子
bool operator () (const test& t1, const test& t2)
};vectorarr;
for (int i = 9; i > 0; i--)
sort(arr.begin(), arr.end(), test());
這個原理其實就是第三個引數,臨時建立了乙個test物件,假設這個物件為t。
那麼**就是 sort(arr.begin(), arr.end(), t)
然後會把比較的兩個元素,通過函式物件的呼叫 t(t1, t2)來進行比較,所以他會正常工作。
sort排序利用的是 快排/堆排/插排,所以並不穩定,如果對穩定性有需求,請使用stable_sort()
那麼,其實讀到這裡,細心的讀者會想問,我引入自定義函式和函式物件後,什麼叫「大」?什麼叫「小」?我要怎麼得到理想的排列順序?
例如,為什麼降序就是那麼自定義函式,返回值是true又發生了什麼?。
實際呼叫sort時,第三個引數compare comp對應的是乙個函式物件或者函式的名字。comp對應的功能,是教sort怎麼排序的,我們可以稱之為「比較器」。
其實,前面提到了,sort演算法比較元素,預設是通過<運算子進行的,達到的效果是它天然就是要公升序排列。那我們可以理解為,它其實預設寫了乙個comp是這樣的。
bool comp(const t& t1, const t& t2)
如果把傳入的第乙個元素比第二個元素小成立(返回值為true),那麼會把第乙個元素往前挪,第二個元素往後挪。
那麼我們現在把小改為任意比較 @。如果第乙個元素@第二個元素成立,那麼會把第乙個元素往前挪,第二個元素往後挪。
所以把@改成》,就實現了降序排列,因為如果第乙個元素比第二個大,那麼大的都往前挪,小的都往後挪,自然就是降序了。
學術一點來說,stl關聯容器中的元素是從小到大排序的。使用關聯容器時,可以用自定義的「比較器」來取代<運算子,以規定元素之間的大小關係。所以以下三者是等價的:
也就是說,我如果從邏輯上遵循了這個規則,那麼會達到公升序的效果。
那麼把小於改成任意關係運算子@,在自定義比較關係時 bool comp(x, y),以下三條是等價的
(!@表示@的逆關係)
例如把這個@替換為 > ,如何規定自己的比較函式和函式物件就顯而易見了。
利用STL中的sort進行成績排序
用一維陣列儲存學號和成績,然後,按成績排序輸出。輸入第一行包括乙個整數n 1 n 100 代表學生的個數。接下來的n行每行包括兩個整數p和q,分別代表每個學生的學號和成績。按照學生的成績從小到大進行排序,並將排序後的學生資訊列印出來。如果學生的成績相同,則按照學號的大小進行從小到大排序。示例1 3 ...
利用sort對結構體進行排序
我定義了乙個學生型別的結構體來演示sort排序對結構體排序的用法 具體用法看 include include include sort函式包含的標頭檔案 using namespace std 定義乙個學生型別的結構體 typedef struct student student 這是函式是sort...
利用sort排序
京東筆試題 說是一批訂單,包含名字和 讓實現乙個函式按照 排序 struct items bool com items a,items b int main sort vec.begin vec.end com for int i 0 i 5 i cout 找出一組陣列中前k個最小的數 用排序的話時...