# 针对范围对的高效查找算法设计（不准用数组）

<<1, 2>, 20>
<<3, 37>, 27>
<<48, 57>, 28>
<<58, 63>, 27>
<<97, 128>, 122>
<<129, 149>, 12>
<<150, 189>, 13>
<<200, 245>, 14>
<<246, 256>, 129>
<<479, 560>, 12>

### 1. 用STL map来存储这些范围对（key）及对应的结果集（value），用map进行查找

class range {
public:
int from;
int to;

public:
range(): from(-1), to(-1) {}
range(int f, int t): from(f), to(t) {}
};

map定义为：

typedef map<range*, int> range_map;

struct cmp_func {
bool operator()(const range* lc,const range* rc) const {
return (lc->from < rc->from) || (lc->from == rc->from && lc->to < rc->to);
}
};

struct cmp_func {
bool operator()(const range* lc,const range* rc) const {
return lc->to < rc->from;
}
};

typedef map<range*, int, cmp_func> range_map;

#include<iostream>
#include<stdio.h>
#include<map>
#include<sys/time.h>
using namespace std;

class range {
public:
int from;
int to;

public:
range(): from(-1), to(-1) {}
range(int f, int t): from(f), to(t) {}
};

struct cmp_func {
bool operator()(const range* lc,const range* rc) const {
return lc->to < rc->from;
}
};

typedef map<range*, int, cmp_func> range_map;

int get_next1(range_map *rm, int c) {
for(range_map::iterator it = rm->begin(); it != rm->end(); ++it) {
if(c >= it->first->from && c <= it->first->to) return it->second;
}

}

int get_next2(range_map *rm, int c) {
range_map::iterator iter = rm->find(new range(c, c));
if(iter != rm->end())  return iter->second;

}

int main()
{
struct timeval t_begin, t_end;

range_map *rm = new range_map();

rm->insert(pair<range*, int>(new range(1, 2), 20));
rm->insert(pair<range*, int>(new range(3, 37), 27));
rm->insert(pair<range*, int>(new range(48, 57), 28));
rm->insert(pair<range*, int>(new range(58, 63), 27));
rm->insert(pair<range*, int>(new range(97, 128), 122));
rm->insert(pair<range*, int>(new range(129, 149), 12));
rm->insert(pair<range*, int>(new range(150, 189), 12));
rm->insert(pair<range*, int>(new range(200, 245), 14));
rm->insert(pair<range*, int>(new range(246, 256), 129));
rm->insert(pair<range*, int>(new range(479, 560), 12));

gettimeofday(&t_begin,NULL);
int result[256];
for(int c = 0; c < 256; c++)
result[c] = get_next1(rm, c);
gettimeofday(&t_end,NULL);
double timeuse=1000000*(t_end.tv_sec-t_begin.tv_sec)+(t_end.tv_usec-t_begin.tv_usec);
timeuse/=1000000;
printf("\nget_next1 time use: %.12f\n", timeuse);
for(int c = 0; c < 256; c++)
cout << result[c] << " ";
cout << endl;

gettimeofday(&t_begin,NULL);
for(int c = 0; c < 256; c++)
result[c] = get_next2(rm, c);
gettimeofday(&t_end,NULL);
timeuse=1000000*(t_end.tv_sec-t_begin.tv_sec)+(t_end.tv_usec-t_begin.tv_usec);
timeuse/=1000000;
printf("\nget_next2 time use: %.12f\n", timeuse);
for(int c = 0; c < 256; c++)
cout << result[c] << " ";
cout << endl;

return 0;
}

get_next1 time use: 0.000124000000
get_next2 time use: 0.000144000000

### 2. 使用二分查找的思想来查找范围对

int ranges[] = {1, 2, 3, 37, 48, 57, 58, 63, 97, 128, 129, 149, 150, 189, 200, 245, 246, 256, 479, 560};
int results[] = {20, 27, 28, 27, 122, 12, 13, 14, 129, 12};

（1）100在128前半部分的数组里，即1, 2, 3, 37, 48, 57, 58, 63, 97；

（2）由于128是范围对<97, 128>的第二部分，那么也有可能这个数属于这个范围对。

#include<iostream>
#include<stdio.h>
#include<map>
#include<sys/time.h>
using namespace std;

class range {
public:
int from;
int to;

public:
range(): from(-1), to(-1) {}
range(int f, int t): from(f), to(t) {}
};

typedef map<range*, int> range_map;

int get_next1(range_map *rm, int c) {
for(range_map::iterator it = rm->begin(); it != rm->end(); ++it) {
if(c >= it->first->from && c <= it->first->to) return it->second;
}

}
// binary search
int get_next2(int *ranges, int *results, int size, int c) {
if(size <= 1) return -1;

int start, end, mid;
start = 0;
end = size - 1;

while(start <= end) {
if(c < ranges[start] || c > ranges[end]) return -1;
mid = start + (end - start) / 2;
if(c == ranges[mid]) return results[mid / 2];
if(c < ranges[mid]) {
if(mid % 2 == 1) {
if(c >= ranges[mid - 1]) return results[mid / 2];
else end = mid - 2;
}
else end = mid - 1;
}
else {
if(mid % 2 == 0) {
if(c <= ranges[mid + 1]) return results[mid / 2];
else start = mid + 2;
}
else start = mid + 1;
}
}

}

int get_next3(int *ranges, int *results, int size, int c) {
for(int i = 0; i < size;) {
if(i % 2 == 0) {
if(c >= ranges[i] && c <= ranges[i + 1]) return results[i / 2];
else if(c < ranges[i]) return -1;
else i += 2;
}
}
}

int main()
{
struct timeval t_begin, t_end;

range_map *rm = new range_map();

rm->insert(pair<range*, int>(new range(1, 2), 20));
rm->insert(pair<range*, int>(new range(3, 37), 27));
rm->insert(pair<range*, int>(new range(48, 57), 28));
rm->insert(pair<range*, int>(new range(58, 63), 27));
rm->insert(pair<range*, int>(new range(97, 128), 122));
rm->insert(pair<range*, int>(new range(129, 149), 12));
rm->insert(pair<range*, int>(new range(150, 189), 13));
rm->insert(pair<range*, int>(new range(200, 245), 14));
rm->insert(pair<range*, int>(new range(246, 256), 129));
rm->insert(pair<range*, int>(new range(479, 560), 12));

int ranges[] = {1, 2, 3, 37, 48, 57, 58, 63, 97, 128, 129, 149, 150, 189, 200, 245, 246, 256, 479, 560};
int results[] = {20, 27, 28, 27, 122, 12, 13, 14, 129, 12};

// int r = get_next2(ranges, results, 20, 65);
// cout << r << endl;

gettimeofday(&t_begin,NULL);
int result[256];
for(int c = 0; c < 256; c++)
result[c] = get_next1(rm, c);
gettimeofday(&t_end,NULL);
double timeuse=1000000*(t_end.tv_sec-t_begin.tv_sec)+(t_end.tv_usec-t_begin.tv_usec);
timeuse/=1000000;
printf("\nget_next1 time use: %.12f\n", timeuse);
// for(int c = 0; c < 256; c++)
//     cout << result[c] << " ";
// cout << endl;

gettimeofday(&t_begin,NULL);
for(int c = 0; c < 256; c++)
result[c] = get_next2(ranges, results, 20, c);
gettimeofday(&t_end,NULL);
timeuse=1000000*(t_end.tv_sec-t_begin.tv_sec)+(t_end.tv_usec-t_begin.tv_usec);
timeuse/=1000000;
printf("\nget_next2 time use: %.12f\n", timeuse);
// for(int c = 0; c < 256; c++)
//     cout << result[c] << " ";
// cout << endl;

gettimeofday(&t_begin,NULL);
for(int c = 0; c < 256; c++)
result[c] = get_next3(ranges, results, 20, c);
gettimeofday(&t_end,NULL);
timeuse=1000000*(t_end.tv_sec-t_begin.tv_sec)+(t_end.tv_usec-t_begin.tv_usec);
timeuse/=1000000;
printf("\nget_next3 time use: %.12f\n", timeuse);
// for(int c = 0; c < 256; c++)
//     cout << result[c] << " ";
// cout << endl;

return 0;
}

get_next1 time use: 0.000302000000
get_next2 time use: 0.000043000000
get_next3 time use: 0.000165000000

posted @ 2014-06-22 19:52  Alexia(minmin)  阅读(4249)  评论(31编辑  收藏