位图--排序

本文介绍了位图在排序中的应用,通过使用位图来表示和操作整数序列,实现高效排序。位图利用一个字节的8位来表示0到7的数字,通过整形int数组来扩展表示更大的范围。文章详细阐述了如何定位整数在位序列中的位置,并提供了位序列的置位和清位函数,最后讨论了如何对非负整数序列进行排序的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 位图使用基本情况
    • 一个字节有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;
}
  • class
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");

        // 随机取k个数
        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){

        // 在DataSet中取count个数
        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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值