最近一直在使用hash_map,找时间来梳理一下html
几句话道出map和hash_map的区别ios
1. STL map is an associative array where keys are stored in sorted order using balanced trees. While hash_map is a hashed associated container, where keys are not stored in an ordered way. Key, value pair is stored using a hashed function.
2. Insertion and lookup takes Ologn time in map, Also performance would degrade as the key size increases. Mainly balance operations on large key ranges would kill performance. while lookup is very efficient O(1) in hash_map.
3. Map is useful where you want to store keys in sorted order, hash_map is used where keys order is not important and lookup is very efficient.
4. One more difference is map has the important property that inserting a new element into a map does not invalidate iterators that point to existing elements. Erasing an element from a map also does not invalidate any iterators.
Performance would mostly be o(lgn) due to the implementation of a balanced tree.
For Map custom objects you would need at the minimum the following operators to store data in a map "<" ">" "==" and of course the other stuff for deep copy.c++
原文地址:http://stlchina.huhoo.net/twiki/bin/view.pl/Main/STLDetailHashMap编程
条条大路通罗马,为何你不随便选一条?数组
岳不群-华山派掌门人,人称君子剑 张三丰-武当掌门人,太极拳创始人 东方不败-第一高手,葵花宝典 ...
这些信息若是保存下来并不复杂,可是找起来比较麻烦。例如我要找"张三丰"的信息,最傻的方法就是取得全部的记录,而后按照名字一个一个比较。 若是要速度快,就须要把这些记录按照字母顺序排列,而后按照二分法查找。可是增长记录的时候同时须要保持记录有序,所以须要插入排序。考虑到效率,这就需 要用到二叉树。讲下去会没完没了,若是你使用STL 的map容器,你能够很是方便的实现这个功能,而不用关心其细节。关于map的数据结构细节,感兴趣的朋友能够参看学习STL map, STL set之数据结构基础。 看看map的实现: bash
#include <map> #include <string> using namespace std; ... map<string, string> namemap; //增长。。。 namemap["岳不群"]="华山派掌门人,人称君子剑"; namemap["张三丰"]="武当掌门人,太极拳创始人"; namemap["东方不败"]="第一高手,葵花宝典"; ... //查找。。 if(namemap.find("岳不群") != namemap.end()){ ... }
不以为用起来很easy吗?并且效率很高,100万条记录,最多也只要20次的string.compare的比较,就能找到你要找的记录;200万条记 录事,也只要用21次的比较。 数据结构
速度永远都知足不了现实的需求。若是有100万条记录,我须要频繁进行搜索时,20次比较也会成为瓶颈,要是能降到一次或者两次比较是否有可能?并且当记 录数到200万的时候也是一次或者两次的比较,是否有可能?并且还须要和map同样的方便使用。 less
答案是确定的。这时你须要has_map. 虽然hash_map目前并无归入C++ 标准模板库中,但几乎每一个版本的STL都提供了相应的实现。并且应用十分普遍。在正式使用hash_map以前,先看看hash_map的原理。 函数
hash_map基于hash table(哈希表)。哈希表最大的优势,就是把数据的存储和查找消耗的时间大大下降,几乎能够当作是常数时间;而代价仅仅是消耗比较多的内存。然而在当 前可利用内存愈来愈多的状况下,用空间换时间的作法是值得的。另外,编码比较容易也是它的特色之一。 post
其基本原理是:使用一个下标范围比较大的数组来存储元素。能够设计一个函数(哈希函数,也叫作散列函数),使得每一个元素的关键字都与一个函数值 (即数组下标,hash值)相对应,因而用这个数组单元来存储这个元素;也能够简单的理解为,按照关键字为每个元素“分类”,而后将这个元素存储在相应 “类”所对应的地方,称为桶。
可是,不可以保证每一个元素的关键字与函数值是一一对应的,所以极有可能出现对于不一样的元素,却计算出了相同的函数值,这样就产生了“冲突”,换句话说,就 是把不一样的元素分在了相同的“类”之中。 总的来讲,“直接定址”与“解决冲突”是哈希表的两大特色。
hash_map,首先分配一大片内存,造成许多桶。是利用hash函数,对key进行映射到不一样区域(桶)进行保存。其插入过程是:
因而可知,要实现哈希表, 和用户相关的是:hash函数和比较函数。这两个参数恰好是咱们在使用hash_map时须要指定的参数。
#include <hash_map> #include <string> using namespace std; int main(){ hash_map<int, string> mymap; mymap[9527]="唐伯虎点秋香"; mymap[1000000]="百万富翁的生活"; mymap[10000]="白领的工资底线"; ... if(mymap.find(10000) != mymap.end()){ ... }
够简单,和map使用方法同样。这时你或许会问?hash函数和比较函数呢?不是要指定么?你说对了,可是在你没有指定hash函数和比较函数的时候,你 会有一个缺省的函数,看看hash_map的声明,你会更加明白。下面是SGI STL的声明:
template <class _Key, class _Tp, class _HashFcn = hash<_Key>, class _EqualKey = equal_to<_Key>, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) > class hash_map { ... }
也就是说,在上例中,有如下等同关系:
... hash_map<int, string> mymap; //等同于: hash_map<int, string, hash<int>, equal_to<int> > mymap;
Alloc咱们就不要取关注太多了(但愿深刻了解Allocator的朋友能够参看标准库 STL :Allocator能作什么)
2.2 hash_map 的hash函数 hash< int>究竟是什么样子?看看源码:struct hash<int> { size_t operator()(int __x) const { return __x; } };
原来是个函数对象。在SGI STL中,提供了如下hash函数:
struct hash<char*> struct hash<const char*> struct hash<char> struct hash<unsigned char> struct hash<signed char> struct hash<short> struct hash<unsigned short> struct hash<int> struct hash<unsigned int> struct hash<long> struct hash<unsigned long>
也就是说,若是你的key使用的是以上类型中的一种,你均可以使用缺省的hash函数。固然你本身也能够定义本身的hash函数。对于自定义变量,你只能 如此,例如对于string,就必须自定义hash函数。例如:
struct str_hash{ size_t operator()(const string& str) const { unsigned long __h = 0; for (size_t i = 0 ; i < str.size() ; i ++) __h = 5*__h + str[i]; return size_t(__h); } }; //若是你但愿利用系统定义的字符串hash函数,你能够这样写: struct str_hash{ size_t operator()(const string& str) const { return __stl_hash_string(str.c_str()); } };
在声明本身的哈希函数时要注意如下几点:
如今能够对开头的"岳不群"进行哈希化了 . 直接替换成下面的声明便可:
map<string, string> namemap; //改成: hash_map<string, string, str_hash> namemap;
其余用法都不用边。固然不要忘了吧str_hash的声明以及头文件改成hash_map。
你或许会问:比较函数呢?别着急,这里就开始介绍hash_map中的比较函数。
2.3 hash_map 的比较函数 在map中的比较函数,须要提供less函数。若是没有提供,缺省的也是less< Key> 。在hash_map中,要比较桶内的数据和key是否相等,所以须要的是是否等于的函数:equal_to< Key> 。先看看equal_to的源码://本代码能够从SGI STL //先看看binary_function 函数声明,其实只是定义一些类型而已。 template <class _Arg1, class _Arg2, class _Result> struct binary_function { typedef _Arg1 first_argument_type; typedef _Arg2 second_argument_type; typedef _Result result_type; }; //看看equal_to的定义: template <class _Tp> struct equal_to : public binary_function<_Tp,_Tp,bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return __x == __y; } };
若是你使用一个自定义的数据类型,如struct mystruct, 或者const char* 的字符串,如何使用比较函数?使用比较函数,有两种方法. 第一种是:重载==操做符,利用equal_to;看看下面的例子:
struct mystruct{ int iID; int len; bool operator==(const mystruct & my) const{ return (iID==my.iID) && (len==my.len) ; } };
这样,就可使用equal_to< mystruct>做为比较函数了。另外一种方法就是使用函数对象。自定义一个比较函数体:
struct compare_str{ bool operator()(const char* p1, const char*p2) const{ return strcmp(p1,p2)==0; } };
有了compare_str,就可使用hash_map了。
2.4 hash_map 函数 hash_map的函数和map的函数差很少。具体函数的参数和解释,请参看: STL 编程手册:Hash_map,这里主要介绍几个经常使用函数。typedef hash_map<const char*, string, hash<const char*>, compare_str> StrIntMap; StrIntMap namemap; namemap["岳不群"]="华山派掌门人,人称君子剑"; namemap["张三丰"]="武当掌门人,太极拳创始人"; namemap["东方不败"]="第一高手,葵花宝典";
如今知道如何选择了吗?权衡三个因素: 查找速度, 数据量, 内存使用。
这里还有个关于hash_map和map的小故事,看看:http://dev.csdn.net/Develop/article/14/14019.shtm
4.3 如何在hash_map中加入本身定义的类型? 你只要作两件事, 定义hash函数,定义等于比较函数。下面的代码是一个例子:4.4如何用hash_map替换程序中已有的map容器? 这个很容易,但须要你有良好的编程风格。建议你尽可能使用typedef来定义你的类型:-bash-2.05b$ cat my.cpp #include <hash_map> #include <string> #include <iostream> using namespace std; //define the class class ClassA{ public: ClassA(int a):c_a(a){} int getvalue()const { return c_a;} void setvalue(int a){c_a;} private: int c_a; }; //1 define the hash function struct hash_A{ size_t operator()(const class ClassA & A)const{ // return hash<int>(classA.getvalue()); return A.getvalue(); } }; //2 define the equal function struct equal_A{ bool operator()(const class ClassA & a1, const class ClassA & a2)const{ return a1.getvalue() == a2.getvalue(); } }; int main() { hash_map<ClassA, string, hash_A, equal_A> hmap; ClassA a1(12); hmap[a1]="I am 12"; ClassA a2(198877); hmap[a2]="I am 198877"; cout<<hmap[a1]<<endl; cout<<hmap[a2]<<endl; return 0; } -bash-2.05b$ make my c++ -O -pipe -march=pentiumpro my.cpp -o my -bash-2.05b$ ./my I am 12 I am 198877
typedef map<Key, Value> KeyMap;
当你但愿使用hash_map来替换的时候,只须要修改:
typedef hash_map<Key, Value> KeyMap;
其余的基本不变。固然,你须要注意是否有Key类型的hash函数和比较函数。
4.5为何hash_map不是标准的? 具体为何不是标准的,我也不清楚,有个解释说在STL加入标准C++之时,hash_map系列当时尚未彻底实现,之后应该会成为标准。若是谁知道更 合理的解释,也但愿告诉我。但我想表达的是,正是由于hash_map不是标准的,因此许多平台上安装了g++编译器,不必定有hash_map的实现。 我就遇到了这样的例子。所以在使用这些非标准库的时候,必定要事先测试。另外,若是考虑到平台移植,仍是少用为佳。下面先保存一个例子,之后备用
// UserRefer.h: interface for the UserRefer class.
//
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/// @file userfefer.h
///
/// @brief
/// 用户基准数据管理类,根据基准数据对位置数据进行校订
///
/// @author bruce
/// @date 26/04/2011
///
/// @version 1.0
///
/// @details
/// 用户基准数据管理类
//////////////////////////////////////////////////////////////////////////
#if !defined(AFX_USERREFER_H__C8175704_44CD_4D5C_94E3_7DD3D4A0BB9D__INCLUDED_)
#define AFX_USERREFER_H__C8175704_44CD_4D5C_94E3_7DD3D4A0BB9D__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <winbase.h>
#include <hash_map>
#include <list>
#include <algorithm>
#include <string>
#include <iostream>
#include "Protocol.h"
using namespace std;
///hashmap 比较函数
struct equal_string_
{
bool operator()(const string & a1, const string & a2) const
{
return a1==a2 ;
}
};
///hashmap hash函数
struct hash_string_
{
size_t operator()(const string & A)const
{
return __stl_hash_string(A.c_str());
}
};
///hash表,包含mcuid和基准信息
typedef hash_map<string,UserReferStruct* ,hash_string_, equal_string_> hmapUser;//用户基准信息表
typedef hmapUser::iterator itrdUser;
//用户基准信息类,用户经过mcuid作为检索的条件,对用户基准信息进行增长,查询,修改。
class UserRefer
{
private:
CRITICAL_SECTION m_Section;
hmapUser UserReferList;
UserRefer(const UserRefer&);
void operator =(const UserRefer&);
public:
UserRefer();
virtual ~UserRefer();
private:
///添加基准信息
void AddRefer(string strMcuid,UserReferStruct*);
///删除基准信息
void DeleteRefer(string strMcuid);
///清理用户基准信息
void DeleteAllRefer();
///修改基准信息
void UpdateDataRefer(string strMcuid,UserReferStruct* );
///hash表保护
void InterLock();
void LeaveLock();
///获得hash表指针
hmapUser* GetUserReferMap();
///获得hash表长
int GetUserReferSize();
///根据mcuid获取基准信息
UserReferStruct* GetDataRefer(string strMcuid);
//检测经经度范围
int inline CheckGpsLon(const double dbLon)
{
if(dbLon>= 73.66667 && dbLon <= 135.04167)
{
return 0;
}
else
{
return -1;
}
};
//检测经纬度范围
int inline CheckGpsLat(const double dbLat)
{
if(dbLat >= 3.86667 && dbLat <= 53.55)
{
return 0;
}
else
{
return -1;
}
};
//检测数据是否在浙江
int inline CheckZJGps(const double dbLon, const double dbLat)
{
};
double inline rad(double d)
{
const double PI = 3.1415926535898;
return d * PI / 180.0;
};
//计算两点之间的距离
int CalcDistance(double fLati1, double fLong1, double fLati2, double fLong2);
//在全局基准表中增长基准信息
int AddUserRefer(UserReferStruct *pUserTmp, char *pszMcuid, char* pszSim, double dbLon, double dbLat, char* pszTime, int nType);
//更新基准信息
int UpdateRefer(UserReferStruct *pRefer, char* pszSim, double dbLon, double dbLat, char* pszTime, int nType);
//更新基准信息,并返回可用数据
//0 :当前位置信息可用
//-2 当前位置信息不可用
int UpdataCidGpsData(UserReferStruct *pRefer, char* pszSim, double dbLon, double dbLat, char* pszTime, int nType, double *pRtnLon, double *pRtnLat);
//对2D位置数据进行处理, 不修改基准信息
int Updata2DGpsData(UserReferStruct *pRefer, char* pszSim, double dbLon, double dbLat, char* pszTime, int nType, double dbCidLon,
double dbCidLat, double *pRtnLon, double *pRtnLat);
int UserRefer::Updata3DGpsData(UserReferStruct *pRefer, char* pszSim, double dbLon, double dbLat, char* pszTime,
int nType, double *pRtnLon, double *pRtnLat);
public:
//位置检验
int AuthGpsData(char* pszMcuid, //mcuid
char* pszSim, //电话号码
double dbLon, //gps经度
double dbLat, //gps纬度
char* pszTime, //gps时间
int nType, //gps定位类型
double dbCidLon, //基站转换的经度
double dbCidLat, //基站转换的纬度
double *pRtnLon, //校验后的经度
double *pRtnLat); //校验后的纬度
};
#endif // !defined(AFX_USERREFER_H__C8175704_44CD_4D5C_94E3_7DD3D4A0BB9D__INCLUDED_)
// UserRefer.cpp: implementation of the UserRefer class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "UserRefer.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// #define CK_MIN(a,b) ((a)<(b)?(a):(b)) #define CK_MAX(a,b) ((a)>(b)?(a):(b)) #define CK_DIS (2) #define CK_3DIS (3) #define CK_ZERO (0.000001) #define CK_SUCCESS (0) typedef enum { GPS_HIS = 0, GPS_CID, GPS_2D, GPS_3D, }GPS_TYPE; UserRefer::UserRefer() { InitializeCriticalSection(&m_Section); } UserRefer::~UserRefer() { DeleteAllRefer(); DeleteCriticalSection(&m_Section); } //清理结点 void UserRefer::DeleteAllRefer() { itrdUser iter, itertemp; EnterCriticalSection(&m_Section); for( iter = UserReferList.begin();iter!=UserReferList.end();) { itertemp = iter++; //先保存下一个节点 UserReferStruct *pUser = (UserReferStruct*)(itertemp->second); if(pUser != NULL) { free(pUser) ; pUser = NULL; } UserReferList.erase(itertemp); } UserReferList.clear(); LeaveCriticalSection(&m_Section); } ///在hash表中根据mcuid增长基准信息 void UserRefer::AddRefer(string strMcuid,UserReferStruct *data) { EnterCriticalSection(&m_Section); UserReferList[strMcuid]=data; LeaveCriticalSection(&m_Section); } //在hash表中根据mcuid删除基准信息 void UserRefer::DeleteRefer(string strMcuid) { EnterCriticalSection(&m_Section); UserReferList.erase(strMcuid); LeaveCriticalSection(&m_Section); } //根据mcuid获取基准信息 UserReferStruct* UserRefer::GetDataRefer(string strMcuid) { UserReferStruct* temp = NULL; EnterCriticalSection(&m_Section); temp =UserReferList[strMcuid]; LeaveCriticalSection(&m_Section); return temp; } //根据mcuid重设基准信息 void UserRefer::UpdateDataRefer(string strMcuid, UserReferStruct* pUserRefer) { EnterCriticalSection(&m_Section); UserReferList[strMcuid] = pUserRefer; LeaveCriticalSection(&m_Section); } void UserRefer::InterLock() { EnterCriticalSection(&m_Section); } void UserRefer::LeaveLock() { LeaveCriticalSection(&m_Section); } //获取整个hash表 hmapUser* UserRefer::GetUserReferMap() { return &UserReferList; } //获取hash表的大小 int UserRefer::GetUserReferSize() { int len; EnterCriticalSection(&m_Section); len= UserReferList.size(); LeaveCriticalSection(&m_Section); return len; } //计算两点之间的距离,返回单位(KM) int UserRefer::CalcDistance(double fLati1, double fLong1, double fLati2, double fLong2) { const double EARTH_RADIUS = 6378.137; long lDis = 0; double radLat1 = rad(fLati1); double radLat2 = rad(fLati2); double a = radLat1 - radLat2; double b = rad(fLong1) - rad(fLong2); double s = 2 * asin(sqrt(pow(sin(a/2),2) + cos(radLat1)*cos(radLat2)*pow(sin(b/2),2))); s = s * EARTH_RADIUS; s = (int)(s*10000) / 10000; return (int)s; } ////////////////////////////////////////////////////////////// //在全局基准表中增长基准信息 int UserRefer::AddUserRefer(UserReferStruct *pUserTmp, char *pszMcuid, char* pszSim, double dbLon, double dbLat, char* pszTime, int nType) { if(NULL == pszMcuid || NULL == pszSim || NULL == pszTime) { return -1; } //新建一个结点 pUserTmp = (UserReferStruct*)malloc(sizeof(UserReferStruct)); memset(pUserTmp, 0, sizeof(UserReferStruct)); pUserTmp->dbLat = dbLat; pUserTmp->dbLon = dbLon; pUserTmp->nType = nType; ///时间 memset(pUserTmp->szTime, 0, sizeof(pUserTmp->szTime)); memcpy(&pUserTmp->szTime[0], pszTime, CK_MIN(strlen(pszTime), sizeof(pUserTmp->szTime))); ///mcuid memset(pUserTmp->szMcuid, 0, sizeof(pUserTmp->szMcuid)); memcpy(&pUserTmp->szMcuid[0], pszMcuid, CK_MIN(strlen(pszMcuid), sizeof(pUserTmp->szMcuid))); ///电话号码 memset(pUserTmp->szTel, 0, sizeof(pUserTmp->szTel)); memcpy(&pUserTmp->szTel[0], pszSim, CK_MIN(strlen(pszSim), sizeof(pUserTmp->szTel))); ///增长基准信息 std::string strMcuid(pszMcuid); AddRefer(strMcuid, pUserTmp); return 0; } //更新基准信息 int UserRefer::UpdateRefer(UserReferStruct *pRefer, char* pszSim, double dbLon, double dbLat, char* pszTime, int nType) { if(NULL == pRefer || NULL == pszTime || NULL == pszSim) { return -1; } pRefer->dbLat = dbLat; pRefer->dbLon = dbLon; pRefer->nType = nType; //更新时间 memset(pRefer->szTime, 0, sizeof(pRefer->szMcuid)); memcpy(&pRefer->szTime[0], pszTime, CK_MIN(strlen(pszTime), sizeof(pRefer->szTime))); //更新电话号码 memset(pRefer->szTel, 0, sizeof(pRefer->szTel)); memcpy(&pRefer->szTel[0], pszSim, CK_MIN(strlen(pszSim), sizeof(pRefer->szTel))); return 0; } //当前终端的数据为3D数据 //更新基准信息,并返回可用数据 int UserRefer::Updata3DGpsData(UserReferStruct *pRefer, char* pszSim, double dbLon, double dbLat, char* pszTime, int nType, double *pRtnLon, double *pRtnLat) { if(NULL == pRefer || NULL == pszTime || NULL == pszSim || NULL == pRtnLon || NULL == pRtnLat) { return -1; } else { if(CK_SUCCESS == CheckGpsLon(dbLon) && CK_SUCCESS == CheckGpsLat(dbLat))// 有效的基站数据 { //更新基准信息 UpdateRefer(pRefer, pszSim, dbLon, dbLat, pszTime, nType); //采用基站数据 *pRtnLon = dbLon; *pRtnLat = dbLat; return 0; } else { ///采用基准信息 *pRtnLon = pRefer->dbLon; *pRtnLat = pRefer->dbLat; return -2; }//基站数据不合法 } } //当前终端的数据为基站数据 //更新基准信息,并返回可用数据 //0 :当前位置信息可用 //-2 当前位置信息不可用 int UserRefer::UpdataCidGpsData(UserReferStruct *pRefer, char* pszSim, double dbLon, double dbLat, char* pszTime, int nType, double *pRtnLon, double *pRtnLat) { if(NULL == pRefer || NULL == pszTime || NULL == pszSim || NULL == pRtnLon || NULL == pRtnLat) { return -1; } if(CK_SUCCESS == CheckGpsLon(dbLon) && CK_SUCCESS == CheckGpsLat(dbLat))// 有效的基站数据 { if(GPS_3D == pRefer->nType) //3D基准信息 { //比较误差 if(CalcDistance(pRefer->dbLat, pRefer->dbLon, dbLat, dbLon) > CK_DIS) //位置确实已经修改,须要更新基准信息 { //更新基准信息 UpdateRefer(pRefer, pszSim, dbLon, dbLat, pszTime, nType); //采用基站数据 *pRtnLon = dbLon; *pRtnLat = dbLat; } else//小于,说明基站数据与基准在同一范围,但基准信息能够不修改 { //采用基站数据 *pRtnLon = dbLon; *pRtnLat = dbLat; } } else if(GPS_2D != nType)//基站基准信息 { //更新基准信息 UpdateRefer(pRefer, pszSim, dbLon, dbLat, pszTime, nType); //采用基站数据 *pRtnLon = dbLon; *pRtnLat = dbLat; } return 0; } else { ///采用基准信息 *pRtnLon = pRefer->dbLon; *pRtnLat = pRefer->dbLat; return -2; }//基站数据不合法 } //对2D位置数据进行处理, 也能够改基准信息 int UserRefer::Updata2DGpsData(UserReferStruct *pRefer, char* pszSim, double dbLon, double dbLat, char* pszTime, int nType, double dbCidLon, double dbCidLat, double *pRtnLon, double *pRtnLat) { if(NULL == pRefer || NULL == pszSim || NULL == pszTime || NULL == pRtnLon || NULL == pRtnLat) { return -1; } if(GPS_2D == nType) //2D定位 { if(CK_SUCCESS == CheckGpsLon(dbCidLon) && CK_SUCCESS == CheckGpsLat(dbCidLat) && CalcDistance(dbCidLat, dbCidLon, pRefer->dbLat, pRefer->dbLon) < CK_DIS) //基站转换的数据可用 { if(CalcDistance(dbCidLat, dbCidLon, dbLat, dbLon) > CK_DIS)//自身的基站与经纬度比较,漂移 { if((GPS_3D == pRefer->nType))//说明是3D基准信息,可使用 { //采用3D基准信息 *pRtnLon = pRefer->dbLon; *pRtnLat = pRefer->dbLat; } else//2D或基站基准信息 { //采用基站数据做为当前位置数据,而且更新基准点 UpdateRefer(pRefer, pszSim, dbCidLon, dbCidLat, pszTime, nType); //采用基站数据 *pRtnLon = dbCidLon; *pRtnLat = dbCidLat; } } else//2D数据可用 { //采用GPS数据更新基准点 UpdateRefer(pRefer, pszSim, dbLon, dbLat, pszTime, nType); *pRtnLon = dbLon; *pRtnLat = dbLat; } } else//基站转换后的数据不合法 { ///2D数据与基准信息相差太远 if(CalcDistance(pRefer->dbLat, pRefer->dbLon, dbLat, dbLon) > CK_3DIS)//2D无效,漂移 { //采用基准信息 *pRtnLon = pRefer->dbLon; *pRtnLat = pRefer->dbLat; } else //当前数据近似可用 { //转发2D数据 *pRtnLon = dbLon; *pRtnLat = dbLat; } } return 0; } else //不是2D定位 { ///采用基准信息 *pRtnLon = pRefer->dbLon; *pRtnLat = pRefer->dbLat; return -2; } } //位置检验 int UserRefer::AuthGpsData(char* pszMcuid, char* pszSim, double dbLon, double dbLat, char* pszTime,int nType, double dbCidLon,double dbCidLat, double *pRtnLon, double *pRtnLat) { UserReferStruct *pUserTmp = NULL; if(NULL == pszMcuid || NULL == pszSim || NULL == pszTime || NULL == pRtnLon || NULL == pRtnLat) { return -1; } std::string strMcuid(pszMcuid); pUserTmp = GetDataRefer(strMcuid); if(NULL == pUserTmp) //没有基准信息 { if(GPS_2D != nType) //基站或3D { //新增基准信息 AddUserRefer(pUserTmp, pszMcuid, pszSim, dbLon, dbLat, pszTime, nType); } //采用当前数据 *pRtnLon = dbLon; *pRtnLat = dbLat; return 0; }//没有基准信息 else { if(GPS_3D == nType)//3D数据 { ///更新基准信息 return Updata3DGpsData(pUserTmp, pszSim, dbLon, dbLat, pszTime, nType, pRtnLon, pRtnLat); } else if(GPS_2D != nType) //基站数据 { return UpdataCidGpsData(pUserTmp, pszSim, dbLon, dbLat, pszTime, nType, pRtnLon, pRtnLat); } else if(GPS_2D == nType) //2D数据 { return Updata2DGpsData(pUserTmp, pszSim, dbLon, dbLat, pszTime, nType, dbCidLon, dbCidLat, pRtnLon, pRtnLat); } }//有基准信息 return 0; }