数据去重

hybest007 2009-06-22 11:41:14
比如数据:1 2 3 3 4 5 5 5

可用何种方法产生:
1 2 3 4 5

我所想到的是用map,map有自动去重功能。但map有限制,数据量上千万后,map应该装不下了吧?除此之外还有什么方法?
...全文
350 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
zlp_ghost 2009-08-16
  • 打赏
  • 举报
回复
#include <iostream>
#include <queue>
using namespace std;
main()
{

int array2[10] = {1,1,2,3,3,3,4,4,5,5};
queue<int> array1;

for(int i = 0; i < 10; i++)
{
bool flag = true;
int ArrayVal = array2[i];
for(int j = i+1; j < 10; j++)
{
if(array2[j] == ArrayVal)
flag = false;
}

if(flag == true)
array1.push(ArrayVal);

}
int j=array1.size();
for(int i = 0; i < j; i++)
{
cout<<array1.front()<<",";
array1.pop();
}

cin.get();
}
limit_clear 2009-08-11
  • 打赏
  • 举报
回复
试验下结贴后
Dancing_Sea 2009-07-08
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 yangyunzhao 的回复:]
排序的开销太大了吧?
应该用容器
[/Quote]

你以为容器对这种情况是怎么实现的?

最好
1、hash方法
2、qsort,然后去重

如果是整形,知道确切上限,并且不是很大,标记位最佳——实际也是hash方法
justdo2008 2009-07-07
  • 打赏
  • 举报
回复
/**
* 字符串去重
* @param str 需要去重的字符串
* @param regex 分隔符
* @return
*/
public String removeDuplicates(String str,String regex){
String [] arr = str.split(regex);
Set strSet = new HashSet();
CollectionUtils.addAll(strSet, arr);
Object obj[] = strSet.toArray();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < obj.length; i++) {
sb.append(obj[i].toString());
sb.append(regex);
}
return sb.substring(0, sb.length()-1);
}
lpf000 2009-06-24
  • 打赏
  • 举报
回复
貌似都是采用map的方法,应该是动态分配的吧
多少数据装不下?

萧霖 2009-06-24
  • 打赏
  • 举报
回复
学习之
  • 打赏
  • 举报
回复
假如数据的是限是50000,数据共100000个

bool a[50000];
int data[100000];
........//将数据读入
int i;
for(i = 0; i < 100000; ++i)
a[data[i]] = true; //上面写错了。
int buf[50000];
int j = 0;
for(i = 0; i < 50000; ++i)
if(a[i]) buf[j++] = i;
从buf[0]到buf[j]之间就是你要的数。

如果数据在文件中,那更好办
int r;
fscanf(infp,"%d",&r);
a[r] = true;
即可
如果结果写入文件,那也好办
for(i = 0; i < 50000; ++i)
if(a[i]) fprintf(outfp,"%d ",i);
  • 打赏
  • 举报
回复
假如数据的是限是50000,数据共100000个

bool a[50000];
int data[100000];
........//将数据读入
int i;
for(i = 0; i < 100000; ++i)
a[i] = true;
int buf[50000];
int j = 0;
for(i = 0; i < 50000; ++i)
if(a[i]) buf[j++] = i;
从buf[0]到buf[j]之间就是你要的数。
pathuang68 2009-06-23
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 pathuang68 的回复:]
引用楼主 hybest007 的帖子:
比如数据:1 2 3 3 4 5 5 5

可用何种方法产生:
1 2 3 4 5

我所想到的是用map,map有自动去重功能。但map有限制,数据量上千万后,map应该装不下了吧?除此之外还有什么方法?


绝对可以装得下,我试过的,至少1亿个整数是一点问题都没有的,
参考:STL中的map和multimap中的第3部分(用的是multimap,装载1亿条记录)
[/Quote]
sorry,记错了,试验是用了900w条数据。不过我想应该是可以装下的。
pathuang68 2009-06-23
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 mengde007 的回复:]
为什么装不下;一样能;
数据库也可以吧;我设置为关键字;
[/Quote]
赞:可以装下
否:用数据库的方式不妥,因为有重复,所以不可能将这个字段设为primary key。
pathuang68 2009-06-23
  • 打赏
  • 举报
回复
[Quote=引用楼主 hybest007 的帖子:]
比如数据:1 2 3 3 4 5 5 5

可用何种方法产生:
1 2 3 4 5

我所想到的是用map,map有自动去重功能。但map有限制,数据量上千万后,map应该装不下了吧?除此之外还有什么方法?
[/Quote]
绝对可以装得下,我试过的,至少1亿个整数是一点问题都没有的,
参考:STL中的map和multimap中的第3部分(用的是multimap,装载1亿条记录)
heroctf 2009-06-23
  • 打赏
  • 举报
回复
。。。。。。
容器中vector是自增长的。但是set和map就不是了
你可以用set<unsigned long>来处理啊!!!
yangyunzhao 2009-06-23
  • 打赏
  • 举报
回复
排序的开销太大了吧?
应该用容器
coreyao1988 2009-06-23
  • 打赏
  • 举报
回复
学习了~~~~
hybest007 2009-06-23
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 xteaj 的回复:]
无符号整数,用bool数组方法最好啦,bool a[8]也就占一个字节,比较节省内存的。而且各方面都快。
先排序也需要时间,一个一个比较也需要时间,用bool数组应该是最快的,但浪费了空间。以空间换时间。
[/Quote]

怎么用啊?
  • 打赏
  • 举报
回复
无符号整数,用bool数组方法最好啦,bool a[8]也就占一个字节,比较节省内存的。而且各方面都快。
先排序也需要时间,一个一个比较也需要时间,用bool数组应该是最快的,但浪费了空间。以空间换时间。
lqy05wx 2009-06-23
  • 打赏
  • 举报
回复
[Quote=引用楼主 hybest007 的帖子:]
比如数据:1  2  3  3  4  5  5  5

可用何种方法产生:
1  2  3  4  5

我所想到的是用map,map有自动去重功能。但map有限制,数据量上千万后,map应该装不下了吧?除此之外还有什么方法?

[/Quote]
论坛里面有很多这方面的讨论,如果对数据有一定的信息支持(至少知道最小和最大,是不是正整数)
如果满足可以用位图来做预处理,可以节省空间
hybest007 2009-06-23
  • 打赏
  • 举报
回复
map效率有点低,不用map还有什么可行方案吗?
pathuang68 2009-06-23
  • 打赏
  • 举报
回复
下面用map的方式解决这个问题的代码(不考虑性能问题,只为了验证map可以装载1kw条记录),请大家指正:

1. 生成数据库文件程序,
2. 保证只有20个不重复的数字
3. 共1000w条记录

#include <iostream>
#include <fstream>
#include <string>
#include <time.h>
using namespace std;
// 生成info.txt的据程序
// info.txt中有1000万行数据
int main ()
{
char buffer[28];
clock_t start, finish;
ofstream outfile ("info.txt");

// 获取写物理文件起始时钟周期
start = clock();
for(int i = 1; i < 10000000; i++)
{
sprintf(buffer, "%d\n", i%20); // 保证只有20个不重复的数据
outfile.write (buffer, strlen(buffer));
}
// 获取写文件结束时钟周期
finish = clock();
int interval = (finish - start) * 1000 / CLOCKS_PER_SEC;
cout << "写物理文件所花时间:" << interval << "ms" << endl; // 5828ms
outfile.close();

return 0;
}

写文件花了5828ms

下面是重上面生成的文本文件中读取数据并存入到map中:

#include <iostream>
#include <fstream>
#include <map>
#include <string>
using namespace std;
// 用map的方式解决
int main(void)
{
ifstream fin("info.txt");
if(!fin)
{
cout << "can not open file..." << endl;
}

// 创建map,第一个int做为key,第二个string作为value
map<int, string> linemap;
int intkey;
string strvalue = " ";
char linestring[26];
clock_t start, finish;

// 写入linemap起始时钟周期
start = clock();
while(fin)
{
// 读取info.txt的一行,存入linestring
fin.getline(linestring, 26);
intkey = atoi(linestring);

// 将key,value对存入map中
linemap.insert(pair<int, string>(intkey, strvalue));
}
// 写入linemap结束时钟周期
finish = clock();
fin.close();

cout << (finish - start) * 1000 / CLOCKS_PER_SEC << "ms elapsed." << endl; // 7360ms
// 检查数据被插入后,是否根据strkey排序了 -> 结论:排序了
// 即使info.txt中有重复的key,也只会有第一行含有key的文本,会被读入到map中

cout << linemap.size() << endl; // 20,即只有20个不重复的数据

map<int, string>::iterator p;
for(p = linemap.begin(); p != linemap.end(); ++p)
{
cout << p->first << endl;
}
return 0;
}

1. 需时7360ms
2. map中只有20个数字,而且是排好序的
3. 20个数字是0,1,2, ... 19

map的效率似有点不太好,不过承载1000w条记录还是没有问题的。
mabelsz 2009-06-23
  • 打赏
  • 举报
回复
加载更多回复(14)

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧