大数据处理算法三:分而治之/hash映射 + hash统计 + 堆/快速/归并排序

百度面试题1、海量日志数据,提取出某日访问百度次数最多的那个IP。

IP 是32位的,最多有个2^32个IP。同样可以采用映射的方法,比如模1000,把整个大文件映射为1000个小文件,再找出每个小文中出现频率最大的 IP(可以采用hash_map进行频率统计,然后再找出频率最大的几个)及相应的频率。然后再在这1000个最大的IP中,找出那个频率最大的IP,即 为所求。

百度面试题2、搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。

假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。),请你统计最热门的10个查询串,要求使用的内存不能超过1G。

第 一步借用hash统计进行预处理: 先对这批海量数据预处理(维护一个Key为Query字串,Value为该Query出现次数,即Hashmap(Query,Value),每次读取一 个Query,如果该字串不在Table中,那么加入该字串,并且将Value值设为1;如果该字串在Table中,那么将该字串的计数加一即可。最终我 们在O(N)(N为1千万,因为要遍历整个数组一遍才能统计处每个query出现的次数)的时间复杂度内用Hash表完成了统计;

第二步借用堆排序找出最热门的10个查询串:时间复杂度为N‘*logK。维护一个K(该题目中是10)大小的小根堆,然后遍历3百万个Query,分别和根元素进行对比(对比value的值),找出10个value值最大的query

最终的时间复杂度是:O(N) + N‘*O(logK),(N为1000万,N’为300万)

或者:采用trie树,关键字域存该查询串出现的次数,没有出现为0。最后用10个元素的最小推来对出现频率进行排序。

我们先看HashMap 实现

1. HashMap的数据结构

数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端。

数组

数组存储区间是连续的,占用内存严重,故空间复杂的很大。但数组的二分查找时间复杂度小,为O(1);数组的特点是:寻址容易,插入和删除困难;

链表

链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N)。链表的特点是:寻址困难,插入和删除容易。

哈希表

那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表。哈希表((Hash table)既满足了数据的查找方便,同时不占用太多的内容空间,使用也十分方便。

  哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法—— 拉链法,我们可以理解为“链表的数组”

我用java 自己实现了一个HashMap,当然这比较简点,不过能说明大概原理,改有的功能基本上有了

index=hashCode(key)=key%16

哈希算法很多,下面我用了java自带的,当然你也可以用别的

/**
 * 自定义 HashMap
 * @author JYC506
 *
 * @param <K>
 * @param <V>
 */
public class HashMap<K, V> {

	private static final int CAPACTITY = 16;

	transient Entry<K, V>[] table = null;

	@SuppressWarnings("unchecked")
	public HashMap() {
		super();
		table = new Entry[CAPACTITY];
	}

	/* 哈希算法 */
	private final int toHashCode(Object obj) {
		int h = 0;
		if (obj instanceof String) {
			return StringHash.toHashCode((String) obj);
		}
		h ^= obj.hashCode();
		h ^= (h >>> 20) ^ (h >>> 12);
		return h ^ (h >>> 7) ^ (h >>> 4);
	}
   /*放入hashMap*/
	public void put(K key, V value) {
		int hashCode = this.toHashCode(key);
		int index = hashCode / CAPACTITY;
		if (table[index] == null) {
			table[index] = new Entry<K, V>(key, value, hashCode);
		} else {
			for (Entry<K, V> entry = table[index]; entry != null; entry = entry.nextEntry) {
				if (entry.hashCode == hashCode && (entry.key == key || key.equals(entry.key))) {
					entry.value = value;
					return;
				}
			}
			Entry<K, V> entry2 = table[index];
			Entry<K, V> entry3 = new Entry<K, V>(key, value, hashCode);
			entry3.nextEntry = entry2;
			table[index] = entry3;

		}
	}
   /*获取值*/
	public V get(K key) {
		int hashCode = this.toHashCode(key);
		int index = hashCode / CAPACTITY;
		if (table[index] == null) {
			return null;
		} else {
			for (Entry<K, V> entry = table[index]; entry != null; entry = entry.nextEntry) {
				if (entry.hashCode == hashCode && (entry.key == key || key.equals(entry.key))) {
					return entry.value;
				}
			}
			return null;

		}
	}
	 /*删除*/
	public void remove(K key){
		int hashCode = this.toHashCode(key);
		int index = hashCode / CAPACTITY;
		if (table[index] == null) {
			return ;
		} else {
			Entry<K, V> parent=null;
			for (Entry<K, V> entry = table[index]; entry != null; entry = entry.nextEntry) {
				if (entry.hashCode == hashCode && (entry.key == key || key.equals(entry.key))) {
					if(parent!=null){
						parent.nextEntry=entry.nextEntry;
						entry=null;
						return ;
					}
				}
				parent=entry;
			}
		}
	}
	public static void main(String[] args) {
		HashMap<String,String> map=new HashMap<String,String>();
		map.put("1", "2");
		map.put("1", "3");
		map.put("3", "哈哈哈");
		System.out.println(map.get("1"));
		System.out.println(map.get("3"));
		map.remove("1");
		System.out.println(map.get("1"));
	}

}

class Entry<K, V> {
	K key;
	V value;
	int hashCode;
	Entry<K, V> nextEntry;

	public Entry(K key, V value, int hashCode) {
		super();
		this.key = key;
		this.value = value;
		this.hashCode = hashCode;
	}

}

/* 字符串hash算法 */
class StringHash {
	public static final int toHashCode(String str) {
		/* 我用java自带的 */
		return str.hashCode();
	}
}
时间: 2024-11-05 04:49:31

大数据处理算法三:分而治之/hash映射 + hash统计 + 堆/快速/归并排序的相关文章

海量数据处理策略之一—Hash映射 + Hash_map统计 + 堆/快速/归并排序

时间:2014.05.21 地点:基地 说明:根据July的博客等整理,感谢July的无私奉献 心情:现在都好开心呀,想着要为以后的时光好好奋斗~ --------------------------------------------------------------------------------------- 一.问题描述 海量日志数据,提取出某日访问百度次数最多的那个IP. 思路:由于数据集很大,我们的策略是先用哈希映射将海量数据集映射为适当数量的非海量数据集,这个非海量数据集的大

海量数据处理:Hash映射 + Hash_map统计 + 堆/快速/归并排序

海量日志数据,提取出某日访问百度次数最多的那个IP. 既然是海量数据处理,那么可想而知,给我们的数据那就一定是海量的. 针对这个数据的海量,我们如何着手呢?对的,无非就是分而治之/hash映射 + hash统计 + 堆/快速/归并排序,说白了,就是先映射,而后统计,最后排序: 分而治之/hash映射:针对数据太大,内存受限,只能是:把大文件化成(取模映射)小文件,即16字方针:大而化小,各个击破,缩小规模,逐个解决 hash_map统计:当大文件转化了小文件,那么我们便可以采用常规的hash_m

海量数据面试题----分而治之/hash映射 + hash统计 + 堆/快速/归并排序

1.从set/map谈到hashtable/hash_map/hash_set 稍后本文第二部分中将多次提到hash_map/hash_set,下面稍稍介绍下这些容器,以作为基础准备.一般来说,STL容器分两种: 序列式容器(vector/list/deque/stack/queue/heap), 关联式容器.关联式容器又分为set(集合)和map(映射表)两大类,以及这两大类的衍生体multiset(多键集合)和multimap(多键映射表),这些容器均以RB-tree完成.此外,还有第3类关

大数据处理算法二:Bloom Filter算法

百度面试题:给定a.b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a.b文件共同的url? Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法.通常应用在一些需要快速判断某个元素是否属于集合,但是并不严格要求100%正确的场合.   一. 实例  为了说明Bloom Filter存在的重要意义,举一个实例: (实例一),假设要你写一个网络蜘蛛(web crawler).由于网络间的链接错综复杂,蜘蛛在网络间爬行很可能会形成

流式大数据处理的三种框架:Storm,Spark和Samza

许多分布式计算系统都可以实时或接近实时地处理大数据流.本文将对三种Apache框架分别进行简单介绍,然后尝试快速.高度概述其异同. Apache Storm 在Storm中,先要设计一个用于实时计算的图状结构,我们称之为拓扑(topology).这个拓扑将会被提交给集群,由集群中的主控节点(master node)分发代码,将任务分配给工作节点(worker node)执行.一个拓扑中包括spout和bolt两种角色,其中spout发送消息,负责将数据流以tuple元组的形式发送出去:而bolt

马化腾漫谈“流式大数据处理的三种框架:Storm,Spark和Samza”

Apache Storm 在Storm中,先要设计一个用于实时计算的图状结构,我们称之为拓扑(topology).这个拓扑将会被提交给集群,由集群中的主控节点(master node)分发代码,将任务分配给工作节点(worker node)执行.一个拓扑中包括spout和bolt两种角色,其中spout发送消息,负责将数据流以tuple元组的形式发送出去:而bolt则负责转换这些数据流,在bolt中可以完成计算.过滤等操作,bolt自身也可以随机将数据发送给其他bolt.由spout发射出的tu

C++大数据处理

转:http://blog.csdn.net/v_july_v/article/details/7382693 作者:July出处:结构之法算法之道blog 前言 一般而言,标题含有“秒杀”,“99%”,“史上最全/最强”等词汇的往往都脱不了哗众取宠之嫌,但进一步来讲,如果读者读罢此文,却无任何收获,那么,我也甘愿背负这样的罪名,:-),同时,此文可以看做是对这篇文章:十道海量数据处理面试题与十个方法大总结的一般抽象性总结. 毕竟受文章和理论之限,本文将摒弃绝大部分的细节,只谈方法/模式论,且注

大数据处理之道 (MATLAB 篇&lt;三&gt;)

一:起因 (1)最近一直在处理大数据,从MB ----> GB的变化,是一次质的飞跃,相应的工具也在变 从widows到linux,从单机单核 到 hadoop多节点的计算 (2)问题来了,面对海量的数据,如何从中挖掘实用的信息或者发现潜在的现象,可视化工具可能是必不可少的 : (3)可视化工具可以说百度一大篇,可是作为研究者的我们,程序猿的我们可能更希望能够抽象出一种数学模型,对现实的现象进行非常好的描述和刻画 (4)Python(数据清洗和处理) + MATLAB(模型分析) 或 c++/j

hdu 4941 Magical Forest(hash映射)

题目链接:hdu 4941 Magical Forest 题目大意:给定N,M和K,表示在一个N*M的棋盘上有K个棋子,给出K个棋子的位置和值,然后是Q次操作,对应的是: 1 a b :交换a和b两行 2 a b : 交换a和b两列 3 a b :查询a b这个位置上棋子的值,没有棋子的话输出0 解题思路:一开始X[i]=i,X[j]=j,如果需要交换i和j,那么就令X[i]=j,X[j]=i即可,因为N和M很大,所以用map映射. #include <cstdio> #include <