<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    PS,1880后程序員

    看不完的牙,寫不完的程序,跑不完的步。
    隨筆 - 97, 文章 - 34, 評論 - 10, 引用 - 0
    數據加載中……

    C++ Primer 之 讀書筆記 第十一章

     

    泛型算法

    算法為了保持獨立性,不使用容器類型,而使用迭代器。

    算法絕不執行容器操作。算法僅僅是根據迭代器和迭代器操作來操作的。因此所有會改變迭代器的操作在通用算法里都不會出現。例如增加或刪除元素。但是這些通用算法有可能會修改容器中元素的值,也可能會在容器中移動元素。

    11.2 初窺算法

    必須要包含一下的頭文件:

    #include <algorithm>

    #include <numeric>

    只讀算法

    accumulate

    這個算法的參數很好說明了算法實際上是不知道元素的類型的。第三個參數指定了起始值,因為accumnulate不知道它正在匯總的元素的類型。

    int sum = accumulate(vec.begin(), vec.end(), 42);

    另一個例子:

    string sum = accumulate(v.begin(), v.end(), string(""));

    這里一定要指定起始值是string,而絕不能寫成字符串常量,因為字符串常量對應的數據類型是const char*。

    有趣!

    find_first_of

    需要兩對迭代器:

    size_t cnt = 0;

    list<string>::iterator it = roster1.begin();

    // look in roster1 for any name also in roster2

    while   ((it = find_first_of(it, roster1.end(),

                 roster2.begin(), roster2.end()))

                    != roster1.end()) {

       ++cnt;

       // we got a match, increment it to look in the rest of roster1

       ++it;

    }

    roster1list,roster2可以是deque,vector,只要我們可以用==操作比較這兩個序列中的元素。尤其是:如果 roster1 list<string> 對象,則 roster2 可以是 vector<char*> 對象,因為 string 標準庫為 string 對象與 char* 對象定義了相等(==)操作符。

    總結一下迭代器實參類型

    標記范圍的兩個實參類型必須精確匹配,必須指向同一個容器中的元素(或者超出容器末端的下一位置),并且如果兩者不相等,則第一個迭代器通過不斷地自增,必須可以到達第二個迭代器。

    帶有兩對迭代器參數。每對迭代器中,兩個實參的類型必須精確匹配,但不要求兩對之間的類型匹配。特別是,元素可存儲在不同類型序列中,只要這兩序列的元素可以比較即可。

    寫容器算法

    寫容器算法最重要的一點是必須保證算法所寫的序列至少要和被寫入的元素數目一樣大。(we must take care to ensure that the sequence into which the algorithm writes is at least as large as the number of elements being written.)就是說如果指定的要寫入的序列范圍必須是有效的,必須大于要寫入的元素數目,就是說不能越界。

    看個最一目了然的例子就是:

    vector<int> vec; // empty vector

    // disaster: attempts to write to 10 (nonexistent) elements in vec

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

    back_inserter

    使用back_inserter之所以安全,是因為如果指定的范圍越界,它執行的并不是數據修改操作而是數據添加操作。

    容器元素重新排序算法

    unique

    sort

    stable_sort

    謂詞predicates

    再次解讀迭代器Iterators

    三類迭代器:

    insert iterators插入迭代器

    iostream iterators

    reverse iterators反向迭代器

    insert iterators

    inserter是迭代器適配器,它和容器綁定,產生一個迭代器,這個迭代器向綁定的容器插入元素。當我們通過inserter迭代器賦值時,迭代器插入新的元素。(An inserter is an iterator adaptor that takes a container and yields an iterator that inserts elements into the specified container. When we assign through an insert iterator, the iterator inserts a new element.

    又分成3類:

    • back_inserter:使用push_back創建一個迭代器
    • front_inserter: 使用push_front創建一個迭代器
    • inserter:在指定的位置后創建迭代器

    list<int> ilst, ilst2, ilst3;     // empty lists

    // after this loop ilst contains: 3 2 1 0

    for (list<int>::size_type i = 0; i != 4; ++i)

         ilst.push_front(i);

    // after copy ilst2 contains: 0 1 2 3

    copy (ilst.begin(), ilst.end(), front_inserter(ilst2));

    // after copy, ilst3 contains: 3 2 1 0

    copy (ilst.begin(), ilst.end(), inserter (ilst3, ilst3.begin()));

    iostream iterators

    istream_iterator:input stream

    ostream_iterator:output stream

    定義流迭代器stream Iterators

    流迭代器都是模板Templates。Example:

    istream_iterator<int> cin_it(cin);    // reads ints1 from cin

    istream_iterator<int> end_of_stream; // end iterator value

    while(cin_it != end_of_stream)

    {

       //do something

    }

    // writes Sales_items from the ofstream named outfile

    // each element is followed by a space

    ofstream outfile;

    ostream_iterator<Sales_item> output(outfile, " ");

    istream_iterator上的操作

    ++it & it++

    迭代器加1,一般前綴加1,返回的是增加后的迭代器的引用。后綴加1,迭代器也加1,但是返回的是未加1的那個值。

    大師給出了一個istream_iteratorostream_iterator這兩種迭代器的最經典的應用,輸入轉輸出,有這個sample這是很容易理解這兩個東西:

    // write one string per line to the standard output

    ostream_iterator<string> out_iter(cout, ""n");

    // read strings from standard input and the end iterator

    istream_iterator<string> in_iter(cin), eof;

    // read until eof and write what was read to the standard output

    while (in_iter != eof)

        // write value of in_iter to standard output

        // and then increment the iterator to get the next value from cin

       *out_iter++ = *in_iter++;

    流迭代器的限制

    1.      不能從ostream_iterator中讀入數據,同時也不能向istream_iterator寫入數據(It is not possible to read from an ostream_iterator, and it is not possible to write to an istream_iterator.

    2.      一旦給ostream_iterator賦值,這個寫入的操作就提交了。一旦賦值,在后續的操作中就不能修改。此外,每個ostream_iterator只能用作輸出一次。(Once we assign a value to an ostream_iterator, the write is committed. There is no way to subsequently change a value once it is assigned. Moreover, each distinct value of an ostream_iterator is expected to be used for output exactly once.

    3.      ostream_iterator里沒有->操作。

    基于流迭代器使用算法

    既然流迭代器基本上可以看做一般意義上的迭代器,那么前面所描述的算法應該同時也適用在流迭代器上。于是,針對流迭代器,我們也可以進行排序,比較等算法操作。

    istream_iterator<int> cin_it(cin);    // reads ints from cin

    istream_iterator<int> end_of_stream; // end iterator value

    // initialize vec from the standard input:

    vector<int> vec(cin_it, end_of_stream);

    sort(vec.begin(), vec.end());

    // writes ints to cout using " " as the delimiter

    ostream_iterator<int> output(cout, " ");

    // write only the unique elements in vec to the standard output

    unique_copy(vec.begin(), vec.end(), output);

    reverse iterators

    從這張圖上可以看出普通迭代器和反向迭代器的區別,另外二者都能夠執行自增和自減操作,形式是一樣的,但本質是不同的。例如形式上都是自增,迭代器都會由beginend方向移動,但是二者卻是反方向的。這樣做的最大好處是:我們能夠透明地使用算法向前或者向后處理容器。

    利用迭代器處理string

    可以達到javaStringToken的功能:我喜歡這段代碼

    // find first element in a comma-separated list

    string::iterator comma = find(line.begin(), line.end(), ',');

    cout << string(line.begin(), comma) << endl;

    反向迭代器獲得最后一個單詞:

    // find last element in a comma-separated list

    string::reverse_iterator rcomma = find(line.rbegin(), line.rend(), ',');

    // wrong: will generate the word in reverse order

    cout << string(rcomma.base(), line.end()) << endl;

    反向迭代器可以代表迭代器范圍以及這個范圍是不對稱的事實產生一個重要的結論。當我們用一般的迭代器對反向迭代器初始化或者賦值時,所得到的迭代器所指向的元素和初始值不一樣。(The fact that reverse iterators are intended to represent ranges and that these ranges are asymmetric has an important consequence. When we initialize or assign a reverse iterator from a plain iterator, the resulting iterator does not refer to the same element as the original.

    泛型算法結構

    Nothing to say。

    其實就是對算法進行了分類,同時對于算法的命名習慣加以闡述,看完了,覺得跳過也無妨哈。

    容器特有算法

    就是針對list,為了性能優化,對于算法,list重新實現。

    posted on 2009-06-04 11:22 amenglai 閱讀(583) 評論(1)  編輯  收藏 所屬分類: C++ Primer 之 讀書筆記

    評論

    # re: C++ Primer 之 讀書筆記 第十一章  回復  更多評論   

    back_inserter

    應該是插入迭代器,默認調用的push_back。不管超出還是不超出。
    2009-06-28 17:11 | zwyd34@sina.com
    主站蜘蛛池模板: 青青草国产免费久久久下载| 亚洲AV中文无码字幕色三| 国产精品永久免费视频| 亚洲精品卡2卡3卡4卡5卡区| 99久久久精品免费观看国产| 污视频网站免费在线观看| 亚洲成AV人片天堂网无码| 大学生美女毛片免费视频| 精选影视免费在线 | 亚洲精品国产国语| 亚洲精品美女久久久久99| 德国女人一级毛片免费| 毛片免费在线观看| 美女扒开尿口给男人爽免费视频| 亚洲国产高清人在线| 免费A级毛片无码A∨男男| 4hu四虎最新免费地址| 好猛好深好爽好硬免费视频| 亚洲狠狠婷婷综合久久蜜芽| 亚洲AV无码成人专区片在线观看| 免费毛片网站在线观看| 67194成手机免费观看| 伊人免费在线观看| 欧洲亚洲综合一区二区三区| 337p欧洲亚洲大胆艺术| 久久影视国产亚洲| 国产性生交xxxxx免费| 无码专区永久免费AV网站| 久久精品成人免费网站| 午夜不卡AV免费| 亚洲国产美女精品久久久| 亚洲精品亚洲人成在线观看麻豆 | 亚洲精品一级无码中文字幕| 在线a级毛片免费视频| 99在线视频免费| 国产一二三四区乱码免费| 羞羞网站在线免费观看| 亚洲欧美中文日韩视频| 亚洲国产成+人+综合| 亚洲伦理一区二区| 亚洲av中文无码乱人伦在线咪咕|