编程珠玑第一章的算法,Java实现,通俗易懂

该算法也就是所谓的位图算法,用一个int表示32位,也就是实际值为1~32的数.

按照书里说的, 该算法只适合内存有限,而磁盘和时间不限,且数字在1~MAX之间不重复的排序.

 1 package demo1;
 2 
 3 /**
 4  * Created with IntelliJ IDEA.
 5  * User: wsyang
 6  * Date: 13-11-3
 7  * Time: 8:11
 8  * To change this template use File | Settings | File Templates.
 9  */
10 public class BitSort {
11 
12     public static void main(String[] args) {
13         //每个int类型数的位数(1个int数是4个字节,1个字节等于8位,所以是32=4*8)
14         int size = 32;
15         //最大值
16         int MAX= 10000000;
17         //计算出需要多大的数组,才能按位保存MAX个数.数组中每一个元素,也就是int数,能保存32位,所以是如下算数.
18         int arraySize = MAX/size + (MAX%size==0?0:1);
19         System.out.println("需要"+arraySize+"个数组元素");
20         int[] datas = new int[arraySize];
21 
22         //测试数据
23         int[] orginal = new int[]{5,888,4,2,6,7,3,10,567,456,234,123,66666,55555,3333333,8908764};
24 
25         //完成位图的填充
26         for(int i=0;i<orginal.length;i++){
27             int v = orginal[i];//原始值
28             //假设数值是33,因为1个int也就是32位只能表示1~32,因此,需要算出:
29             int index = v/size + (v%size==0?0:1)-1;//数组第几项才能表示目标数v
30             int pos = v % size - 1;//偏移量,也就是数组的index位置的int数的第几位才是这个数
31             //这里用了按位与运算,因为假设原值是000100,计算出偏移量是30,也就是说,倒数第二位是1,合并进去就是001 10.
32             //因此这里按位与运算最合适
33             int newResult = datas[index]  | 1<< 31-pos;//新结果
34             //更新值
35             datas[index]=newResult;
36             System.out.print("原始值" + v);
37             System.out.print("下标" + index);
38             System.out.print("偏移" + pos);
39             System.out.print("新结果" + newResult);
40             System.out.println();
41         }
42         //遍历位图,输出结果
43         for(int i=0;i<datas.length;i++){
44             int data = datas[i];
45 
46             //有了data这个十进制数,如何得到她的二进制的每位值呢?
47             //很简单,需要得到某位的值,就将该数右移31-第几位,并将除末位外的所有位置为0,就能知道该位实际值.
48             for(int index=0;index<31;index++){
49                 //上条注释所言的计算方法
50                 int posVal = (data >> (31-index)) & 1;
51 
52                 if(posVal==1){
53                     //如果该位是1,那么说明该位是有值的,输出她
54                     //由于我们进行了拆分,也就是说当i=1时,基数是32开始,偏移量为1,就是33
55                     int result = size*i + index+1;
56                     System.out.print(result + ",");
57                 }
58             }
59 
60         }
61     }
62 }

 这个程序的输出是:

需要312500个数组元素
原始值5下标0偏移4新结果134217728
原始值888下标27偏移23新结果256
原始值4下标0偏移3新结果402653184
原始值2下标0偏移1新结果1476395008
原始值6下标0偏移5新结果1543503872
原始值7下标0偏移6新结果1577058304
原始值3下标0偏移2新结果2113929216
原始值10下标0偏移9新结果2118123520
原始值567下标17偏移22新结果512
原始值456下标14偏移7新结果16777216
原始值234下标7偏移9新结果4194304
原始值123下标3偏移26新结果32
原始值66666下标2083偏移9新结果4194304
原始值55555下标1736偏移2新结果536870912
原始值3333333下标104166偏移20新结果2048
原始值8908764下标278398偏移27新结果16
2,3,4,5,6,7,10,123,234,456,567,888,55555,66666,3333333,8908764,
Process finished with exit code 0

原文地址:https://www.cnblogs.com/dycg/p/3404593.html