`
981875739
  • 浏览: 7659 次
  • 性别: Icon_minigender_2
  • 来自: 长沙
社区版块
存档分类
最新评论

M个int 排重分析

阅读更多

 

最近两周学习研究了有关大数据的解决办法,下面就M个int(数据量很大,大于内存)排重进行浅层分析。做这种大数据的问题,我们要真正的动脑筋去想解决办法,在可行的条件下最好自己去实践一下,否则也只能是纸上谈兵。

 

对几亿个int型数据进行排重,我们的电脑内存空间都是有限的【以1G内存为例,我们最多存2^30B,也就是是2^28个int(1GB=1024MB,1MB=1024KB,1KB=1024B)】想要把数据都装入数组中,那显然是装不下的~~那么怎么样才可行呢?

 

下面分析一下解决办法:

方法一:

将大数据分为若干部分,在每个小部分里面先进行一次排序(从大到小),每次从每个部分中取出各自最大的那个,再在其中选出最大存入文件,在拿若干个数据进行比较,选出第二大的,若与前一个元素相同,则舍去,不同则写入文件。这样依次进行下去,遍历完所有的数据也就完成了排重的工作。

但是这个方法需要扫描数据两遍,比较费事,在时间花销上应该是很大的。

那么有没有其他更好的方法呢?

方法二:

1个int—>4个Byte—>32个bit

试想想,我们可不可以在1个int里存入32个数据的相关信息呢?这样的话,是不是将占用的内存降低到1/32了呢?

将一个int表示为32位的01字符串,如果对应位置的数据存在就把bit设为1,不存在就为0。

假设有数据“5”,那么就把第5个位置的0改成1

将01串转换成int存入数组里就可以了

下面看一下我写的方法,比较简单

 

package Eliminate;

/**
 * 一组int很多,排重
 * @author Administrator
 * 最多有2^32(2147483647])个int数字,用一个bit来表示,最多用2^27大小的数组来表示
 */
	
public class Eliminate {

		/**
		 * 将一个32位的字符串转成一个整数
		 * 
		 * @param s
		 * @return
		 */
		public int stringTOint(String s) {
			int a=(int) (((int) s.charAt(0) - 48) * (2147483647+1));
			
			int b=(int)((int) s.charAt(1) - 48) * 1073741824 + ((int) s.charAt(2) - 48)* 536870912
					+ ((int) s.charAt(3) - 48) * 268435456+ ((int) s.charAt(4) - 48) * 134217728
					+ ((int) s.charAt(5) - 48) * 67108864 + ((int) s.charAt(6) - 48) * 33554432
					+ ((int) s.charAt(7) - 48) * 16777216 + ((int) s.charAt(8) - 48) * 8388608;
			
			int c=(int)((int) s.charAt(9) - 48) * 4194304 + ((int) s.charAt(10) - 48)*2097152
			        + ((int) s.charAt(11) - 48) * 1048576 + ((int) s.charAt(12) - 48)*524288
					+ ((int) s.charAt(13) - 48) *  262144+ ((int) s.charAt(14) - 48) * 131072
					+ ((int) s.charAt(15) - 48) * 65536 + ((int) s.charAt(16) - 48) * 32768 
					+ ((int) s.charAt(17) - 48)*16384+ ((int) s.charAt(18) - 48) * 8192
					+ ((int) s.charAt(19) - 48)*4096 + ((int) s.charAt(20) - 48) * 2048
					+ ((int) s.charAt(21) - 48) * 1024 + ((int) s.charAt(22) - 48) * 512
					+ ((int) s.charAt(23) - 48) * 256 + ((int) s.charAt(24) - 48)* 128
					+ ((int) s.charAt(25) - 48) * 64 + ((int) s.charAt(26) - 48)* 32 
					+ ((int) s.charAt(27) - 48) * 16+ ((int) s.charAt(28) - 48) * 8 
					+ ((int) s.charAt(29) - 48) * 4+ ((int) s.charAt(30) - 48) * 2
					+ ((int) s.charAt(31) - 48);
			return a+b+c;
					
		}
		
		/**
		 * 将int型转化为32位的bit
		 */
		public  String intTOstring(int index){
			String str=Integer.toBinaryString(index);
			int strlength=str.length();
			if(strlength<32){
				for(int i=0;i<32-strlength;i++){
					str="0"+str;
				}
			}
			return str;
		}
		
		/**
		 * 打印最终排重结果输出 
		 * @param args
		 */
		public void  print(int src[]){
			int number;
			int count=0;
			//将src数组中的数据还原成01字符串,找出相应位置的下标
			//循环src数组
			for(int i=1;i<src.length;i++){
				String s=intTOstring(src[i]);
				System.out.println(s);
				for(int j=0;j<s.length();j++){
					if(s.charAt(j)=='1'){
						number=(i-1)*32+j;
						count++;
						System.out.print(number+"  ");					
					}
					
				}
				System.out.println();
			}
			System.out.println("排重后的数据有"+count+"个");
			
		}
		
		
	}

测试代码:


package Eliminate;

import java.util.Random;

public class Test {
	private static  int SrcSize=80000;//最多用2^27大小的数组来表示
	private static int M =1000000;//数据量
	private static  int [] src=new int [SrcSize];
	private static  Random r=new Random();
	
	/**
	 * 主函数
	 * @param args
	 */
    public static void main(String args[]){
    	Long BeginTime=System.currentTimeMillis(); 
    	Eliminate e=new Eliminate();
		int temp;//随机数
		int number;//商
		int index;//数组下标
		int mod;//余数
		int x;
		for(int i=0;i<M;i++){
			    temp=r.nextInt(2000000);	
			    System.out.print(temp+" ");
			    System.out.println();
				number=temp/32;//取商			
				index=number+1;
				mod=temp%32;//取余			
				//将int型转化为32位的bit
				String str=e.intTOstring(src[index]);
				//修改mod处的bit值
				String newStr=new String();
                for(int j=0;j<32;j++){
                	char c=str.charAt(j);
                	if(j==mod){
                		newStr=newStr+1;             		
                	}else{
                		newStr=newStr+c;
                	}
                }
                //将修改后的字符串转化为int,放回数组
			    x=e.stringTOint(newStr);
			    src[index]=x;
			
		}
		e.print(src);
		Long EndTime=System.currentTimeMillis();
        System.out.println("排重时间为:"+(EndTime-BeginTime));
	}
}

由于时间问题,没有对很庞大的数据进行测试。这里的数据量为100万,数组大小为8万

测试结果:

 

排重后的数据有786678个

排重时间为:9344


个人认为排重速度还是不错的~~是不是很有效哟~~

下面进行了一个小数据的测试,证明方法的有效和正确性:

测试结果:
随机产生数据50个:
83 62 85 29 98 21 22 36 84 13 50 33 90 39 17 26 90 52 15 56 54 85 19 48 75 46 93 36 52 14 8 44 68 36 24 22 63 30 54 18 28 95 92 98 92 67 36 49 63 51

00000000100001110111011010101110
8  13  14  15  17  18  19  21  22  24  26  28  29  30  
01001001000010101111101010000011
33  36  39  44  46  48  49  50  51  52  54  56  62  63  
00011000000100000001110000101101
67  68  75  83  84  85  90  92  93  95  
00100000000000000000000000000000
98  
排重后的数据有39个
排重时间为:15

以上就是M个int(数据量很大,大于内存)排重的分析及解决方案,大数据问题还有很多很多,还需要进一步的分析研究~~应该会很有趣哟~~

 

 

分享到:
评论
1 楼 lixiongzhi_m 2013-01-21  
   不知道是不是我理解上的差异。这个方法的核心是不是比如有0,1,2,3、、、、31这样的32个数字我们可以用三十二个1也就是来表示,将他转换成一个int即2^32-1来表示,然后存储到数组中。这样当我们要去用的时候取出来,逆过程:先将这个数取出来然后转换成32个01串,1代表这个位置有数字0代表没有。
    这样数组下标为0的一个数能存储0到31,为1的能存储32到63,依次列推。
    是不是大概是这样的思路???要是不是的话那么可能是我理解上的错误。要是是 的话那么这边有几个问题?
    1.要是这M个数中有两个一样的,因为这些01串的位置都是唯一的,那么该如何去存储?
    2.还有这样一个情况,这个M不大,但其中有一个数非常的大,那么这个大数按这种方法存储到数组下标对应的数字也就比较大。那么这些不多的数按道理来讲是不是也要开个大数组来存储?

相关推荐

    java 经典习题.doc

    1.程序分析:利用for循环控制100-999个数,每个数分解出个位,十位,百位。 【程序4】 题目:将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。 程序分析:对n进行分解质因数,应先找到一个最小的质数k...

    最新JAVA编程题全集_50题及答案

    程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除, 则表明此数不是素数,反之是素数。 public class lianxi02 { public static void main(String[] args) { int count = 0; for(int i=...

    c程序设计习题参考(谭浩强三版)习题参考解答

    10.4有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成前面m个数。 75 写一函数实现以上功能,在主函数中输入n个整数,并输出调整后的n个数。 75 10.5有一字符串,包含n个字符。写一个函数,将此字符串中从...

    北邮信通院数据结构实验_车厢重排问题代码

    给定任意次序的车厢,通过转轨站将车厢编号按顺序重新排成1~n。转轨站共有k个缓冲轨,缓冲轨位于入轨和出轨之间。开始时,车厢从入轨进入缓冲轨,经过缓冲轨的重排后,按1~n的顺序进入出轨。缓冲轨按照先进先出方式...

    约瑟夫问题全集

    約瑟夫問題可用代數分析來求解,將這個問題擴大好了,假設現在您與m個朋友不幸參與了這個遊戲,您要如何保護您與您的朋友?只要畫兩個圓圈就可以讓自己與朋友免於死亡遊戲,這兩個圓圈內圈是排列順序,而外圈是自殺...

    大数据的一些面试题.pdf

    ⾸先我们 将int划分为2^16个区域,然后读取数据统计落到各个区域⾥的数的个数,之后我们根据统计结果就 可以判断中位数落到那个区域,同时知道这个区域中的第 ⼏⼤数刚好是中位数。然后第⼆次扫描我们只统计落在这个...

    软件课程设计 试验报告 代码 演示

    本题主要是要求设计一个程序,让用户输入正整数m ,它代表一个人民币钱数(元数),由程序计算一个最有方法,使人民币纸币的张数最少,并凑成上述的钱数m 。 ///////////////////////////////////////////// 程序...

    你必须知道的495个C语言问题(PDF)

    4.4 我有个函数,它应该接受并初始化一个指针void f(int *ip) f static int dummy = 5; ip = &dummy;g 但是当我如下调用时: int *ip; f(ip); 调用者的指针却没有任何变化。. . . . . . . . . . . . . . . 18 4.5 我...

    C语言程序设计标准教程

    int类型,该类型占两个字节的内存空间,所以每个元素均占有两个 字节(图中每一格为一字节)。 二维数组元素的表示方法  二维数组的元素也称为双下标变量,其表示的形式为: 数组名[下标][下标] 其中下标应为整型...

    uboott移植实验手册及技术文档

    int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size) { int i, j; Create PDF files without this message by purchasing novaPDF printer (http://www.novapdf.com) if ((start_addr & ...

    C语言程序设计经典例子

    题目:有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。 1. 程序分析:首先判断此数是否大于最后一个数,然后再考虑插入中间的数的情况,插入后  此元素之后的数,依次后移一个位置。 2....

    c++课程设计--保安排班系统.doc

    四 系统实现与测试 4.1 主菜单 4.1.1主菜单流程图 图4.1主菜单流程图 4.1.2主菜单代码 int main() { int m; string p; int t=1; while(t!=0) { system("cls"); cout****************欢迎进入排班系统*

    c++课程设计保安排班系统.doc

    四 系统实现与测试 4.1 主菜单 4.1.1主菜单流程图 图4.1主菜单流程图 4.1.2主菜单代码 int main() { int m; string p; int t=1; while(t!=0) { system("cls"); cout****************欢迎进入排班系统**************...

    C语言课程设计-商场商品信息管理系统.doc

    /*最多200个商品*/ 2 系统设计 2.1 总体设计 按系统分析的功能要求将系统划分为以下几个主要功能模块: 文件管理 文件打开、关闭:对于刚输入或进行操作后的商品信息,在建立新的商品库存量后, 可以把其保存在一个...

    计算机二级公共基础知识

    在满二叉树中,每一层上的结点数都达到最大值,即在满二叉树的第k层上有2k-1个结点,且深度为m的满二叉树有2m-1个结点。 完全二叉树是指这样的二叉树:除最后一层外,每一层上的结点数均达到最大值;在最后一层上只...

    二十三种设计模式【PDF版】

    o m m u n i c a t i n go b j e c t)的重复模式。这些模式解决特定的设计问题,使面向对象设计更灵活、优雅,最终复用性更 好。它们帮助设计者将新的设计建立在以往工作的基础上,复用以往成功的设计方案。 一个...

    Vs2008快捷键和技巧文本

    "isqlw" 这是SQL2000的我也提供一下吧,这个可以起到SQL2000的查询分析器。 "devenv" 启动相应版本的VS Studio 17、Ctrl提示透明窗口 这是一个比较有意思的键。VS2005下,当你在调试代码的时候,有时候提示信息会...

    51单片机C语言编程基础及实例

    P3 支持第二功能:RXD、TXD、INT0、INT1、T0、T1 单片机内部 I/O 部件:(所为学习单片机,实际上就是编程控制以下 I/O 部件,完成指定任务) 1. 四个 8 位通用 I/O 端口,对应引脚 P0、P1、P2 和 P3; 2. 两个 16 位...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    角色是一组权限的集合,将角色赋给一个用户,这个用户就拥有了这个角色中的所有权限。  系统预定义角色 预定义角色是在数据库安装后,系统自动创建的一些常用的角色。下面我们就简单介绍些系统角色:  CONNECT...

    大学文献检索资料 DOC

    51 Int.Cl. E04D 5/10 11 公开号 CN123917A 21 申请号 98 112102.0 22 申请日 98. 6.17 71 申请人 重庆大学 72 发明人 江涛 李燕红 74 专利代理机构 重庆大学专利事务所 代理人 张敏 54 发明名称 屋面...

Global site tag (gtag.js) - Google Analytics