最近一直在使用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; }