432 lines
8.6 KiB
C++
432 lines
8.6 KiB
C++
#pragma once
|
|
#include <vector>
|
|
#include <functional>
|
|
#include <algorithm>
|
|
|
|
#define DELETE_PTR(ptr)\
|
|
if (ptr)\
|
|
{\
|
|
delete ptr;\
|
|
ptr = NULL;\
|
|
}
|
|
|
|
template <class K>
|
|
class TDPtrList
|
|
{
|
|
typedef std::vector<K*> KVec;
|
|
typedef int(*cmpFunc)(const K *, const K *); // 比较函数
|
|
typedef int(*cmpByVoidPtr)(const K *, const void *); // 比较函数
|
|
|
|
// 由于DList内的QuickSort()函数的排序结果与std::sort()的相反.
|
|
// 故用此functor在 QuickSort()内部,将 cmpFunc的结果取反,以达到与DList结果相同的目的!
|
|
struct TSort
|
|
{
|
|
cmpFunc func;
|
|
TSort (cmpFunc f): func(f){}
|
|
bool operator () (const K *p1, const K * p2)
|
|
{
|
|
bool brel = func(p1, p2) > 0 ? true : false;
|
|
return !brel;
|
|
}
|
|
};
|
|
|
|
protected:
|
|
bool m_nDelFlag; // true - 自动释放
|
|
K *head; // 头元素,为兼容DList
|
|
K *tail; // 尾元素,为兼容DList
|
|
private:
|
|
KVec m_data;
|
|
size_t m_pos; // 当前位置,为兼容DList
|
|
|
|
public:
|
|
TDPtrList(int dFlag = 1);
|
|
|
|
// 用数组初始化链表, 不能用于字符串数组!!
|
|
// 建议 K 有copy constructor
|
|
TDPtrList(K * addr, size_t nCount);
|
|
|
|
~TDPtrList();
|
|
|
|
int operator !() const;
|
|
// 移到当前指针到第 n 个节点, 并返回它所指的值
|
|
K * operator [](int n);
|
|
const K & operator [](int n) const;
|
|
|
|
void MoveToHead();
|
|
|
|
const K & GetAt(int n) const;
|
|
K * GetAt(int n);
|
|
|
|
//并入
|
|
//并入链表,listother被直接连接到this的末尾
|
|
//最后this链表的游标值不变, listother失去对其内数据的维护权.
|
|
TDPtrList<K>& operator << (TDPtrList<K> &listother);
|
|
|
|
//复制
|
|
//建议 K 有copy constructor
|
|
TDPtrList<K>& copyFrom(const TDPtrList<K> &listother);
|
|
|
|
void Insert(K * node);
|
|
void Append(K * node);
|
|
void Replace(K * node, int n = -1);
|
|
void Reset();
|
|
|
|
int Remove();
|
|
int Remove(int n);
|
|
|
|
// 求当前指针的位置(-1: current 为 NULL)
|
|
int CurPosition() const;
|
|
|
|
int Length() const;
|
|
|
|
int GetDelFlag() const;
|
|
void SetDelFlag(int nFlag);
|
|
|
|
K * CurData() const;
|
|
void SetCurData(K* p);
|
|
|
|
// 如cmp为空,则直接比较指针地址.
|
|
// 如cmp不为空,则比较指针所指内容.
|
|
int Find(const K * node);
|
|
int Exist(const K * node) const;
|
|
|
|
// 把指针移到最后,准备下一个插入
|
|
void MoveEnd();
|
|
|
|
K* Head() const;
|
|
K* Tail() const;
|
|
K* FindNode(const void *, cmpByVoidPtr cmp);
|
|
|
|
void QuickSort(cmpFunc cmp);
|
|
void Swap(int n1,int n2);
|
|
void Reverse();
|
|
void FindAndDel(const void *p, cmpByVoidPtr cmp);
|
|
|
|
KVec& GetData();
|
|
const KVec& GetData() const;
|
|
|
|
protected:
|
|
virtual int Compare(const K *, const K *) const;
|
|
|
|
private:
|
|
TDPtrList<K> & operator = (const TDPtrList<K> &src);
|
|
TDPtrList(const TDPtrList<K> &src);
|
|
bool judge_idx(size_t idx) const;
|
|
void set_head_tail();
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::set_head_tail()
|
|
{
|
|
if (m_data.empty())
|
|
head = tail = NULL;
|
|
else
|
|
{
|
|
head = m_data.front();
|
|
tail = m_data.back();
|
|
}
|
|
}
|
|
|
|
template <class K>
|
|
std::vector<K*>& TDPtrList<K>::GetData() { return m_data; }
|
|
|
|
template <class K>
|
|
const std::vector<K*>& TDPtrList<K>::GetData() const { return m_data;}
|
|
template <class K>
|
|
bool TDPtrList<K>::judge_idx( size_t idx ) const
|
|
{
|
|
if (idx >= 0 && idx < m_data.size())
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
template <class K>
|
|
TDPtrList<K>::TDPtrList( int dFlag /*= 1*/ )
|
|
: m_nDelFlag(dFlag != 0 ? true : false), m_data(0),
|
|
head(NULL), tail(NULL), m_pos(0){set_head_tail();}
|
|
|
|
template <class K>
|
|
TDPtrList<K>::TDPtrList( K * addr, size_t nCount)
|
|
: m_nDelFlag(true), m_pos(0), head(NULL), tail(NULL), m_data(0)
|
|
{
|
|
m_data.resize(nCount);
|
|
for (size_t i = 0; i < nCount; ++i, ++m_pos)
|
|
m_data[i] = new K(addr[i]);
|
|
set_head_tail();
|
|
}
|
|
|
|
template <class K>
|
|
TDPtrList<K>::~TDPtrList()
|
|
{
|
|
if (!m_nDelFlag)
|
|
return;
|
|
for (size_t i = 0; i < m_data.size(); ++i)
|
|
{
|
|
K *p = m_data[i];
|
|
DELETE_PTR(p);
|
|
}
|
|
}
|
|
|
|
template <class K>
|
|
const K & TDPtrList<K>::operator[]( int n ) const { return GetAt(n); }
|
|
|
|
template <class K>
|
|
K * TDPtrList<K>::operator[]( int n ) { return GetAt(n); }
|
|
|
|
template <class K>
|
|
K * TDPtrList<K>::GetAt( int n )
|
|
{
|
|
m_pos = n;
|
|
return m_data[n];
|
|
}
|
|
|
|
template <class K>
|
|
const K & TDPtrList<K>::GetAt( int n ) const
|
|
{
|
|
TDPtrList<K> *pThis = (TDPtrList<K> *)this;
|
|
const K *p = pThis->GetAt(n);
|
|
return *p;
|
|
}
|
|
|
|
template <class K>
|
|
TDPtrList<K>& TDPtrList<K>::copyFrom( const TDPtrList<K>& listother )
|
|
{
|
|
if (this == &listother)
|
|
return *this;
|
|
Reset();
|
|
m_nDelFlag = listother.GetDelFlag() != 0 ? true : false;
|
|
m_data.resize(listother.Length());
|
|
for (size_t i = 0; i < (size_t)listother.Length(); ++i,++m_pos)
|
|
m_data[i] = new K (listother[(int)i]);
|
|
|
|
set_head_tail();
|
|
return *this;
|
|
}
|
|
|
|
template <class K>
|
|
TDPtrList<K>& TDPtrList<K>::operator << ( TDPtrList<K> &listother )
|
|
{
|
|
KVec &odata = listother.GetData();
|
|
m_data.insert(m_data.end(), odata.begin(), odata.end());
|
|
listother.head = listother.tail = NULL;
|
|
listother.m_pos = 0;
|
|
listother.GetData().clear();
|
|
set_head_tail();
|
|
return *this;
|
|
}
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::Insert( K * node )
|
|
{
|
|
if (!judge_idx(m_pos))
|
|
{
|
|
Append(node);
|
|
return;
|
|
}
|
|
typename KVec::iterator it = m_data.begin();
|
|
std::advance(it , m_pos);
|
|
m_data.insert(it, node);
|
|
set_head_tail();
|
|
++m_pos;
|
|
}
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::Append( K * node )
|
|
{
|
|
m_data.push_back(node);
|
|
// dlist在进行尾插入后,其当前索引会指到结尾的下一个内存处,而不是最后一个元素.
|
|
// 对此我表示理解无能...
|
|
m_pos = m_data.size();
|
|
set_head_tail();
|
|
}
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::Replace( K * node, int n /*= -1*/ )
|
|
{
|
|
if (!judge_idx((size_t)n))
|
|
return;
|
|
|
|
if (m_nDelFlag)
|
|
DELETE_PTR(m_data[n]);
|
|
|
|
m_data[n] = node;
|
|
m_pos = n;
|
|
set_head_tail();
|
|
}
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::Reset()
|
|
{
|
|
if (m_nDelFlag)
|
|
{
|
|
for (size_t i = 0; i < m_data.size(); ++i)
|
|
DELETE_PTR(m_data[i]);
|
|
}
|
|
m_data.clear();
|
|
head = tail = NULL;
|
|
m_pos = 0;
|
|
}
|
|
|
|
template <class K>
|
|
int TDPtrList<K>::Exist( const K * node) const
|
|
{
|
|
return const_cast<TDPtrList<K>*>(this)->Find(node);
|
|
}
|
|
|
|
template <class K>
|
|
int TDPtrList<K>::Find( const K * node)
|
|
{
|
|
TDPtrList<K> *p = (TDPtrList<K>*) this;
|
|
for ( m_pos = 0; m_pos < m_data.size(); ++m_pos)
|
|
{
|
|
if (!Compare(m_data[m_pos], node))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::SetCurData( K* p ) // dlist 在这里只是简单替换,并没有考虑内存释放问题
|
|
{
|
|
if (!judge_idx(m_pos))
|
|
return;
|
|
if (m_nDelFlag)
|
|
DELETE_PTR(m_data[m_pos]);
|
|
m_data[m_pos] = p;
|
|
set_head_tail();
|
|
}
|
|
|
|
template <class K>
|
|
K * TDPtrList<K>::CurData() const
|
|
{
|
|
if (!judge_idx(m_pos))
|
|
return NULL;
|
|
return m_data[m_pos];
|
|
}
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::SetDelFlag( int nFlag ) { m_nDelFlag = nFlag != 0 ? true : false; }
|
|
|
|
template <class K>
|
|
int TDPtrList<K>::GetDelFlag() const { return m_nDelFlag; }
|
|
|
|
template <class K>
|
|
int TDPtrList<K>::Length() const { return (int)m_data.size(); }
|
|
|
|
template <class K>
|
|
int TDPtrList<K>::CurPosition() const { return m_pos < m_data.size() ? (int)m_pos : -1; }
|
|
|
|
template <class K>
|
|
int TDPtrList<K>::Remove( int n )
|
|
{
|
|
if (!judge_idx((size_t)n))
|
|
return 0;
|
|
|
|
m_pos = n;
|
|
return Remove();
|
|
}
|
|
|
|
template <class K>
|
|
int TDPtrList<K>::Remove()
|
|
{
|
|
if (!judge_idx(m_pos))
|
|
return 0;
|
|
|
|
if (m_nDelFlag)
|
|
DELETE_PTR(m_data[m_pos]);
|
|
|
|
typename KVec::iterator it = m_data.begin();
|
|
std::advance(it, m_pos);
|
|
m_data.erase(it);
|
|
|
|
set_head_tail();
|
|
|
|
return 1;
|
|
}
|
|
|
|
// 注意dlist用的是指针比较,所以...这里也是如此
|
|
template <class K>
|
|
int TDPtrList<K>::Compare( const K *p1, const K *p2 ) const
|
|
{
|
|
if (p1 == p2)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
template <class K>
|
|
TDPtrList<K>::TDPtrList( const TDPtrList<K> &src )
|
|
: m_nDelFlag(true), m_pos(0), head(NULL), tail(NULL), m_data(0){ copyFrom(src); }
|
|
|
|
template <class K>
|
|
TDPtrList<K> & TDPtrList<K>::operator=( const TDPtrList<K> &src ) { return copyFrom(src); }
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::FindAndDel( const void *p, cmpByVoidPtr cmp )
|
|
{
|
|
while (FindNode(p, cmp))
|
|
Remove();
|
|
}
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::Reverse()
|
|
{
|
|
std::reverse(m_data.begin(), m_data.end());
|
|
set_head_tail();
|
|
}
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::Swap( int n1, int n2 )
|
|
{
|
|
if (!judge_idx((size_t)n1) || !judge_idx((size_t)n2))
|
|
return;
|
|
|
|
K *tmp = m_data[n1];
|
|
m_data[n1] = m_data[n2];
|
|
m_data[n2] = tmp;
|
|
m_pos = n2;
|
|
set_head_tail();
|
|
}
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::QuickSort( cmpFunc cmp )
|
|
{
|
|
std::sort(m_data.begin(), m_data.end(), TSort(cmp));
|
|
set_head_tail();
|
|
}
|
|
|
|
template <class K>
|
|
K* TDPtrList<K>::FindNode( const void *p, cmpByVoidPtr cmp )
|
|
{
|
|
for (size_t i = 0; i < m_data.size(); ++i)
|
|
{
|
|
m_pos = i;
|
|
K *result = m_data[i];
|
|
if (!cmp(result, p))
|
|
return result;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template <class K>
|
|
K* TDPtrList<K>::Tail() const {const_cast<TDPtrList<K>*>(this)->set_head_tail(); return tail; }
|
|
|
|
template <class K>
|
|
K* TDPtrList<K>::Head() const {const_cast<TDPtrList<K>*>(this)->set_head_tail(); return head; }
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::MoveEnd() { m_pos = -1; }
|
|
|
|
template <class K>
|
|
void TDPtrList<K>::MoveToHead() { m_pos = 0; }
|
|
|
|
template <class K>
|
|
int TDPtrList<K>::operator!() const
|
|
{
|
|
if (head)
|
|
{
|
|
return 0;
|
|
}
|
|
return 1;
|
|
} |