数组中寻找第K小的数----位图法(bitmap)

http://baike.baidu.com/link?url=4OAMuQ6CYG6IjdyYH6y5zeDfd8GCVvlb5G6NXTSJSOQOVHMSC7qBOZ1STmKVM7UUldxfj6edBitJ9e66mG5mWK

http://blog.csdn.net/cscmaker/article/details/8074268

1)位图法

     所谓bitmap,就是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况。通常是用来判断某个数据存不存在的(百度百科)。 

     例如:对{0, 1, 5,3, 7}进行排序,可以在计算机中使用8位表示这几个数,也就是使用一个字节空间可以完成排序。

      数组中的数:               0   1            3              5               7 

      bitmap中的位值:      1    1    0     1      0     1      0       1     //若在数组中,则位值设为1,否则为0

      bitmap中的位标号:  0    1    2     3      4      5      6      7


      位图法还可以判断数组中值是否重复出现。位图法在降低了时间复杂度的同时,很好的控制了空间复杂度。


(2)算法实现(分为  针对无符号数组  及  有符号数组)

         A:针对无符号数组实现:
    

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <iostream>  
  4.   
  5. using namespace std;  
  6.   
  7. void set_bit(char *bit_map, int n)  
  8. {  
  9.     for(int i=0; i<(n/8); ++i)  
  10.         bit_map++;  
  11.     //相应表示的位置1  
  12.     *bit_map =(*bit_map) | (0x01<<n%8);  
  13. }  
  14.   
  15. int get_max_value(int num[], int n)  
  16. {  
  17.    int temp = num[0];  
  18.    for(int i=1; i<n; ++i)  
  19.    {  
  20.        if(num[i]>temp)  
  21.            temp = num[i];  
  22.    }  
  23.    return temp;  
  24. }  
  25.   
  26. void bit_map_sort(int num[], int n)  
  27. {  
  28.     //首先得到数组中的最大值  
  29.     int max = get_max_value(num, n);  
  30.     //计算bitmap的长度,每一个字节可以表示8个数  
  31.     int bit_map_len = 0;  
  32.     if(max%8 == 0)  
  33.       bit_map_len = max/8;  
  34.     else  
  35.       bit_map_len = max/8+1;  
  36.     //创建bitmap  
  37.     char* bit_map = new char[bit_map_len];  
  38.     memset(bit_map, 0, bit_map_len);  
  39.     for(int i=0; i<n; ++i)  
  40.         set_bit(bit_map, num[i]);  
  41.     //输出数组  
  42.     for(int i=0; i<bit_map_len; ++i)  
  43.     {  
  44.         for(int j=0; j<8; ++j)  
  45.         {  
  46.             //如果该位是1,则输出  
  47.             if((bit_map[i]&(0x01<<j)) == (0x01<<j))  
  48.                 cout<<(i*8+j)<<" ";  
  49.         }  
  50.     }  
  51.     cout<<endl;  
  52. }  
  53.   
  54. int main()  
  55. {  
  56.     int num[] = {3,5, 2, 10, 6, 9999999, 8, 14, 9};  
  57.     bit_map_sort(num, 9);  
  58.     return 0;  
  59. }  


       B:针对有符号数组(数组中存在负数)

 

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <iostream>  
  4.   
  5. using namespace std;  
  6.   
  7. //从bitmap中间开始计算,左边表示负数,右边表示正数  
  8. void set_bit(char *bit_map_mid, int num)  
  9. {  
  10.     //若为正数,则指针右移  
  11.     if(num >= 0)  
  12.        for(int i=0; i<(num/8); ++i)  
  13.         bit_map_mid++;  
  14.     //反之,指针左移  
  15.     if(num < 0)  
  16.     {  
  17.        num = -1*num;  
  18.        for(int i=0; i<(num/8); ++i)  
  19.         bit_map_mid--;  
  20.        bit_map_mid--;  
  21.     }  
  22.     //相应表示的位置1  
  23.     *bit_map_mid =(*bit_map_mid) | (0x01<<num%8);  
  24. }  
  25.   
  26. //得到数组中绝对值最大的值  
  27. int get_max_absolute_value(int num[], int n)  
  28. {  
  29.    int temp = 0;  
  30.    for(int i=0; i<n; ++i)  
  31.    {  
  32.        if(num[i]>temp)  
  33.            temp = num[i];  
  34.        else if(num[i]<0)  
  35.          if((num[i]*(-1))>temp)  
  36.              temp = num[i]*(-1);  
  37.    }  
  38.    return temp;  
  39. }  
  40.   
  41. void bit_map_sort(int num[], int n)  
  42. {  
  43.     //首先得到数组中的最大值  
  44.     int max = get_max_absolute_value(num, n);  
  45.     //计算bitmap的长度,每一个字节可以表示8个数  
  46.     int bit_map_len = 0;  
  47.     if(2*max%8 == 0)//若最大值为16,则其bitmap应该能表示[-16, 16],所以乘以2;  
  48.       bit_map_len = 2*max/8;  
  49.     else  
  50.       bit_map_len = 2*max/8+1;  
  51.     //创建bitmap  
  52.     char* bit_map = new char[bit_map_len];  
  53.     memset(bit_map, 0, bit_map_len);  
  54.     int mid = bit_map_len/2;  
  55.     for(int i=0; i<n; ++i)  
  56.         set_bit(bit_map+mid, num[i]);  
  57.     //首先输出负数  
  58.     for(int i=0; i<mid; ++i)  
  59.     {  
  60.         for(int j=0; j<8; ++j)  
  61.         {  
  62.             //如果该位是1,则输出  
  63.             if((bit_map[i]&(0x01<<j)) == (0x01<<j))  
  64.                 cout<<(-1)*((mid-1-i)*8+j)<<" ";  
  65.         }  
  66.     }  
  67.     for(int i=mid; i<bit_map_len; ++i)  
  68.     {  
  69.         for(int j=0; j<8; ++j)  
  70.         {  
  71.             //如果该位是1,则输出  
  72.             if((bit_map[i]&(0x01<<j)) == (0x01<<j))  
  73.                 cout<<(i-mid)*8+j<<" ";  
  74.         }  
  75.     }  
  76.     cout<<endl;  
  77. }  
  78.   
  79. int main()  
  80. {  
  81.     int num[] = {3,5, 2, 10, 6, -999999, 8, -14, 9};  
  82.     bit_map_sort(num, 9);  
  83.     return 0;  
  84. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值