外部排序算法相關:主要用到歸併排序,堆排序,桶排序,重點是先分紅不一樣的塊,而後從每一個塊中找到最小值寫入磁盤,分析過程能夠看看http://blog.csdn.net/jeason29/article/details/50474772html
hash值算法算法
給定a、b兩個文件,各存放50億個url,每一個url各佔64字節,內存限制是4G,讓你找出a、b文件共同的url?編程
(1)首先咱們最常想到的方法是讀取文件a,創建哈希表(爲何要創建hash表?由於方便後面的查找),而後再讀取文件b,遍歷文件b中每一個url,對於每一個遍歷,咱們都執行查找hash表的操做,若hash表中搜索到了,則說明兩文件共有,存入一個集合。數組
(2)但上述方法有一個明顯問題,加載一個文件的數據須要50億*64bytes = 320G遠遠大於4G內存,況且咱們還須要分配哈希表數據結構所使用的空間,因此不可能一次性把文件中全部數據構建一個總體的hash表。性能優化
(3)針對上述問題,咱們分治算法的思想。服務器
step1:遍歷文件a,對每一個url求取hash(url)%1000,而後根據所取得的值將url分別存儲到1000個小文件(記爲a0,a1,...,a999,每一個小文件約300M),爲何是1000?主要根據內存大小和要分治的文件大小來計算,咱們就大體能夠把320G大小分爲1000份,每份大約300M(固然,到底能不能分佈儘可能均勻,得看hash函數的設計)數據結構
step2:遍歷文件b,採起和a相同的方式將url分別存儲到1000個小文件(記爲b0,b1,...,b999)(爲何要這樣作? 文件a的hash映射和文件b的hash映射函數要保持一致,這樣的話相同的url就會保存在對應的小文件中,好比,若是a中有一個url記錄data1被hash到了a99文件中,那麼若是b中也有相同url,則必定被hash到了b99中)數據結構和算法
因此如今問題轉換成了:找出1000對小文件中每一對相同的url(不對應的小文件不可能有相同的url)函數
step3:由於每一個hash大約300M,因此咱們再能夠採用(1)中的想法性能
http://blog.csdn.net/tiankong_/article/details/77234726
在全部具備性能優化的數據結構中,我想你們使用最多的就是hash表,是的,在具備定位查找上具備O(1)的常量時間,多麼的簡潔優美,
可是在特定的場合下:
①:對10億個不重複的整數進行排序。
②:找出10億個數字中重複的數字。
固然我只有普通的服務器,就算2G的內存吧,在這種場景下,咱們該如何更好的挑選數據結構和算法呢?
問題分析
這年頭,大牛們寫的排序算法也就那麼幾個,首先咱們算下放在內存中要多少G: (10億 * 32)/(1024*1024*1024*8)=3.6G,可憐
的2G內存直接爆掉,因此各類神馬的數據結構都玩不起來了,固然使用外排序仍是能夠解決問題的,因爲要走IO因此暫時剔除,由於咱們
要玩高性能,無望後咱們想一想可不能夠在二進制位上作些手腳?
好比我要對{1,5,7,2}這四個byte類型的數字作排序,該怎麼作呢?咱們知道byte是佔8個bit位,其實咱們能夠將數組中的值做爲bit位的
key,value用」0,1「來標識該key是否出現過?下面看圖:
從圖中咱們精彩的看到,咱們的數組值都已經做爲byte中的key了,最後我只要遍歷對應的bit位是否爲1就能夠了,那麼天然就成有序數組了。
可能有人說,我增長一個13怎麼辦?很簡單,一個字節能夠存放8個數,那我只要兩個byte就能夠解決問題了。
能夠看出我將一個線性的數組變成了一個bit位的二維矩陣,最終咱們須要的空間僅僅是:3.6G/32=0.1G便可,要注意的是bitmap排序不
是N的,而是取決於待排序數組中的最大值,在實際應用上關係也不大,好比我開10個線程去讀byte數組,那麼複雜度爲:O(Max/10)。
(上面摘自http://www.cnblogs.com/huangxincheng/archive/2012/12/06/2804756.html,省去了代碼部分,具體代碼分析可見下文)
bitmap算法解釋
1、bitmap算法思想
32位機器上,一個整形,好比int a; 在內存中佔32bit位,能夠用對應的32bit位對應十進制的0-31個數,bitmap算法利用這種思想處理大量數據的排序與查詢.
優勢:1.運算效率高,不準進行比較和移位;2.佔用內存少,好比N=10000000;只需佔用內存爲N/8=1250000Byte=1.25M。
缺點:全部的數據不能重複。即不可對重複的數據進行排序和查找。
好比:
第一個4就是
00000000000000000000000000010000
而輸入2的時候
00000000000000000000000000010100
輸入3時候
00000000000000000000000000011100
輸入1的時候
00000000000000000000000000011110
思想比較簡單,關鍵是十進制和二進制bit位須要一個map圖,把十進制的數映射到bit位。下面詳細說明這個map映射表。
2、map映射表
假設須要排序或者查找的總數N=10000000,那麼咱們須要申請內存空間的大小爲int a[1 + N/32],其中:a[0]在內存中佔32爲能夠對應十進制數0-31,依次類推:
bitmap表爲:
a[0]--------->0-31
a[1]--------->32-63
a[2]--------->64-95
a[3]--------->96-127
..........
那麼十進制數如何轉換爲對應的bit位,下面介紹用位移將十進制數轉換爲對應的bit位。
3、位移轉換
例如十進制0,對應在a[0]所佔的bit爲中的第一位:
00000000000000000000000000000001
0-31:對應在a[0]中
i =0 00000000000000000000000000000000
temp=0 00000000000000000000000000000000
answer=1 00000000000000000000000000000001
i =1 00000000000000000000000000000001
temp=1 00000000000000000000000000000001
answer=2 00000000000000000000000000000010
i =2 00000000000000000000000000000010
temp=2 00000000000000000000000000000010
answer=4 00000000000000000000000000000100
i =30 00000000000000000000000000011110
temp=30 00000000000000000000000000011110
answer=1073741824 01000000000000000000000000000000
i =31 00000000000000000000000000011111
temp=31 00000000000000000000000000011111
answer=-2147483648 10000000000000000000000000000000
32-63:對應在a[1]中
i =32 00000000000000000000000000100000
temp=0 00000000000000000000000000000000
answer=1 00000000000000000000000000000001
i =33 00000000000000000000000000100001
temp=1 00000000000000000000000000000001
answer=2 00000000000000000000000000000010
i =34 00000000000000000000000000100010
temp=2 00000000000000000000000000000010
answer=4 00000000000000000000000000000100
i =61 00000000000000000000000000111101
temp=29 00000000000000000000000000011101
answer=536870912 00100000000000000000000000000000
i =62 00000000000000000000000000111110
temp=30 00000000000000000000000000011110
answer=1073741824 01000000000000000000000000000000
i =63 00000000000000000000000000111111
temp=31 00000000000000000000000000011111
answer=-2147483648 10000000000000000000000000000000
淺析上面的對應表:
1.求十進制0-N對應在數組a中的下標:
十進制0-31,對應在a[0]中,先由十進制數n轉換爲與32的餘可轉化爲對應在數組a中的下標。好比n=24,那麼 n/32=0,則24對應在數組a中的下標爲0。又好比n=60,那麼n/32=1,則60對應在數組a中的下標爲1,同理能夠計算0-N在數組a中的下標。
2.求0-N對應0-31中的數:
十進制0-31就對應0-31,而32-63則對應也是0-31,即給定一個數n能夠經過模32求得對應0-31中的數。
3.利用移位0-31使得對應32bit位爲1.
4、編程實現
解析本例中的void set(int i) { a[i>>SHIFT] |= (1<<(i & MASK)); }
1.i>>SHIFT:
其中SHIFT=5,即i右移5爲,2^5=32,至關於i/32,即求出十進制i對應在數組a中的下標。好比i=20,經過i>>SHIFT=20>>5=0 可求得i=20的下標爲0;
2.i & MASK:
其中MASK=0X1F,十六進制轉化爲十進制爲31,二進制爲0001 1111,i&(0001 1111)至關於保留i的後5位。
好比i=23,二進制爲:0001 0111,那麼
0001 0111
& 0001 1111 = 0001 0111 十進制爲:23
好比i=83,二進制爲:0000 0000 0101 0011,那麼
0000 0000 0101 0011
& 0000 0000 0001 0000 = 0000 0000 0001 0011 十進制爲:19
i & MASK至關於i%32。
3.1<<(i & MASK)
至關於把1左移 (i & MASK)位。
好比(i & MASK)=20,那麼i<<20就至關於:
0000 0000 0000 0000 0000 0000 0000 0001 >>20
=0000 0000 0000 1000 0000 0000 0000 0000
4.void set(int i) { a[i>>SHIFT] |= (1<<(i & MASK)); }等價於:
void set(int i)
{
a[i/32] |= (1<<(i%32));
}
a | 0 | 1 | 2 | ...... | 1000022 | ..... | 100000030 | ... | 2*32- 1 |
flag | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 1 |
a | 0 | 1 | ...... | 2*32 / 8- 1 |
bit | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | ...... | 0 1 2 3 4 5 6 7 |
flag | 0 0 0 0 0 0 0 0 | 0 0 1 0 0 0 0 0 | ...... | 0 0 0 0 0 0 0 0 |
字符串全組合枚舉(對於長度爲n的字符串,組合方式有2^n種),如:abcdef,能夠構造一個從字符串到二進制的映射關係,經過枚舉二進制來進行全排序。
null --> 000000
f --> 000001
e --> 000010
ef --> 000011
……
abcedf --> 111111
給定N(1<=N<=100000)個五維的點A(x1,x2,x3,x4,x5),求兩個點X(x1,x2,x3,x4,x5)和Y(y1,y2,y3,y4,y5),使得他們的哈密頓距離(d=|x1-y1| + |x2-y2| + |x3-y3| + |x4-y4| + |x5-y5|)最大。
爬蟲系統中經常使用的URL去重(Bloom Filter算法)
在2.5億個整數中找出不重複的整數,注,內存不足以容納這2.5億個整數?
給40億個不重複的unsigned int的整數,沒排過序的,而後再給一個數,如何快速判斷這個數是否在那40億個數當中?
位排序
(以上摘抄自http://blog.csdn.net/qq_26891045/article/details/51137589)
另:能夠看看KMP(字符串匹配算法)