我是靠谱客的博主 深情鸵鸟,这篇文章主要介绍随机选取算法 (有权重的记录中选取),现在分享给大家,希望可以做个参考。

三类随机问题

1.  已有n条记录,从中选取m条记录,选取出来的记录前后顺序不管。

     实现思路:按行遍历所有记录,约隔n/m条取一个数据即可


2.  在1类情况下,还要求选取出来的m条记录是随机排序的

     实现思路: 给n条记录,分别增加一列标记,值为随机选取的1至n之间的不重复数据,

     实现参考博文 将文件内容按行随机排列


3.  区别于1,2类问题, 如果记录是有权重的,如何结合权重去随机选取。 比如A的权重为10, B的权重股为5, C的权重为1, 则随机选取4个时可能应该出现AABB。

 


这第三类问题是本文重点,下面开始解决。

实现思路: 以 A:10, B:5, C:1 三条记录上随机选取4条为例,(是否以权重排序这个无所谓)

    对于

    A 10

    B 5

    C 1

首先,将第n行的数值赋为第n行加第n-1行的,递归执行,如下:

    A 10

    B 15

    C 16

然后每次从[1,16]随机选取一个数,如果落在[1,10]之间,则选取A,如果落在(10,15]之间则选B,如果落在(16,16]之间则选取C, 图示如下,谁占的区间大(权重高),被选上的概率更大。



 知道了思路,实现起来就比较方便了, 需要考虑的一点可能就是我随即选了一个数值,比如12,我怎么跟B对应上? 其实也比较简单,用二分法查找即可。

下面附上实现代码:


[cpp]  view plain copy
  1. #include <string>  
  2. #include <cstdlib>  
  3. #include <vector>  
  4.   
  5. using namespace std;  
  6.   
  7. const int LEN = 4098;   
  8. const int MAX_QUERY_LEN = 2048;  
  9.   
  10. //返回属于[p,q)的随机数  
  11. int rand(int p, int q)  
  12. {  
  13.      int size = q-p+1;  
  14.      return  p+ rand()%size;   
  15. }  
  16.   
  17. //删除行尾换行符  
  18. int chomp(char *str)  
  19. {  
  20.     int len = strlen(str);  
  21.     while(len > 0 && (str[len - 1] == 'n' || str[len - 1] == 'r'))  
  22.     {  
  23.         str[len - 1] = 0;  
  24.         len--;  
  25.     }  
  26.     return len;  
  27. }  
  28.   
  29. //获取一个随机数会落在哪个区间  
  30. int get_pos(vector<int> vec_freq, int begin, int end, int rand_num)  
  31. {  
  32.     if(begin >= end)  
  33.     {  
  34.         return begin;  
  35.     }  
  36.       
  37.     int mid = (begin + end)/2;  
  38.     if( vec_freq[mid] >= rand_num )  
  39.     {  
  40.         return get_pos(vec_freq, begin, mid, rand_num );  
  41.     }  
  42.     else  
  43.     {  
  44.         return get_pos(vec_freq, mid+1, end, rand_num );  
  45.     }  
  46. }  
  47.   
  48. //主函数  
  49. int main(int argc, char *argv[])  
  50. {  
  51.     //输入记录文件,两列,第一列为记录,第二列为热度值  
  52.     FILE* infile = fopen(argv[1], "r");  
  53.     if( infile == NULL )  
  54.     {  
  55.         printf("Cann't open file %s.", argv[1]);  
  56.         return -1;  
  57.     }  
  58.   
  59.     FILE* outfile = fopen(argv[2], "w");  
  60.     if( outfile == NULL)  
  61.     {  
  62.         printf("Cann't open file %s to write.", argv[2]);  
  63.         return -1;  
  64.     }  
  65.   
  66.     //要获取的随机记录个数  
  67.     int num = atoi(argv[3]);  
  68.     if( num <= 0)  
  69.     {  
  70.         printf("num [%s] <= 0.");  
  71.         return -1;  
  72.     }  
  73.   
  74.     //这两个数组用下标关联  
  75.     vector<string> vec_query;  
  76.     vector<int> vec_freq;  
  77.     vec_query.clear();  
  78.     vec_freq.clear();  
  79.     int freq = 0;  
  80.     char line[MAX_QUERY_LEN]={0};  
  81.       
  82.         while( !feof(infile) )  
  83.         {  
  84.             if( !fgets(line, sizeof(line),infile))  
  85.             {  
  86.                 break;  
  87.             }  
  88.         line[sizeof(line)-1] = 0;  
  89.             chomp(line);  
  90.   
  91.         char* p_tab = strchr(line, 't');  
  92.         if( NULL == p_tab )  
  93.         {  
  94.             printf("line format error. [%s]n");  
  95.             continue;  
  96.         }  
  97.         *p_tab = 0;  
  98.   
  99.         string query(line);  
  100.         freq += atoi(p_tab+1);  
  101.           
  102.         vec_query.push_back(query);  
  103.         vec_freq.push_back(freq);  
  104.   
  105.         //printf("%st%dn", line, freq);  
  106.         }  
  107.   
  108.     for(int i=0; i < num; ++i)  
  109.     {  
  110.         int rand_num = rand(1, freq+1);  
  111.         int pos = get_pos(vec_freq, 0, vec_freq.size(), rand_num);  
  112.         fprintf(outfile, "%st%dt%dn", vec_query[pos].c_str(), vec_freq[pos], rand_num);  
  113.     }  
  114.       
  115.     fclose(infile);  
  116.     fclose(outfile);      
  117.   
  118.     return 0;  

最后

以上就是深情鸵鸟最近收集整理的关于随机选取算法 (有权重的记录中选取)的全部内容,更多相关随机选取算法内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(40)

评论列表共有 0 条评论

立即
投稿
返回
顶部