搜索结构——位图

github地址:https://github.com/ALXlixiong/bitmap1

引:给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。 【腾讯】

 我的思路:拿到这道题首先想到的就是暴力求解法(O(N)),但是效率太慢;其次可从题中知40亿个数字无序,所以第二种思路就是排序+二分查找(O(NlgN)+O(lgN));还有一种思路就是哈希表+平衡搜索树(O(N)+O(lgN));

  1. 暴力求解法      O(N)
  2. 排序+二分查找      O(NlgN)+O(lgN)
  3. 哈希表+平衡搜索树      O(N)+O(lgN)

以上三种方法中,第二和第三中方法时间效率虽然和第一种时间效率差不多,但是两者有本质区别。第一种方法是一次性的,第二种和第三种是永久性的,只需要我们把数据组织好,以后查找效率O(lgN),所以后两种方法优于第一种。

但是40亿个数据(1G = 1024*1024*1024 byte )所以40亿int 需要内存4G*4(32位编译器),所以这些数据一定保存于磁盘,当然在磁盘中可以排序,但是效率太慢,而且后续需要二分查找,但是二分查找需要下标,所以不可行。所以上述三种方法都不可行。

上述三种方法都不可行,主要原因就是内存不够,那么我们想办法既可以判断该数字是否存在,又可以缩小空间。可以使用字符1表示存在,字符0表示不存在,那么我们可以假设预留>40亿的4G空间(此处假设42亿数字中包含了40亿数字)如果那么数字存在,把相应字符数组位置置为1,不存在置为0。这种方法下来大约需要4G空间,所以只要内存地址空间大和64位程序可能malloc出空间大小。

感觉上述方法还是不是最好的方法既然我们使用一个字符来保存1或者0,那么我们可以使用比特位来标识1或者0,那么我们可以采用位图。

位图

位图专门是解决数字存在与否,位图是直接定址法哈希表。

 

#include "bitmap.h"

void BitMapInit(BitMap *bp,unsigned int size)
{
  assert(bp);
  bp->capacity = size;
  //需要多少个字节
  //size>>5+1表示需要多少个int
  bp->array = (int *)malloc(sizeof(int)*((size>>5)+1));
  if(bp->array == NULL)
    return;
  bp->size = 0;
  memset(bp->array,0,sizeof(int)*((size>>5)+1));
}

void BitMapSet(BitMap *bp,unsigned int data)
{
  int index = data>>5;
  int bit = data%32;
  bp->size++;
  bp->array[index] |= (1<<bit);
}

void BitMapReset(BitMap *bp,unsigned int data)
{
  int index = data>>5;
  int bit = data%32;
  bp->size--;
  bp->array[index] &= ~(1<<bit);
}

unsigned int BitMapIs(BitMap *bp,unsigned int data)
{
  int index = data>>5;
  int bit = data%32;
  return (bp->array[index]>>bit) & 1;
}

void BitMapDestory(BitMap *bp)
{
  free(bp->array);
  bp->array = NULL;
  bp->capacity = 0;
  bp->size = 0;
}

void test()
{
  BitMap bp;
  BitMapInit(&bp,7);
  BitMapSet(&bp,1);
  BitMapSet(&bp,3); 
  BitMapSet(&bp,7); 
  BitMapSet(&bp,4); 
  BitMapSet(&bp,12);
  BitMapSet(&bp,16);

  printf("res_1 = %d\n",BitMapIs(&bp,1));
  printf("res_1 = %d\n",BitMapIs(&bp,7));
  printf("res_1 = %d\n",BitMapIs(&bp,12));
  printf("res_1 = %d\n",BitMapIs(&bp,66));
  printf("res_1 = %d\n",BitMapIs(&bp,2));

  BitMapReset(&bp,7);
  printf("res_1 = %d\n",BitMapIs(&bp,7));

  BitMapDestory(&bp);
}

//bitmap.h

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>


typedef struct BitMap
{
  int *array;//保存多少个int,对每个int里面的32个比特位操作
  int capacity;
  int size;
}BitMap;


void BitMapInit(BitMap *bp,unsigned int size);

void BitMapSet(BitMap *bp,unsigned int data);

void BitMapReset(BitMap *bp,unsigned int data);

unsigned int BitMapIs(BitMap *bp,unsigned int data);

void BitMapDestory(BitMap *bp);

void test();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_41318405

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值