【演算法】海量資料處理:有一千萬條簡訊,有重複,以文字形式儲存,一行一條,找出重複最少的前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;
}
相關文章
- excel刪除重複資料保留一條 如何刪掉重複資料只留一條Excel
- dataset 判斷整列是否有重複,找出重複資料
- Oracle:重複資料去重,只取最新的一條資料Oracle
- mysql刪除重複記錄,儲存Id最小的一條MySql
- Oracle 刪除重複資料只留一條Oracle
- mysql 查詢出重複資料的第一條MySql
- 海量資料處理_刪除重複行
- python 如何一次隨機取出多條資料(能重複/不能重複)Python隨機
- 複合條件查詢的重構
- 陣列合並且去重&向一個陣列新增一條資料(重複的就不新增)&陣列物件去重處理陣列物件
- MySQL 處理重複資料MySql
- Oracle 重複資料處理Oracle
- sql刪除重複記錄只保留一條SQL
- WPS表格技巧:巧用條件格式查詢重複資料
- MySQL刪除重複記錄並保留第一條MySql
- 資料處理之去除重複資料
- 一條細小的報警簡訊的處理
- Oracle如何刪除表中重複記錄保留第一條Oracle
- 重構複雜條件的規則設計模式 - levelup設計模式
- json字串返回的資料有重複的資料JSON字串
- SQL刪除重複資料,只保留一行SQL
- SQL 處理重複值SQL
- 求一條sql關於按分組重複值不顯示?SQL
- 重構遺留程式碼(3):複雜的條件語句
- 有重複元素的全排列
- Mysql語句查詢指定重複記錄和刪除重複記錄僅保留一條【親測可以】MySql
- Python中去除重複資料的方法有哪些?Python
- 印表機打出來有條紋怎麼處理 印表機打出來有間隔白條
- 請給Array本地物件增加一個原型方法,它用於刪除陣列條目中重複的條目(可能有多個),返回值是一個包含被刪除的重複條目的新陣列。...物件原型陣列
- 判斷表中資料是否有重複
- 查詢前10條資料oracleOracle
- 查詢/刪除重複的資料(單個欄位和多個欄位條件)
- 你的程式碼有重複嗎?
- 有重複元素的排列問題
- AIX條帶化、儲存條帶化、ASM條帶化AIASM
- SqlServer中根據某幾列獲取重複的資料將其刪除並保留最新一條SQLServer
- 在陣列中找出唯一的重複元素陣列
- 從一條資料說起——InnoDB儲存資料結構資料結構