现在的位置: 首页 > 综合 > 正文

在大容量数据集中查找前N个数的算法

2014年01月22日 ⁄ 综合 ⁄ 共 2386字 ⁄ 字号 评论关闭

因工作原因,前阵子看了MTK中关于FM搜频的代码,其中记忆犹新的是一种比较实用的查找算法,我依据它的思想对这个算法做了小小的改动。

该算法的作用是在容量加大的数据集中查找前N个最大(也可以是最小,最大和最小不是算法的关键)数字,当然,这里的N一般比较小,如在100,000,000个数中查找前10个最大的数字。传统的算法是先对这100万个数排序,再取前10个,但对这么多的数字排序相当慢,由于只需取10个数,其余数字的排序实际上是无用的,因此需要一种新的算法。下面简述本文所说的算法思路:

该算法的思路是:每次在所有数据集中选出最大的数字,并将该数字设置一个标志位,已免下次遍历最大值的时候重复选中该数字。为避免查找算法的额外开销,设置标志位的方法比较重要,如果这些数据全部是整数,我们可以用位运算处理;如果是浮点数,我们可以先将这些数据放大,在一定精度范围内将其转化为整数,再使用位运算处理(当然,应该有其他的处理方式)。

写了这么多,个人觉得还是通过程序看算法容易得多。为获取大量不同数据源,我采用随机数生成了10000个整数,并在这些数字中选前10个数字。

/***************************************************
 * Name: Rapid Searching Arithmetic
 *
 * Author: zhouliang
 * Date:    2008-10-20
 * Email:   zhouliang531@163.com
 **************************************************/
#include "stdlib.h" 
#include "stdio.h" 
#include "time.h"

#define MAX_BIT          0x8000                     /*屏蔽的最大比特位,也可以是0x40, 0x800等*/
#define MARK(x)          ((x) |= MAX_BIT)           /*即(x) | = 0x8000*/
#define IS_MARK(x)       ((x) & MAX_BIT)            /*即(x) & 0x8000*/
#define UNMARK(x)        ((x) & (MAX_BIT-1))        /*即(x) | 0x7FFF*/
#define MAX_DATA         (MAX_BIT - 1)              /*即0x7FFF*/
#define TOP_NUM          10                         /*找出前N个最大值*/
#define TOTAL_NUM        10000                      /*总个数*/

void main( void ) 

     int i, j;
     int data[TOTAL_NUM];                 /*存储所有数据*/
     int result[TOP_NUM];                 /*存储查找结果*/
     int max, temp;
     int index;

     /*确保总个数不小于TOP个数*/
     if (TOP_NUM > TOTAL_NUM){
          printf("Please make sure TOP_NUM <= TOTAL_NUM");
          return;
     }

     /*以时间为种子,生成随机数*/
     srand( (unsigned)time( NULL ) );  
     /* 生成 TOTAL_NUM个小于MAX_DATA的随机数*/ 
     for (i=0; i<TOTAL_NUM; i++){ 
          do {
               temp = rand();
          }while(temp > MAX_DATA);
          data[i] =temp;
          printf("%6d/n", temp); 
     }

     /*查找最大的TOP_NUM个数字*/
     for (i=0; i<TOP_NUM; i++){
          max = 0;
          index = -1;
          for (j=0; j<TOTAL_NUM; j++){
               if (!IS_MARK(data[j])){ /*避免重复选取*/
                    temp = UNMARK(data[j]);
                    if (temp > max){
                         max = temp;
                         index = j;
                    }
               }//end if
          }//end for
          if (index >= 0){ /*找到最大的,标记*/
               result[i] = data[index];
               MARK(data[index]);
          }
          else{
               break;
          }
     }//end for
 
     printf("Top %d Number:/n", TOP_NUM);
     for (i=0; i<TOP_NUM; i++){
          printf("%6d/n", result[i]);
     }
} // end main

为测试数据集多变,上述程序通过时间种子生成随机数,因此每次运行的时候可以得到不同的数据集。

抱歉!评论已关闭.