这几天学习了模板链表类的封装,今天记录下学习过程
模板链表类的声明和实现都要写在一个头文件中
QList.h
//模板链表类
template <class T>
class QList
{
public:
QList() {
m_bNewList = FALSE;
m_pHead = nullptr;
m_pEnd = nullptr;
m_nCount = 0;
m_bModify = FALSE;
}
~QList() {
if (m_bNewList)
ClearNode();
else
ClearAll();
}
private:
//节点类
class Node
{
public:
Node(Node* pPave, Node* pNext, T* pData)
:m_pPave(pPave), m_pNext(pNext), m_pData(pData) {}
private:
Node* m_pPave; //前一节点
Node* m_pNext; //下一节点
T* m_pData; //数据域
friend class QList;
};
void ClearNode()
{
Node* pTem = nullptr;
while (m_pHead)
{
pTem = m_pHead;
m_pHead = m_pHead->m_pNext;
delete pTem;
}
m_pHead = nullptr;
m_pEnd = nullptr;
m_nCount = 0;
}
public:
//清除链表所有的节点内存和数据域内存
void ClearAll()
{
Node* pTem = nullptr;
while (m_pHead)
{
pTem = m_pHead;
m_pHead = m_pHead->m_pNext;
delete pTem->m_pData;
pTem->m_pData = nullptr;
delete pTem;
pTem = nullptr;
}
m_pHead = nullptr;
m_pEnd = nullptr;
m_nCount = 0;
}
int Add(T* pData) //添加数据域指针到链表
{
Node* pNewNode = new Node(nullptr, nullptr, pData);
if (m_pHead == nullptr)
{
m_pHead = pNewNode;
m_pEnd = pNewNode;
}
else
{
pNewNode->m_pPave = m_pEnd;
m_pEnd->m_pNext = pNewNode;
m_pEnd = pNewNode;
}
m_nCount++;
m_bModify = TRUE;
return m_nCount;
}
T* GetAt(int nIndex)const
{
if (nIndex >= m_nCount || nIndex < 0)
return nullptr;
Node* pCur = m_pHead;
for (int i = 0; i < nIndex; i++)
pCur = pCur->m_pNext;
return pCur->m_pData;
}
int GetCount()const
{
return m_nCount;
}
//清除修改标记
void ClearModify() { m_bModify = FALSE; }
BOOL GetModify()const { return m_bModify; }
//判断空链表
BOOL IsNull()
{
return m_nCount == 0;
}
void operator+=(T* pData)
{
/*Node* pNewNode = new Node(nullptr,nullptr,pData);
pNewNode->m_pNext = m_pHead;
pNewNode->m_pPave = nullptr;
m_pHead->m_pPave = pNewNode;
m_pHead = pNewNode;*/
Add(pData);
}
public:
//查找单个符合条件的数据
template<class FIND_FUNC>
T* FindSing_if(FIND_FUNC findFunc)
{
Node* pCur = m_pHead;
while (pCur)
{
if (findFunc(pCur->m_pData))
return pCur->m_pData;
pCur = pCur->m_pNext;
}
return nullptr;
}
//返回链表中所有符合指定条件的数据组成的链表指针
//返回的链表指针用后要Delete掉
template<class FIND_FUNC>
QList<T>* FindAll_if(FIND_FUNC findFunc)
{
QList<T>* pTemList = new QList<T>;
pTemList->m_bNewList = TRUE;
Node* pCur = m_pHead;
while (pCur)
{
if (findFunc(pCur->m_pData))
pTemList->Add(pCur->m_pData);
pCur = pCur->m_pNext;
}
return pTemList;
}
//删除单个符合条件的数据
template<class DEL_FUNC>
BOOL DelSing_if(DEL_FUNC delFunc)
{
Node* pCur = m_pHead;
while (pCur)
{
if (delFunc(pCur->m_pData))
{
if (pCur == m_pHead)
{
//删除头节点
m_pHead = m_pHead->m_pNext;
m_pHead->m_pPave = nullptr;
//删除数据域内存和节点内存,当前节点指向新的头节点
delete pCur->m_pData;
pCur->m_pData = nullptr;
delete pCur;
pCur = m_pHead;
}
else if (pCur == m_pEnd)
{
//删除尾节点
m_pEnd = pCur->m_pPave;
m_pEnd->m_pNext = nullptr;
delete pCur->m_pData;
pCur->m_pData = nullptr;
delete pCur;
pCur = nullptr;
}
else
{
//中间节点的删除
Node* pNext = pCur->m_pNext;
pCur->m_pPave->m_pNext = pCur->m_pNext;
delete pCur->m_pData;
pCur->m_pData = nullptr;
delete pCur;
pCur = pNext;
}
m_nCount--;
m_bModify = TRUE;
return 1;
}
else
pCur = pCur->m_pNext;
}
return 0;
}
//删除所有符合条件的数据,返回删除的个数
template<class DEL_FUNC>
int DelAll_if(DEL_FUNC delFunc)
{
int nRet = 0;
Node* pCur = m_pHead;
while (pCur)
{
if (delFunc(pCur->m_pData))
{
if (pCur == m_pHead)
{
//删除头节点
m_pHead = m_pHead->m_pNext;
m_pHead->m_pPave = nullptr;
//删除数据域内存和节点内存,当前节点指向新的头节点
delete pCur->m_pData;
pCur->m_pData = nullptr;
delete pCur;
pCur = m_pHead;
}
else if (pCur == m_pEnd)
{
//删除尾节点
m_pEnd = pCur->m_pPave;
m_pEnd->m_pNext = nullptr;
delete pCur->m_pData;
pCur->m_pData = nullptr;
delete pCur;
pCur = nullptr;
}
else
{
//中间节点的删除
Node* pNext = pCur->m_pNext;
pCur->m_pPave->m_pNext = pCur->m_pNext;
delete pCur->m_pData;
pCur->m_pData = nullptr;
delete pCur;
pCur = pNext;
}
m_nCount--;
nRet++;
}
else
pCur = pCur->m_pNext;
}
if (nRet > 0)
m_bModify = TRUE;
return nRet;
}
//修改数据
template<class FIND_FUNC>
void ModifyData(T* pNewData, FIND_FUNC findFunc)
{
Node* pCur = m_pHead;
while (pCur)
{
if (findFunc(pCur->m_pData))
{
delete pCur->m_pData;
pCur->m_pData = pNewData;
m_bModify = TRUE;
break;
}
pCur = pCur->m_pNext;
}
}
//循环链表
template<class FOREACH_FUNC>
void ForEach(FOREACH_FUNC forFunc)
{
Node* pCur = m_pHead;
while (pCur)
{
forFunc(pCur->m_pData);
pCur = pCur->m_pNext;
}
}
protected:
Node* m_pHead; //头节点
Node* m_pEnd; //尾节点
int m_nCount; //节点个数
BOOL m_bNewList; //是否New的链表
BOOL m_bModify; //链表数据修改标记
};
我这是把函数实现也写在链表类中,当前然也可写在类外,
如:
在类内声明:
template<class FOREACH_FUNC>
void ForEachTwo(FOREACH_FUNC forFunc);
在类外实现,(要在同一头文件中)
template<class T>
template<class FOREACH_FUNC>
void QList<T>::ForEachTwo(FOREACH_FUNC forFunc)
{
//...
}
应用实例:
1.查找指定姓名的对象,返回对象指针
TCHAR name[]=TEXT("张三");
Student* pSut=m_stuList.FindSing_if([&name](Student* p){
return _tcscmp(p->name,name)==0;
});
2.删除指定姓名的对象
TCHAR name[]=TEXT("张三");
m_stuList.DelSing_if([&name](Student* p){
return _tcscmp(p->name,name)==0;
});
3.链表的遍历
m_stuList.ForEach([](Student* p){
//输出p的所有成员变量
TCHAR strMsg[64]={0};
_stprintf_s(strMsg,
TEXT("编号:%d,姓名:%s,性别:%s,年龄:%d"),
p->id,p->name,p->sex,p->age);
OutputDebugString(strMsg);//输出到输出窗口
});