C 泛型演算法基礎

2021-07-02 15:02:51 字數 3247 閱讀 4553

順序容器只定義了很少的操作,我們希望容器支援更多的操作。c++標準庫為了滿足更多開發者的需求,實現了一些經典演算法的公共介面,因為這些演算法不依賴於具體的容器,而是借助迭代器對容器進行操作,所以常稱其為泛型演算法

泛型演算法都定義在標頭檔案中,少數數值型演算法定義在標頭檔案中。

一般情況下,演算法不會直接操作容器,而是借助容器的迭代器來遍歷、操作容器中的元素。而且,大多數演算法絕對不會改變容器的長度。(erase和insert等操作不是演算法,而是「容器操作」,注意分清)

唯讀演算法會讀取輸入範圍內的元素,而絕對不會改變元素,這種情況下我們一般使用常量迭代器。

if (it != intvec.cend())

cout << *it

<< endl;

find查詢容器中是否存在值為value的元素,如果不存在返回尾後迭代器。

auto sum = accumulate(intvec.cbegin(), intvec.cend(), 0);
accumulate定義在標頭檔案中,用來求容器中一段範圍的和,第三個引數是sum的初始值,注意初始值的選取和容器中元素的型別是有關係的。如果是double型要初始化為0.0.

值得一提的是,accumulate並不支援所有的元素型別。

元素型別必須定義了「+」操作才可以用accumulate。

例如:

vector

vec =;

auto sum = accumulate(vec.cbegin(),vec.cend()," ");

因為char*並不支援『+』操作,所以編譯器報錯,如果是vector是可以的。

equal(c1.cbegin(), c1.cend(), c2.cbegin());
該演算法接收三個迭代器。前兩個迭代器表示第乙個序列的範圍,第三個迭代器是第二個序列的起始迭代器位置。這個演算法基於這樣的程式設計假設:

1.c1和c2容器型別不必相同,但是容器中的元素型別必須相同

2.容器中的元素型別必須支援「==」操作。(例如某些自定義類可能沒有過載「==」運算子,那麼就不能用該演算法)

3.第二個序列的長度至少和第乙個序列的長度相同

前邊曾經提到過,絕大部分演算法不會修改容器的長度,這好像限制了某些操作。

例如:

vector

intvec;//空容器

fill_n(intvec.begin(), 10, 0);

這裡執行會報錯。因為規定演算法不可以修改容器的長度,此時容器長度為0。這一點很容易出現致命錯誤,因為編譯器不會檢查演算法的寫操作是否合法,需要程式設計師保證

我們可以先分配給intvec一些空間後,再指向fill_n操作。

intvec.resize(20);

fill_n(intvec.begin(), 10, 0);

注意這裡是resize而不是reserve。vector 的reserve增加了vector的capacity,但是它的size沒有改變!而resize改變了vector的capacity同時也增加了它的size!

除了剛才的方法,還可以用一種叫做」插入迭代器」的方式來得到我們期望的結果。

插入迭代器back_inserter是一種」迭代器介面卡「。

介面卡是一種介面轉換器,它可以讓一種東西看起來像另一種東西。

在這裡back_inserter使得迭代器能夠像函式push_back進行一樣的操作,它使得乙個迭代器看起來像是呼叫了push_back一樣。

fill_n(back_inserter(intvec), 10, 0);//新增10個0到intvec中去
這裡在提醒一下,我們之前說過演算法不可以改變容器的size,那這裡為什麼可以成功執行不出錯呢?

原因在於,演算法操作了乙個迭代器,迭代器可以完成向容器中新增元素的功能,但是演算法本身永遠不會這麼做,所以和我們之前說的並不矛盾。

auto it1 = back_inserter(intvec);//插入器繫結到了intvec上並且生成了乙個迭代器it

*it1 = 10;//相當於intvec.push_back(10)

除了back_inserter之外還有front_inserter(呼叫push_front)和inserter呼叫容器操作的inserter

例如:auto it3 = inserter(intvec, intvec.begin())在intvec.begin()位置之前呼叫insert()容器操作。

當然,vector並不可以使用front_inserter(),因為vector上沒有定義push_front操作。

vector

l;copy(intvec.cbegin(), intvec.cend(), l.begin());

l是空容器,l.size() == 0,copy不可以改變其size所以操作出錯。可以預先改變l的size或者利用back_inserter

改變l的size:

vector

l;l.resize(100);

copy(intvec.cbegin(), intvec.cend(), l.begin());

利用back_inserter

vector

l;copy(intvec.cbegin(), intvec.cend(), back_inserter(l));

replace(l.begin(), l.end(), 0, 101);
將l的所有0替換為101.

C 泛型基礎

泛型的基本思想 泛型程式設計 generic programming 是一種語言機制,通過它可以實現乙個標準的容器庫。像類一樣,泛型也是一種抽象資料型別,但是泛型不屬於物件導向,它是物件導向的補充和發展。在物件導向程式設計中,當演算法與資料型別有關時,物件導向在對演算法的抽象描述方面存在一些缺陷。比...

基礎 C 泛型

msdn 章節內容 ms help 泛型是 2.0 版 c 語言和公共語言執行庫 clr 中的乙個新功能。泛型將型別引數的概念引入 net framework,型別引數使得設計如下類和方法成為可能 這些類和方法將乙個或多個型別的指定推遲到客戶端 宣告並例項化該類或方法的時候。例如,通過使用泛型型別引...

C 泛型基礎

泛型的基本思想 泛型程式設計 generic programming 是一種語言機制,通過它可以實現乙個標準的容器庫。像類一樣,泛型也是一種抽象資料型別,但是泛型不屬於物件導向,它是物件導向的補充和發展。在物件導向程式設計中,當演算法與資料型別有關時,物件導向在對演算法的抽象描述方面存在一些缺陷。比...