当前位置: 首页 > news >正文

【算法】海量数据处理:有一千万条短信,有重复,以文本形式保存,一行一条,找出重复最少的前10条...

题目:有一千万条短信,有重复,以文本形式保存,一行一条,找出重复最少的前10条

思路:通过哈希表去重并统计出重复次数后,通过堆调整找出重复次数最少的前10条

参考文章:http://gengning938.blog.163.com/blog/static/128225381201161994028740/,代码有改动。

关于从n(n很大)个数字中查找前k个最小的数的方法,用堆调整的方法,具体参见:

http://www.oschina.net/code/snippet_180974_6371和我之前的一篇博客:【数据结构】堆排序

下面给出经过改动的代码,编译是通过的。如果任何地方有什么纰漏之处,敬请指正。

#include<iostream>
#include<fstream>
#include<stdlib.h>
#include<malloc.h>
using namespace std;

const int ERROR=0;

struct LinkHash
{
    LinkHash *next;

    //用来装填短信息的内容
    char msg[10];
    int count;
};
struct SData
{
    char msg[10];
    int count;
};

//哈希函数,将一条短信息转成0~99的某值:[0,99] = f(短信息)
int Hash_Func(char const *p)
{
    int value=0;
    while(*p!='\0')
    {
        value=*p+value;
        p++;
    }
    return value%100;
}

class CHashTable
{
private:
    LinkHash *HashTable[100];
public:
    CHashTable();
    ~CHashTable();

    void HashCollision(char const *p);
    void WriteToFile();

};
CHashTable::CHashTable()
{
    int i;
    for(i=0;i<100;i++)
    {
        HashTable[i]=(LinkHash*)malloc(sizeof(LinkHash));
        if(!HashTable[i])
            exit(ERROR);
        
        //初始化
        HashTable[i]->next=NULL;
        memset(HashTable[i]->msg, 0 , 10);
        HashTable[i]->count=0;

    }
}
CHashTable::~CHashTable()
{
    //释放开辟的内存空间(释放链接表)
    int i;
    LinkHash* p,*q;
    for(i=0; i<100; i++)
    {
        p = HashTable[i];
        while(p != NULL)
        {
            q = p;
            p = p->next;
            free(q);
        }    
    }

}

void CHashTable::HashCollision(char const *p)
{    
    int pos;
    LinkHash *head,*mobile,*newNode,*last;
    pos = Hash_Func(p);
    head = HashTable[pos];
    bool flag = false;
    if(head->count == 0)
    {
        strcpy(head->msg,p);
        head->count++;
    }
    else 
    {
        mobile = head;
        while(mobile!=NULL)
        {
            if(flag==false && strcmp(mobile->msg,p) == 0)
            {
                mobile->count++;
                flag = true;
                //break;//不用break是为了取得链表尾部指针
            }
            last = mobile;
            mobile = mobile->next;
        }
        if(flag == false)
        {
            newNode = (LinkHash *)malloc(sizeof(LinkHash));
            if(!newNode)
                exit(ERROR);
            newNode->next = NULL;
            strcpy(newNode->msg,p);
            newNode->count = 1;
            last->next = newNode;
        }
    }
}

//将原短信去重后统计出重复次数后写入result.txt文件中
void CHashTable::WriteToFile()
{
    int i;
    ofstream fout;
    LinkHash *p;
    fout.open("result.txt");//应写明正确路径
    
    for(i=0; i<100; i++)
    {
        p=HashTable[i];
        while(p)
        {
            fout<<p->msg<<" "<<p->count<<endl;
            p=p->next;
        }

    }
    fout.clear();
    fout.close();
}

//以下几个函数为完成查找n个数中(n很大)最小的前k个数
//最大堆调整
void swap(SData *a, SData *b)
{
    SData temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

void HeapAdjust(SData *a,int i,int size)  //调整堆
{    
    int lchild=2*i;       //i的左孩子节点序号
    int rchild=2*i+1;     //i的右孩子节点序号
    int max=i;            //临时变量
    if(i<=size/2)          //如果i不是叶节点就不用进行调整
    {       
        if(lchild<=size&&a[lchild].count>a[max].count)
        {            
            max=lchild;
        }            
        if(rchild<=size&&a[rchild].count>a[max].count)
        {            
            max=rchild;
        }        
        if(max!=i)
        {            
            swap(&a[i],&a[max]);
            HeapAdjust(a,max,size);    //避免调整之后以max为父节点的子树不是堆
        }
    }
}

void BuildHeap(SData *a,int size)    //建立堆
{    
    int i;
    for(i=size/2;i>=1;i--)    //非叶节点最大序号值为size/2
    {        
        HeapAdjust(a,i,size);
    }
} 

int main()
{
    int i;
    const int k=10;
    char instr[10];
    SData Array[k+1];
    ifstream fin;
    ofstream fout;
    SData InData;

    /*fout.open("MessageData.txt");

    for(i=0;i<10000000;i++)//随机生成重复的短信,短信简化为三个字母
    {

    for(j=0;j<3;j++)
    str[j]='A'+rand()%10;
    str[3]='\0';
    fout<<str<<"\r\n";

    }
    fout.close();*/
    CHashTable cht=CHashTable();
    //MessageData.txt为存放海量信息的文本
    fin.open("MessageData.txt");
    if(fin.is_open())
    {
        while(fin>>instr)//将原短信文档读入并通过hash表处理
        {
            cht.HashCollision(instr);
        }
    }
    fin.close();
    fin.clear();

    //该函数将短信息以一定格式(如:我爱米老鼠 3453)写在result.txt中。
    cht.WriteToFile();

    //从result.txt中读取数据
    fin.open("result.txt");
    if(fin.is_open())
    {
        for(i=1;i<=k;i++)//先读取前k个
        {
            fin>>Array[i].msg>>Array[i].count;
            
        }


        cout<<"建堆:"<<endl;
        BuildHeap(Array,k);
        fin>>InData.msg>>InData.count; //继续读取文件中后面的数
        while(fin.fail()==false)//如果没有到文件尾
        {     

            if(InData.count<Array[1].count)//如果读取的数小于现有的堆的堆顶元素,则交换
            {
                Array[1]=InData;     
                HeapAdjust(Array,1,k);//调整为堆
            }
            fin>>InData.msg>>InData.count;
        }

    }
    //输出前k个数
    for(i=1;i<=k;i++)
        cout<<Array[i].msg<<" ------ "<<Array[i].count<<endl;

    return 0;

}

 上面是求重复次数最少的前10条,如果要求重复次数最多的前10条则是建立一个小顶堆。

相关文章:

  • hdu 3631(floyd思想的运用)
  • 用MDT 2012为企业部署windows 7(七)--创建标准操作系统部署任务序列
  • 自动化运维之 Kerberos 账号信息管理平台
  • POJ 1226 Substrings 解题报告
  • 集合元素并查集
  • PostgreSQL的总体架构
  • Web 应用程序项目 XXXX 已配置为使用 IIS。 无法访问 IIS 元数据库。您没有足够的特权访问计算机上的 IIS 网站。...
  • 030、 Linux 查看CPU信息、机器型号等硬件信息
  • 用Shell脚本监控服务器并发邮件报警
  • HANA学习笔记1-搭建HANA学习环境
  • linux何检查一个目录是否为空目录
  • 网站安全那些事
  • Gartner:数据审计与保护的9个关键能力
  • Mybatis 在CS程序中的应用
  • 支持高并发的IIS Web服务器常用设置
  • [译]CSS 居中(Center)方法大合集
  • css系列之关于字体的事
  • JavaScript设计模式与开发实践系列之策略模式
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • Java的Interrupt与线程中断
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • React+TypeScript入门
  • socket.io+express实现聊天室的思考(三)
  • Spring核心 Bean的高级装配
  • 阿里云应用高可用服务公测发布
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 马上搞懂 GeoJSON
  • 区块链分支循环
  • 实战|智能家居行业移动应用性能分析
  • 使用 Docker 部署 Spring Boot项目
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 在electron中实现跨域请求,无需更改服务器端设置
  • 智能合约开发环境搭建及Hello World合约
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • ​LeetCode解法汇总518. 零钱兑换 II
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • (day 12)JavaScript学习笔记(数组3)
  • (java)关于Thread的挂起和恢复
  • (动态规划)5. 最长回文子串 java解决
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (过滤器)Filter和(监听器)listener
  • (力扣)1314.矩阵区域和
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)菜鸟学数据库(三)——存储过程
  • (转载)从 Java 代码到 Java 堆
  • .net 8 发布了,试下微软最近强推的MAUI
  • .NET Core 2.1路线图
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .Net Web窗口页属性
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args