C 中利用sort進行排序

2022-08-12 20:36:10 字數 3515 閱讀 5594

編寫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個最小的數 用排序的話時...