算法的核心思想很简单,每次删去不同的4个数,最后剩下的元素有可能是频繁项。
假设数组有15个元素,若一个元素的出现频率大于1/4,其必须出现4次。不妨设数组为{1,2,1,4,1,4,2,9,1,7,4,3,9,4,3},d表示删去该数。我们来模拟一下算法的过程。
第一次 1d,2d,1,4d,1,4,2,9d,1,7,4,3,9,4,3 剩下 1,1,4,2,1,7,4,3,9,4,3
第二次 1d,1,4d,2d,1,7d,4,3,9,4,3 剩下 1,1,4,3,9,4,3
第三次 1d,1,4d,3d,9d,4,3 剩下 1,4,3
那么 1,4,3 即为候选频繁项
对 1,4,3 逐个进行检验,统计其再数组中出现的次数,若其超过出现频率阈值,则输出。
代码如下:
#include <iostream>
using namespace std;
#define ARRAY_SIZE 15
#define RESULT_NUM 3 //数组中出现频率的大于1/(RESULT_NUM+1)
int gl_array[ARRAY_SIZE] = {1,2,1,4,1,4,2,9,1,7,4,3,9,4,3};//给定的数字集合
struct Result
{
int iNumber;
int iTempTimes;
};
int GetEmptyElemInResult(Result r[], int iArrayLength)
{
int i = 0;
for (i = 0; i < iArrayLength; i++)
{
if (r[i].iTempTimes <= 0)
{
return i;
}
}
return -1;
}
int GetNumberPosInResult(int iNumber, Result r[], int iArrayLength)
{
int i = 0;
for (i = 0; i < iArrayLength; i++)
{
if (r[i].iNumber == iNumber && r[i].iTempTimes > 0)
{//iNumber出现在候选中,并且有效(在给定的数字集合中,出现次数大于0)
return i;
}
}
return -1;
}
int main(int argc, char** argv)
{
Result resultArray[RESULT_NUM];//结果候选集合
int i, j, iTemp;
for (i = 0; i < RESULT_NUM; i++)
{
resultArray[i].iNumber = 0;
resultArray[i].iTempTimes = 0;
}
for (i = 0; i < ARRAY_SIZE; i++)
{
iTemp = GetNumberPosInResult(gl_array[i], resultArray, RESULT_NUM);
if (-1 != iTemp)
{//若当前数出现在候选集合中,且有效,则其出现次数+1
++resultArray[iTemp].iTempTimes;
}
else//不在候选中
{
iTemp = GetEmptyElemInResult(resultArray, RESULT_NUM);
if (-1 != iTemp)
{//结果候选不满RESULT_NUM个元素,将当前数插入在候选集合中
resultArray[iTemp].iNumber = gl_array[i];
resultArray[iTemp].iTempTimes = 1;
}
else
{//当前数与候选集合中的所有元素都不相同,执行“删除”操作
for (j = 0; j < RESULT_NUM; j++)
{
--resultArray[j].iTempTimes;
}
}
}
}
//test the result in the array
for (i = 0; i < RESULT_NUM; i++)
{
if (resultArray[i].iTempTimes > 0)
{
iTemp = 0;
for (j = 0; j < ARRAY_SIZE; j++)
{
if (resultArray[i].iNumber == gl_array[j])
{
++iTemp;
}
}
if (iTemp > ARRAY_SIZE / (RESULT_NUM+1))//出现次数大于阈值
{
cout << resultArray[i].iNumber << ": " << iTemp << endl;
}
}
}
return 0;
}