青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Impossible is nothing  
  愛過知情重醉過知酒濃   花開花謝終是空   緣份不停留像春風來又走   女人如花花似夢
公告
日歷
<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456
統計
  • 隨筆 - 8
  • 文章 - 91
  • 評論 - 16
  • 引用 - 0

導航

常用鏈接

留言簿(4)

隨筆分類(4)

隨筆檔案(8)

文章分類(77)

文章檔案(91)

相冊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

 

上次提到過為容器生成數據的問題,我給出的用 boost.lambda 的方法是

上次提到過為容器生成數據的問題,我給出的用 boost.lambda 的方法是:

? std::vector<int> vect(10);
? int i = 0;
? std::for_each( vect.begin(), vect.end(), _1 = ++var(i) );

不錯,這樣可以生成連續的數字,也還算比較簡潔,因為代碼量不會隨著容器的大小而變化,不過,如果要在容器內填入隨機數呢?其實比上面更簡單,因為 STL 的 generate 算法就是設計來做這個的:

? std::vector<int> vect(10);
? std::generate(vect.begin(), vect.end(), rand);

rand 是我們熟悉的標準 C 庫函數,這樣我們可以生成任意數量的隨機數了,不過還是有點不好的地方:每次生成的序列都是一樣的,因為 rand 生成的是偽隨機數。這個容易解決,我們必須先 seed 一下:

? std::vector<int> vect(10);
? srand(time(NULL));
? std::generate(vect.begin(), vect.end(), rand);

好了,我們終于還是用了三行(其實是兩行,聲明 vector 總是必需的吧!),但是好歹是有了一個可用的方案。回頭看看,前面的連續整數問題也可以用 generate 來做,方法不言而喻:

? std::vector<int> vect(10);
? int i = 0;
? std::generate(vect.begin(), vect.end(), ++var(i));

好處是 generate 本身更能說明這句話的用途,當然這個可能因人而異。

我知道有人一定在問:一定要兩行么?一定要有一個初始變量么?答案是可以沒有,但是要用到另外的算法,再加上 boost.lambda 的協助。看看下面:

? std::vector<int> vect(10);
? std::partial_sum(vect.begin(), vect.end(), vect.begin(), _2 = _1 + 1);

如果你現在把 vect 輸出,你會得到:

0 1 2 3 4 5 6 7 8 9

乍看起來不太好理解,我來慢慢解釋。
partial_sum 的第4個參數是一個雙參數的 functor ,在這里,lambda 表達式 _2 = _1 + 1 充當了這個角色,它相當于

f(x, y)? {? y? =? x? +? 1;? }

而 partial_sum 呢?它把一個序列的 partial sum 送到結果序列中去,例如如果輸入一個數組 v[10] ,而輸出是 r[10] ,那么它的計算就是

r[0] = v[0]????????????
r[1] = f( r[0], r[1] )
r[2] = f( r[1], r[2] )
......
r[9] = f( r[8], r[9] )

而當我們把 partial_sum 作用于 vect 本身,結果就成了

vect[0] = vect[0]??????????????????????????? // vect[0] = 0
vect[1] = (vect[1] = vect[0] + 1)?? // vect[1] = 1
vect[2] = (vect[2] = vect[1] + 1)?? // vect[2] = 2
......
vect[9] = (vect[9] = vect[8] + 1)?? // vect[9] = 9

你一定發現其中的問題所在了:首先,我們必須依賴于編譯器把 vect[0] 初始化為0,其次,vect[0] = vect[0] 是不可回避的。以我當前所想到的,也只能這樣了。

推廣一下,如果把
_2 = _1 + 1 中的常數 1 換成另外的數字,我們就可以用一句話得到從 0 開始的等差數列,例如

? std::partial_sum(vect.begin(), vect.end(), vect.begin(), _2 = _1 + 3);

得到的是

0 3 6 9 12 15 18 21 24 27

如果再發揮一點想象力,你就可以構造出更復雜的 lambda 表達式,從而得到更復雜的數組(也許這里叫數列更好吧),例如

? std::partial_sum(vect.begin(), vect.end(), vect.begin(), _2 = 2 * _1 + 1);

得到的是 2 的 n 次方 - 1 數列

0 1 3 7 15 31 63 127 255 511

在 STL 算法中,adjacent_difference 和 partial_sum 是逆運算,因此,上面的事情也可以用 adjacent_difference 來做,只不過要把 lambda 表達式中的參數位置換一下,例如要得到 0, 3, 6... 的等差數列,只需要

? std::adjacent_difference(vect.begin(), vect.end(), vect.begin(), _1 = _2 + 3);

而 2 的 n 次方 - 1 數列也是同樣道理

? std::adjacent_difference(vect.begin(), vect.end(), vect.begin(), _1 = 2*_2 + 1);

如果你要生成倒序的數列呢?當然,STL 算法 reverse 可以派上用場,不過也不要忘了 STL 還有 reverse_iterator 這回事,用它就無需另外調用 reverse 了:

? std::partial_sum(vect.rbegin(), vect.rend(), vect.rbegin(), _2 = 2*_1 + 1);

得到

511 255 127 63 31 15 7 3 1 0

最后還要提醒大家不要忘了一個很有用的 STL 算法: random_shuffle 。它可以把 Random access container 里面的值打亂,配合上面的數列生成,在很多場合是進行測試
(例如測試排序算法) 的好工具。在我的機器上,下面兩行

? std::partial_sum(vect.begin(), vect.end(), vect.begin(), _2 = 2*_1 + 1);
? std::random_shuffle(vect.begin(), vect.end());

得到打亂以后的數列:

255 1 511 3 0 31 127 7 15 63

=================================================================================

有了強大的生成機制作基礎,下面的實驗也更加容易了。STL 的 count_if 和 find_if 都接受一個 predicate 作為比較的依據,而這個 predicate 往往非常簡單,以至于為它專門寫一個 functor 簡直不可接受。在第一篇里面已經展示了用 boost.lambda 生成臨時的無名 functor 的能力,這里再多說一點。

下面先生成 2^n - 1 的數組,然后找出其中第一個大于100的數

? std::vector<int> vect(10);
? std::partial_sum(vect.begin(), vect.end(), vect.begin(), _2 = 2*_1 + 1);
?
? std::cout << *std::find_if(vect.begin(), vect.end(), _1 > 100);

輸出為 127 ,如我們所料。同樣道理,如果是 count_if ,則會得到大于100的數的個數

? std::cout << std::count_if(vect.begin(), vect.end(), _1 > 100);

輸出是 3 。注意細節:find_if 返回一個 iterator ,所以在它之前有 * 解引用,而 count_if 直接返回一個數字,無需解引用。

與之類似的還有 STL 的 partition 算法,它根據傳入的 predicate 對一個序列進行劃分,predicate 得到 true 的將放在前面,其余的放在后面,返回的是那些“
放在 后面”的元素中的第一個,換言之就是分界點。下面的代碼

? std::vector<int> vect(10);
? std::partial_sum(vect.begin(), vect.end(), vect.begin(), _2 = 2*_1 + 1);
?
? std::cout << *std::partition(vect.begin(), vect.end(), _1 > 100) << std::endl;
?
? std::for_each(vect.begin(), vect.end(), std::cout << _1 << " ");

輸出為

7
511 255 127 7 15 31 63 3 1 0

如果仔細觀察,還可以發現上面的輸出有點問題:數列中原有的順序(0, 1, 3, 7...)不復存在,這是因為 partition 并不是一個穩定排序的算法,它不保證排序結果保有原來的順序。如果需要穩定排序,可以使用 stable_partition 。只需要更改排序的那一句代碼為

? std::cout << *std::stable_partition(vect.begin(), vect.end(), _1 > 100) << std::endl;

結果是

0
127 255 511 0 1 3 7 15 31 63

當然,如果你還記得大學里的算法理論,就知道它們在效率上是有點區別的,partition 的復雜度保證為 O(n) ,具體地說是保證不超過 n/2 次交換;而 stable_partition 在最好情況下為 O(n) ,最差情況則達到 O(n*log(n)) 。

順便說一下,上面的幾件簡單的事情,用標準的 STL 算法都可以辦到,只不過實在是……面目可憎:

? std::cout << *std::partition(vect.begin(), vect.end(),
??? std::bind2nd(std::greater<int>(), 100)) << std::endl;

這句代碼做的事情和前面的 partition 一模一樣,但是孰優孰劣,大家自有公斷。
posted on 2006-06-28 13:44 笑笑生 閱讀(226) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


 
Copyright © 笑笑生 Powered by: 博客園 模板提供:滬江博客
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美日韩高清区| 性欧美xxxx大乳国产app| 蜜桃久久av一区| 久久久综合精品| 亚洲日本中文字幕| 亚洲福利视频一区二区| 免费成人高清视频| 日韩网站在线| 中文在线资源观看网站视频免费不卡 | 亚洲国产成人精品久久久国产成人一区 | 激情综合自拍| 亚洲第一福利社区| 欧美日精品一区视频| 午夜精品一区二区三区在线播放| 小处雏高清一区二区三区| 影院欧美亚洲| 亚洲精品视频免费观看| 国产精品伊人日日| 欧美成人首页| 欧美色综合网| 久久久久久久久蜜桃| 久久精品国产视频| 日韩一级在线| 午夜精品国产更新| 亚洲日本成人| 亚洲伊人观看| 亚洲国产网站| 亚洲综合国产激情另类一区| 尤物精品国产第一福利三区| 亚洲国产日韩欧美在线动漫| 国产精品久久久久av| 久久久噜噜噜久久中文字免| 欧美精品二区| 久久三级视频| 欧美三级视频| 欧美不卡一区| 国产精品久久国产精品99gif| 免费成人美女女| 国产精品a久久久久| 麻豆av一区二区三区| 欧美视频一区二区三区在线观看 | 亚洲美女免费精品视频在线观看| 国产精品综合| 亚洲国产裸拍裸体视频在线观看乱了中文 | 久久er精品视频| 夜夜爽99久久国产综合精品女不卡| 亚洲欧美日韩视频二区| 亚洲精品一区二区三区99| 亚洲欧美一级二级三级| 99视频精品全部免费在线| 久久成人亚洲| 亚洲一区二区精品| 久久久亚洲高清| 欧美一级黄色录像| 欧美激情va永久在线播放| 久久久蜜桃一区二区人| 欧美日韩综合在线免费观看| 免费视频久久| 国产毛片一区二区| 日韩视频免费观看高清完整版| 国产一区二区日韩精品| 一区二区三区|亚洲午夜| 亚洲第一精品电影| 性娇小13――14欧美| 亚洲视频1区2区| 免费日韩av电影| 久久一区中文字幕| 国产伦精品一区二区三区在线观看 | 亚洲一区二区伦理| 欧美成人激情视频| 老司机一区二区三区| 国产乱码精品一区二区三区av| 亚洲精品乱码久久久久久| 亚洲国产精品久久久久| 欧美主播一区二区三区美女 久久精品人| 亚洲视频在线观看| 欧美福利视频一区| 欧美fxxxxxx另类| 国内成+人亚洲| 亚洲欧美一区二区三区在线| 亚洲一区久久久| 欧美日韩二区三区| 欧美国产精品中文字幕| 国内精品免费在线观看| 亚洲欧美亚洲| 欧美一区二区大片| 国产精品久久久久久久第一福利| 亚洲另类在线视频| 亚洲精品字幕| 欧美高清视频一二三区| 女人色偷偷aa久久天堂| 国内精品美女在线观看| 欧美一区二区在线免费播放| 欧美一区二区高清在线观看| 国产精品免费一区二区三区在线观看| 日韩视频一区二区| 一区二区三区.www| 欧美日韩三级在线| 亚洲精品自在久久| 一区二区三区精品| 欧美日韩免费观看一区=区三区| 亚洲人成在线影院| 日韩视频中文字幕| 欧美久久成人| 99精品热6080yy久久| 中日韩视频在线观看| 欧美日韩亚洲一区二区三区在线观看 | 欧美激情一区二区三区在线视频观看 | 一区二区三区日韩在线观看| 亚洲一区视频在线观看视频| 国产精品久久二区二区| 亚洲综合好骚| 久久超碰97人人做人人爱| 国产亚洲午夜| 久久国产一区二区三区| 毛片一区二区三区| 亚洲黄网站黄| 久久综合狠狠综合久久综青草| 欧美成人免费在线观看| 亚洲精品乱码久久久久久| 欧美精品午夜| 亚洲视频999| 欧美亚洲系列| 国内精品免费在线观看| 久久人人97超碰国产公开结果| 久久亚洲综合网| 亚洲国产精品久久久久久女王| 蜜臀av性久久久久蜜臀aⅴ| 亚洲国产另类精品专区| 亚洲一区二区伦理| 国产日产欧产精品推荐色| 久久久久**毛片大全| 欧美电影在线观看完整版| 亚洲免费激情| 国产精品日韩久久久久| 久久国产精彩视频| 亚洲高清影视| 亚洲专区国产精品| 国产专区欧美专区| 看欧美日韩国产| 99在线热播精品免费| 欧美一区综合| 亚洲国产裸拍裸体视频在线观看乱了中文 | 久久久久在线观看| 亚洲经典在线看| 国产精品va| 久久国产精品一区二区| 亚洲国产精彩中文乱码av在线播放| 中日韩视频在线观看| 国产一区二区三区电影在线观看| 老**午夜毛片一区二区三区| 亚洲三级毛片| 欧美专区中文字幕| 最新亚洲一区| 国产精品热久久久久夜色精品三区| 久久精品国产精品| 亚洲精品在线免费| 久久精品日产第一区二区三区| 亚洲经典自拍| 国产九区一区在线| 欧美黄色视屏| 性欧美18~19sex高清播放| 欧美激情小视频| 性色一区二区| 最新国产成人av网站网址麻豆 | 老司机aⅴ在线精品导航| 一本色道久久综合亚洲精品婷婷| 国产欧美日韩免费| 免费在线看成人av| 亚洲欧美综合v| 91久久香蕉国产日韩欧美9色| 亚洲一级黄色片| 亚洲国产午夜| 国产欧美一区二区三区在线看蜜臀| 欧美成人午夜免费视在线看片| 亚洲曰本av电影| 亚洲欧洲在线播放| 久久综合国产精品台湾中文娱乐网| 99国产一区| 在线看一区二区| 国产精品黄页免费高清在线观看| 久久影视精品| 亚洲欧美日韩中文视频| 亚洲免费观看在线视频| 猛干欧美女孩| 午夜精彩国产免费不卡不顿大片| 在线播放日韩| 国产精品一区一区| 欧美精品国产精品| 久久久国产一区二区三区| 亚洲一区二区黄色| 亚洲人屁股眼子交8| 免费短视频成人日韩| 久久er99精品| 亚洲在线电影| 日韩亚洲一区在线播放| 一区二区视频在线观看| 国产日韩欧美中文在线播放| 欧美日韩一区视频| 美女黄色成人网|