HashMap Java 和 C++的实现比较

1. Java中Map/HashMap/TreeMap的分析

Map/HashMap其存储是没有顺序的,而TreeMap则是有序存储。

参考链接:

http://blog.csdn.net/devillyd/article/details/3135479

http://coolshell.cn/articles/9703.html

import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Hashtable;
import java.util.TreeMap;
class  HashMaps
{
       public static void main(String[] args)
      {
            Map map=new HashMap();           
            map.put("a", "aaa");
            map.put("b", "bbb");
            map.put("c", "ccc");
            map.put("d", "ddd");
          
            Iterator iterator = map.keySet().iterator();           
            while (iterator.hasNext()) {
             Object key = iterator.next();
             System.out.println("map.get(key) is :"+map.get(key));
            }      
           
           
           
            Hashtable tab=new Hashtable();           
            tab.put("a", "aaa");
            tab.put("b", "bbb");
            tab.put("c", "ccc");
            tab.put("d", "ddd");
            Iterator iterator_1 = tab.keySet().iterator();
            while (iterator_1.hasNext()) {
             Object key = iterator_1.next();
             System.out.println("tab.get(key) is :"+tab.get(key));
            }        
           
            TreeMap tmp=new TreeMap();           
            tmp.put("a", "aaa");
            tmp.put("b", "bbb");
            tmp.put("c", "ccc");
            tmp.put("d", "ddd");
            Iterator iterator_2 = tmp.keySet().iterator();
            while (iterator_2.hasNext()) {
             Object key = iterator_2.next();
             System.out.println("tmp.get(key) is :"+tmp.get(key));
            }        
                     
        
       }
    
}
运行结果如下:

map.get(key) is :ddd
map.get(key) is :bbb
map.get(key) is :ccc
map.get(key) is :aaa
tab.get(key) is :bbb
tab.get(key) is :aaa
tab.get(key) is :ddd
tab.get(key) is :ccc
tmp.get(key) is :aaa
tmp.get(key) is :bbb
tmp.get(key) is :ccc
tmp.get(key) is :ddd

2.GCC下C++ HashMap的表达


hash_map散列表本身不在ISO的STL和C++标准库中,不属于标准的一部分,不适用于跨编译器使用。一个编译器能用,另一个可能不能用。比如gcc下,hash_map已经被归为旧版兼容的工具,需要用__gnu_cxx::hash_map名字空间才能使用,而非标准的std::推荐用符合ISO标准map容器(红黑树表)替代。如果没有明显的性能差距,多用map而不是hash_map。


按照hashmap的基本原理用C++实现了简单的基本功能,复杂的实现参考C++库的源码,C++最新的标准库里已经有以下四种基于hashtable的容器:

unordered_set(C++11)unordered_multiset(C++11)unordered_map(C++11)unordered_multimap (C++11)

具体参考:http://en.cppreference.com/w/

http://www.cnblogs.com/luxiaoxun/archive/2012/09/02/2667782.html


#include <string>
#include <iostream>
#include <ext/hash_map>
using namespace std;
using namespace __gnu_cxx;

struct str_hash {
    size_t operator() (const string & s) const {
        return __stl_hash_string(s.c_str());
}};

struct str_compare {
    int operator() (const string & a, const string & b) const {
        return (a == b);
}};
typedef hash_map < string, string, str_hash, str_compare > StrMap;

int main()
{
    StrMap strMap;
    string a, b;
    cout << "鎻掑叆:" << endl;
    while (cin >> a >> b) {
        if (a.length() <= 1)
            break;
        strMap.insert(make_pair(a, b));
    }
    cout << "鏌ヨ:" << endl;
    while (cin >> a) {
        if (a.length() <= 1)
            break;
        if (strMap.find(a) != strMap.end())
            cout << strMap[a] << endl;
        else
            cout << "not found" << endl;
    }
    return 0;
}

利用unordered_map实现如下:

/*
 * =====================================================================================
 *
 *       Filename:  unordered_map.cc
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2014年01月17日 16时38分01秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  lishuming (think different and do it with plearsure.), lism2013@hotmail.com
 *   Organization:  RADI A401
 *
 * =====================================================================================
 */

#include <iostream>
#include <unordered_map>
#include <string>
 using namespace std;

unsigned int JSHash(const char *str)
{
    unsigned int hash = 1315423911;
    while (*str)
    {
    	hash ^= ((hash << 5) + (*str++) + (hash >> 2));
    }
    return (hash & 0x7FFFFFFF);
}

struct StrHash {
    size_t operator() (const string & s) const {
    	return JSHash(s.c_str());
}};
struct StrCompare {
    bool operator() (const string & a, const string & b) const {
	return a == b;
}};
typedef unordered_map < string, string, StrHash, StrCompare > MyMap;
int main()
{
    MyMap mymap;
    string a, b;
    while (cin >> a >> b)
    {
      	mymap[a] = b;
    }
    for (MyMap::iterator it = mymap.begin(); it != mymap.end(); ++it)
	      cout << it->first << " " << it->second << endl;
    return 0;
}


HashMap 利用C++的具体实现

/*
 * =====================================================================================
 *
 *       Filename:  HashMap.h
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2014年01月17日 16时56分40秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  lishuming (think different and do it with plearsure.), lism2013@hotmail.com
 *   Organization:  RADI A401
 *
 * =====================================================================================
 */
/*
    * HashMap.h
     * Author: luxiaoxun
      */

#ifndef HASHMAP_H_
#define HASHMAP_H_

#include <iostream>
using namespace std;

//List all the integer number no less than 57 total number is 28
//And each number is about half of its next number
static int prime[28] = {
    57, 97, 193, 389, 769,
    1543, 3079, 6151, 12289, 24593,
    49157, 98317, 196613, 393241, 786433,
    1572869, 3145739, 6291469, 12582917, 25165843,
    50331653, 100663319, 201326611, 402653189, 805306457,
};

class HashMapUtil {
  public:
    static int find_NextPrimeNumber(int current) {
	//Find the next prime number by searching in the prime number list
	int i = 0;
	for (; i < 28; i++)
	    if (current < prime[i])
		 break;
	 return prime[i];	//return the next larger prime.
    }
};

template < class Key, class Value, class HashFunc, class EqualKey >
    class HashMap
{
  private:
    template < class _Key, class _Value > class KeyNode
    {
      public:
	_Value value;		//Store the value
	_Key key;		//Store the keyword
	int used;
	//if the type of Value/Key is your own class, make sure they can handle copy constructor and operator =
      KeyNode():used(0)
	{
	}
	KeyNode(const KeyNode & kn) {
	    value = kn.value;
	    key = kn.key;
	    used = kn.used;
	}
	KeyNode & operator=(const KeyNode & kn) {
	    if (this == &kn)
		return *this;
	    value = kn.value;
	    key = kn.key;
	    used = kn.used;
	    return *this;
	}
    };

  public:
    HashMap();
    ~HashMap();
    bool insert(const Key & hashKey, const Value & value);
    bool remove(const Key & hashKey);
    void rehash();		//use it when rehashing
    Value & find(const Key & hashKey);
    const Value & operator [] (const Key & hashKey) const;
    Value & operator [](const Key & hashKey);

  private:
    HashFunc hash;
    EqualKey equal;
    HashMapUtil hml;
    KeyNode < Key, Value > *table;
    int size;			//current number of itmes
    int capacity;		//capacity of the array
    static const double loadingFactor;
    int findKey(const Key & hashKey);	//find the index of a key
};

template < class Key, class Value, class HashFunc, class EqualKey >
    const double HashMap < Key, Value, HashFunc,
    EqualKey >::loadingFactor = 0.9;

template < class Key, class Value, class HashFunc, class EqualKey >
    HashMap < Key, Value, HashFunc, EqualKey >::HashMap()
{
    hash = HashFunc();
    equal = EqualKey();
    hml = HashMapUtil();
    capacity = hml.find_NextPrimeNumber(0);	//initialize the capacity with first primer 57
    //resize the table with capacity because an extra one is used
    //to return the NULL type of Value in the function find
    table = new KeyNode < Key, Value >[capacity + 1];
    for (int i = 0; i < capacity; i++)	//initialize the table
	table[i].used = 0;
    size = 0;
}

template < class Key, class Value, class HashFunc, class EqualKey >
    HashMap < Key, Value, HashFunc, EqualKey >::~HashMap()
{
    delete[]table;
}

template < class Key, class Value, class HashFunc, class EqualKey >
    bool HashMap < Key, Value, HashFunc,
    EqualKey >::insert(const Key & hashKey, const Value & value)
{
    int index = hash(hashKey) % capacity;
    //cout<<"Index is "<<index<<endl;
    if (table[index].used == 1)	//the key-value's hash is unique
    {
	//cout<<"The key-value must be unique!"<<endl;
	return false;
    }
    table[index].used = 1;	//modify the KeyNode
    table[index].key = hashKey;
    table[index].value = value;

    size++;
    //if the table's size is too large ,then rehash it
    if (size >= capacity * loadingFactor)
	rehash();
    return true;
}

template < class Key, class Value, class HashFunc, class EqualKey >
    void HashMap < Key, Value, HashFunc, EqualKey >::rehash()
{
    int pastsize = capacity;
    //create a new array to copy the information in the old table
    capacity = hml.find_NextPrimeNumber(capacity);
    KeyNode < Key, Value > *tmp = new KeyNode < Key, Value >[capacity];
    for (int i = 0; i < pastsize; i++)
    {
	if (table[i].used == 1)	//copy the KeyNode into the tmp array
	{
	    tmp[i] = table[i];
	}
    }
    delete[]table;		//release the memory of the old table

    table = new KeyNode < Key, Value >[capacity + 1];	//resize the table
    for (int i = 0; i < capacity; i++)	//initialize the table
    {
	table[i].used = 0;
    }
    for (int i = 0; i < pastsize; i++)	//insert the item into the table one by one
    {
	if (tmp[i].used == 1)
	    insert(tmp[i].key, tmp[i].value);
    }
    delete[]tmp;		//delete the tmp array
}

template < class Key, class Value, class HashFunc, class EqualKey >
    bool HashMap < Key, Value, HashFunc,
    EqualKey >::remove(const Key & hashKey)
{
    int index = findKey(hashKey);	//find the index of the key
    if (index < 0)		//if find modify the flag with 0,else print out "no such key!"
    {
	cout << "No such Key!" << endl;
	return false;
    } else
    {
	table[index].used = 0;
	size--;
	return true;
    }
}

template < class Key, class Value, class HashFunc, class EqualKey >
    Value & HashMap < Key, Value, HashFunc,
    EqualKey >::find(const Key & hashKey)
{
    int index = findKey(hashKey);
    if (index < 0)		//if index <0 ,not found,else return the index
    {
	cout << "can not find the key!" << endl;
	return table[capacity].value;	//return NULL
    } else
    {
	return table[index].value;
    }
}

template < class Key, class Value, class HashFunc, class EqualKey >
    const Value & HashMap < Key, Value, HashFunc,
    EqualKey >::operator[] (const Key & hashKey)
const {
    return find(hashKey);	//overload the operation to return the value of the element
}
template < class Key, class Value, class HashFunc, class EqualKey >
    Value & HashMap < Key, Value, HashFunc,
    EqualKey >::operator[] (const Key & hashKey)
{
    return find(hashKey);	//overload the operation to return the value of the element
}

template < class Key, class Value, class HashFunc, class EqualKey >
    int HashMap < Key, Value, HashFunc,
    EqualKey >::findKey(const Key & hashKey)
{
    int index = hash(hashKey) % capacity;
    if ((table[index].used != 1) || !equal(table[index].key, hashKey))
	return -1;
    else
	return index;
}

#endif				/* HASHMAP_H_ */

/*
 * =====================================================================================
 *
 *       Filename:  HahMap.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2014年01月17日 16时57分03秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  lishuming (think different and do it with plearsure.), lism2013@hotmail.com
 *   Organization:  RADI A401
 *
 * =====================================================================================
 */

#include "HashMap.h"
#include <string>
#include <iostream>
using namespace std;

//Hash function you provided must be correspond to the type of the Key
class HashFunc {
  public:
    int operator() (const string & key) {
	int hash = 0;
	for (int i = 0; i < key.length(); ++i)
	{
	    hash = hash << 7 ^ key[i];
	} return (hash & 0x7FFFFFFF);
    }
};

//Equal function you provided to check whether two Keys are equal
//must be correspond to the type of the Key
class EqualKey {
  public:
    bool operator() (const string & A, const string & B) {
	if (A.compare(B) == 0)
	    return true;	//if equal return true
	else
	    return false;	//else false
}};

int main()
{
    HashMap < string, string, HashFunc, EqualKey > hm;

    hm.insert("hello", "you");
    hm.insert("why", "dream");
    hm.insert("java", "good");
    hm.insert("welcome", "haha");

    hm.insert("welcome", "hehe");	//error, key-value must be unique


    cout << "after insert:" << endl;
    cout << hm.find("welcome") << endl;
    cout << hm.find("java") << endl;
    cout << hm["why"] << endl;
    cout << hm["hello"] << endl;

    if (hm.remove("hello"))
	cout << "remove is ok" << endl;	//remove is ok
    cout << hm.find("hello") << endl;	//not exist print NULL

    hm["why"] = "love";		//modify the value 
    cout << hm["why"] << endl;

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值