全部博文(31)
分类: 嵌入式
2010-07-04 17:15:40
/*
MIT License
Copyright (c) 2010 X-Hawk cublog: http://file.chinaunix.com
*/
#include
#include
#include
#include
#include
#include
template<class T>
class PosSwap_vector
{
protected:
struct AccessIndex
{
unsigned int m_prev;
unsigned int m_curr;
unsigned int m_next;
T m_member;
AccessIndex(unsigned int prev, unsigned int curr, unsigned int next, T member)
: m_prev(prev)
, m_curr(curr)
, m_next(next)
, m_member(member)
{
}
AccessIndex &operator=(const AccessIndex &right)
{
AccessIndex(right).swap(*this);
return *this;
}
void swap(AccessIndex &right)
{
std::swap(m_prev, right.m_prev);
std::swap(m_curr, right.m_curr);
std::swap(m_next, right.m_next);
std::swap(m_member, right.m_member);
}
inline unsigned int GetAccessFreq(unsigned int globalIndex) const
{
unsigned long freq0 = m_curr - m_prev;
unsigned long freq1 = globalIndex - m_curr;
return (freq0 > freq1 ? freq0 : freq1);
}
};
std::vector<AccessIndex> m_members;
unsigned int m_globalIndex;
class Comp:
public std::binary_function<const AccessIndex &, const AccessIndex &, bool>
{
protected:
unsigned int m_globalIndex;
public:
Comp(unsigned int globalIndex)
: m_globalIndex(globalIndex)
{
}
bool operator()(const AccessIndex &l, const AccessIndex &r) const
{
unsigned int freq0 = l.GetAccessFreq(m_globalIndex);
unsigned int freq1 = r.GetAccessFreq(m_globalIndex);
if(freq0 == freq1)
return l.m_member < r.m_member;
else
return freq0 < freq1;
}
};
public:
void SelectMember(std::vector<T> &members, size_t n) const
{
members.clear();
size_t i = 0;
typename std::vector<AccessIndex>::const_iterator itr = m_members.begin();
while(i < n && itr != m_members.end())
{
members.push_back(itr->m_member);
++i;
++itr;
}
}
void InsertMember(const T &member)
{
AccessIndex insert(0, 0, 0, member);
for(typename std::vector<AccessIndex>::iterator i = m_members.begin();
i != m_members.end();
++i)
{
if(i->m_member == member)
{
insert = *i;
m_members.erase(i);
break;
}
}
++m_globalIndex;
if(m_globalIndex == 0)
{
m_members.clear();
return;
}
insert.m_prev = insert.m_curr;
insert.m_curr = m_globalIndex;
insert.m_next = insert.m_curr * 2 - insert.m_prev;
m_members.push_back(insert);
std::sort(m_members.begin(), m_members.end(), Comp(m_globalIndex));
}
PosSwap_vector()
: m_members()
, m_globalIndex(0)
{
}
virtual ~PosSwap_vector()
{
}
};
template<class T>
class PosSwap
{
protected:
struct AccessIndex
{
unsigned int m_prev;
unsigned int m_curr;
unsigned int m_next;
const T *m_member;
AccessIndex(unsigned int prev, unsigned int curr, unsigned int next, T *member)
: m_prev(prev)
, m_curr(curr)
, m_next(next)
, m_member(member)
{
}
inline unsigned int GetAccessFreq(unsigned int globalIndex) const
{
unsigned long freq0 = m_curr - m_prev;
unsigned long freq1 = globalIndex - m_curr;
return (freq0 > freq1 ? freq0 : freq1);
}
static bool CompNear0(const AccessIndex &l, const AccessIndex &r)
{
unsigned int freq0 = l.m_curr - l.m_prev;
unsigned int freq1 = r.m_curr - r.m_prev;
if(freq0 == freq1)
{
//return l.m_curr < r.m_curr;
return *l.m_member < *r.m_member;
}
else
return freq0 < freq1;
}
static bool CompNear1(const AccessIndex &l, const AccessIndex &r)
{
if(l.m_next == r.m_next)
return l.m_curr < r.m_curr;
else
return l.m_next < r.m_next;
}
static bool CompFar(const AccessIndex &l, const AccessIndex &r)
{
return l.m_curr < r.m_curr;
}
};
typedef bool (*CompFunc)(const AccessIndex &, const AccessIndex &);
typedef std::map<T, AccessIndex> MemberType;
MemberType m_allMembers;
/* For the members with m_next >= current index, put member's iterator in m_nearMembers0,
the 1st argument of map is "m_curr - m_prev" */
std::map<AccessIndex, typename MemberType::iterator, CompFunc> m_nearMembers0;
/* For the members with m_next >= current index, put member's iterator in m_nearMembers1,
the 1st argument of map is "m_next" */
std::map<AccessIndex, typename MemberType::iterator, CompFunc> m_nearMembers1;
/* For the members with m_next < current index, put member's iterator in m_farMembers,
the 1st argument of map is "m_curr" */
std::map<AccessIndex, typename MemberType::iterator, CompFunc> m_farMembers;
unsigned int m_globalIndex;
public:
PosSwap()
: m_allMembers()
, m_nearMembers0(&AccessIndex::CompNear0)
, m_nearMembers1(&AccessIndex::CompNear1)
, m_farMembers(&AccessIndex::CompFar)
, m_globalIndex(0)
{
}
void SelectMember(std::vector<T> &members, size_t n) const
{
members.clear();
typename std::map<AccessIndex, typename MemberType::iterator, CompFunc>::const_reverse_iterator ifar
= m_farMembers.rbegin();
typename std::map<AccessIndex, typename MemberType::iterator, CompFunc>::const_iterator inear
= m_nearMembers0.begin();
size_t i = 0;
for(; i < n; ++i)
{
if(ifar != m_farMembers.rend() && inear != m_nearMembers0.end())
{
unsigned int freqFar = m_globalIndex - ifar->first.m_curr;
unsigned int freqNear = inear->first.m_curr - inear->first.m_prev;
if(freqFar < freqNear)
{
members.push_back(ifar->second->first);
++ifar;
}
else if(freqFar > freqNear)
{
members.push_back(inear->second->first);
++inear;
}
else if(ifar->second->first < inear->second->first)
{
members.push_back(ifar->second->first);
++ifar;
}
else
{
members.push_back(inear->second->first);
++inear;
}
}
else if(ifar != m_farMembers.rend())
{
members.push_back(ifar->second->first);
++ifar;
}
else if(inear != m_nearMembers0.end())
{
members.push_back(inear->second->first);
++inear;
}
else
break;
}
}
unsigned int GetMemberFrequency(const T &member) const
{
typename MemberType::const_iterator itr = m_allMembers.find(member);
if(itr != m_allMembers.end())
{
return itr->second.GetAccessFreq(m_globalIndex);
}
else
return 0;
}
void InsertMember(const T &member)
{
AccessIndex index(0, 0, 0, NULL);
/* Check if member exists */
typename MemberType::iterator itr = m_allMembers.find(member);
if(itr != m_allMembers.end())
{
index = itr->second;
if(m_globalIndex <= itr->second.m_next)
{
m_nearMembers0.erase(itr->second);
m_nearMembers1.erase(itr->second);
}
else
m_farMembers.erase(itr->second);
m_allMembers.erase(itr);
}
/* Move from m_nearMembers0 & m_nearMembers1 to m_farMembers. */
AccessIndex end(0, 0, m_globalIndex, NULL);
typename std::map<AccessIndex, typename MemberType::iterator, CompFunc>::iterator pos
(m_nearMembers1.lower_bound(end));
while(pos != m_nearMembers1.end())
{
typename std::map<AccessIndex, typename MemberType::iterator, CompFunc>::iterator move = pos;
++pos;
if(move->first.m_next == m_globalIndex)
{
m_farMembers.insert(*move);
m_nearMembers0.erase(move->first);
m_nearMembers1.erase(move);
}
else
break;
}
/* Increase m_globalIndex */
++m_globalIndex;
if(m_globalIndex == 0)
{
/* Overflow, clear all records, start new statistics */
m_allMembers.clear();
m_nearMembers0.clear();
m_nearMembers1.clear();
m_farMembers.clear();
return;
}
/* Insert the member */
index.m_prev = index.m_curr;
index.m_curr = m_globalIndex;
index.m_next = index.m_curr * 2 - index.m_prev;
itr = m_allMembers.insert(std::make_pair(member, index)).first;
itr->second.m_member = &itr->first;
/* m_globalIndex - index.m_next
= index.m_curr - (index.m_curr * 2 - index.m_prev)
= index.m_prev - index.m_curr <= 0 */
m_nearMembers0.insert(std::make_pair(itr->second, itr));
m_nearMembers1.insert(std::make_pair(itr->second, itr));
}
virtual ~PosSwap()
{
}
};
template<class SWAP>
void test_time(SWAP &ps0)
{
#define MAX_NUM 150
#define SELECT_NUM 4
#define LOOP_TIME 3000
time_t start = time(0);
srand(time(0));
for(int j = 0; j < LOOP_TIME; ++j)
{
for(int i = 0; i < MAX_NUM; ++i)
{
/* Insert a random value */
int r = rand() % MAX_NUM;
ps0.InsertMember(r);
/* Select the most recent value */
std::vector<unsigned int> members0;
ps0.SelectMember(members0, SELECT_NUM);
}
}
printf("time = %d\n", (int)(time(0) - start));
}
int main()
{
PosSwap<unsigned int> ps0;
test_time(ps0);
PosSwap_vector<unsigned int> ps1;
test_time(ps1);
return 0;
}