- 位图使用基本情况
- 一个字节有8位,假设第0位表示0,第1位表示1,那么一个字节就可以表示8个数字。整数序列{0,1,4,7}, 在位序列中表示为10010011,左边第一位为低位,表示有效数字0。
- 位序列如何表示?
- Java 整形int 用4个字节表示,可以用整形int 数组表示位序列:
- 初始化一整形数组 int[] bitMap = new int[(N >> 5) + 1]
- bitMap[0] 4个字节共32位,表示区间[0 , 31]
- bitMap[1] 4个字节共32位,表示区间[32, 63]
- 以上规律,整数x 在位序列的位置可以定位到bitMap[(x >> 5)]
- bitMap[(x >> 5)] 4个字节共32位,具体用哪一位表示,由整数x的最低5位确定 (1 << ( x & 0x1F))
- 位序列置位函数
void setBit( int x ) { bitMap[(x >> 5)] |= (1 << ( x & 0x1F))}
- 位序列清位函数
void clrBit( int x ) { bitMap[(x >> 5)] &= ~(1 << ( x & 0x1F))}
- 对一数量为N(小于10000000)的非负整数序列排序,该整数序列中的元素具有唯一性。
private void genDataSet(){
File dataSet = new File(File_PATH);
DataOutputStream out = null;
try{
if( !dataSet.exists()){
dataSet.createNewFile();
}
out = new DataOutputStream(new FileOutputStream(dataSet));
for(int i = DATA_COUNT; i >= 0 ; i--){
out.writeInt(i);
}
}catch (Exception e) {
e.printStackTrace();
}finally{
try{
if(out != null)
out.close();
}catch (Exception e1){
e1.printStackTrace();
}
}
}
private void setBit(int x, int[] bitMap){
bitMap[ x >> SHIFT ] |= 1 << (x & LOWEST_FILE_BIT);
}
/**
* 使用位图 排序整数序列
*/
private int[] sortDataSet(){
int[] dataSet = new int[DATA_COUNT + 1 ];
int[] bitMap = new int[(DATA_COUNT >> SHIFT) + 1];
DataInputStream in = null;
try {
in = new DataInputStream(new FileInputStream(new File( File_PATH )));
while(true){
try {
int x = in.readInt();
setBit(x, bitMap);
}catch (EOFException eof){
break;
}
}
int index = 0;
for(int i = 0; i < bitMap.length; i++ ){
int bits = bitMap[ i ];
for(int j = 0; j < 32; j++){
if (( (bits >> j) & 0x01) == 1){
dataSet[index ++] = (i << SHIFT) + j;
}
}
}
}catch (Exception e){
e.printStackTrace();
}finally {
if (in != null){
try{
in.close();
}catch (Exception e1){
e1.printStackTrace();
}
}
}
return dataSet;
}
public class SortIntSet {
public static String File_PATH = "dateset.txt";
public static int SHIFT = 5;
public static byte LOWEST_FILE_BIT = 0x1F;
public static int DATA_COUNT = 10000000;
public static void main(String[] args) {
SortIntSet st = new SortIntSet();
st.genDataSet();
long start = System.currentTimeMillis();
int[] dataSet = st.sortDataSet();
System.out.println("消耗时间:" + ((System.currentTimeMillis() - start) / 1000) + "s");
int[] ranNums = st.getRanSeq(10, dataSet);
Arrays.stream(ranNums).forEach(e -> System.out.println(e));
}
private void genDataSet(){...}
private void setBit( int x ){...}
private void sortDataSet(){...}
/**
* 从数组dataSet中随机获取count个数,不重复取
* @param count
* @param dataSet
* @return
*/
private int[] getRanSeq(int count, int[] dataSet){
for(int i = 0; i < count; i++){
int index = RandomUtils.nextInt(i, DATA_COUNT);
int tmp = dataSet[index];
dataSet[index] = dataSet[i];
dataSet[i] = tmp;
}
int[] res = new int[count];
for( int i = 0; i < count; i++){
res[i] = dataSet[i];
}
return res;
}
}