但是在特定的场合下:
①:对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)。
二:代码
我想bitmap的思想大家都清楚了,这一次又让我们见证了二进制的魅力,当然这些移位都是位运算的工作了,熟悉了你就玩转了。
1:Clear方法(将数组的所有bit位置0)
比如要将当前4对应的bit位置0的话,只需要1左移4位取反与B[0] & 即可。
1 #region 初始化所用的bit位为0
2 ///
3 /// 初始化所用的bit位为0
4 ///
5 ///
6 static void Clear(byte i)
7 {
8 //相当于 i%8 的功能
9 var shift = i & 0x07;
10
11 //计算应该放数组的下标
12 var arrindex = i >> 3;
13
14 //则将当前byte中的指定bit位取0,&后其他对方数组bit位必然不变,这就是 1 的妙用
15 var bitPos = ~(1
2:Add方法(将bit置1操作)
同样也很简单,要将当前4对应的bit位置1的话,只需要1左移4位与B[0] | 即可。
1 #region 设置相应bit位上为1
2 ///
3 /// 设置相应bit位上为1
4 ///
5 ///
6 static void Add(byte i)
7 {
8 //相当于 i%8 的功能
9 var shift = i & 0x07;
10
11 //计算应该放数组的下标
12 var arrindex = i >> 3;
13
14 //将byte中的 1 移动到i位
15 var bitPos = 1
2:Contain方法(判断当前bit位是否是1)
如果看懂了Clear和Add,我相信最后一个方法已经不成问题了。
1 #region 判断当前的x在数组的位中是否存在
2 ///
3 ///判断当前的x在数组的位中是否存在
4 ///
5 ///
6 ///
7 static bool Contain(byte i)
8 {
9 var j = a[i >> 3] & (1
最后上总的代码:
View Code
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Diagnostics;
6 using System.Threading;
7 using System.IO;
8
9 namespace ConsoleApplication2
10 {
11 public class Program
12 {
13 static byte n = 7;
14
15 static byte[] a;
16
17 public static void Main()
18 {
19 //节省空间的做法
20 a = new byte[(n >> 3) + 1];
21
22 for (byte i = 0; i
41 /// 初始化所用的bit位为0
42 ///
43 ///
44 static void Clear(byte i)
45 {
46 //相当于 i%8 的功能
47 var shift = i & 0x07;
48
49 //计算应该放数组的下标
50 var arrindex = i >> 3;
51
52 //则将当前byte中的指定bit位取0,&后其他对方数组bit位必然不变,这就是 1 的妙用
53 var bitPos = ~(1
62 /// 设置相应bit位上为1
63 ///
64 ///
65 static void Add(byte i)
66 {
67 //相当于 i%8 的功能
68 var shift = i & 0x07;
69
70 //计算应该放数组的下标
71 var arrindex = i >> 3;
72
73 //将byte中的 1 移动到i位
74 var bitPos = 1
83 ///判断当前的x在数组的位中是否存在
84 ///
85 ///
86 ///
87 static bool Contain(byte i)
88 {
89 var j = a[i >> 3] & (1
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.e1idc.net