模板链表类的扩展(QListEx<T>)
以前写的链表都是比较简单的,插入节点是在头节点上,所以循环链表时都是从最后一个数据往前找的,给人的感觉是倒着的,
今天写一个在链表尾部插入数据
1。链表节点类的定义
/链表节点类
template <class T>
class QNode
{
public:
QNode()
{
pNext = nullptr;
pData = nullptr;
}
public:
QNode<T>* pNext;//指向下一个节点的指针
T* pData; //指向数据域的指针
};
2.链表类的定义
//顺序链表
template <class T>
class QListEx
{
typedef BOOL(*PFINDBOOL)(T*,PVOID);
public:
QListEx();
~QListEx();
public:
void AddNode(T* pData); //添加数据到链表中
void ClearAll(); //清除所有节点和数据域内存
void ClearNode(); //清除节点内存(不清除数据域内存,有可能数据域被别的链表应用)
void DelAt(int nIndex); //删除指定索引位置的节点
void SetAt(int nIndex,T* pData); //设置指定索引的数据域数据
int GetCount()const; //获得节点个数
T* GetAt(int nIndex)const; //获得节点数据域指针
T* FindSing(PFINDBOOL pBol); //根据外部查寻条件返回单个数据域指针指向的内存
int FindIndex(PFINDBOOL pBol, PVOID pObject = 0); //根据外部查寻条件返回数据在链表中的索引值
int DelFind(PFINDBOOL pBol); //根据外部查寻条件删除数据,返回删除的个数
QListEx<T>* FindArray(PFINDBOOL pBol,LPVOID lpData); //根据外部查寻条件返回符合条件的数据集合
BOOL IsNull();
BOOL IsModfiy()const; //判断链表数据是否有修改状态
QNode<T>* GetHeadNode()const; //获得头节点指针
void ClearModfiy(); //清除修改标志 protected:
QNode<T>* m_pHead; //头指针
QNode<T>* m_pEnd; //尾指针
int m_nCount; //节点个数
BOOL m_bTemList; //是否是临时链表
BOOL m_bModfiy; //链表数据是否有修改
};
3.链表类方法的实现
3.1.链表构造函数
template<class T>
inline QListEx<T>::QListEx()
{
m_pEnd = nullptr;
m_pHead = nullptr;
m_nCount = 0;
m_bTemList = FALSE;
m_bModfiy = FALSE;
}
3.2 添加节点数据到链表中(AddNode)
//添加新的节点
//参数是数据域的内存地址,所以在外面要New一个数据域内存
template <class T>
inline void QListEx<T>::AddNode(T* pData)
{
QNode<T>* pNode = new QNode<T>;
pNode->pData = pData; if (m_pHead == nullptr)//如果头节点为NULL,新节点为头节点
{
m_pHead = pNode;
m_pEnd = m_pHead;
}
else //如果头节点不为空,尾节点的下一个指向新节点,再把新节点设置为尾节点
{
m_pEnd->pNext = pNode;
m_pEnd = pNode;
} m_bModfiy = TRUE; //链表中的数据有修改状态
m_nCount++;
}
3.3在链表中查找符合指定条件的数据
指定条件只能是在外部传进来的数据,所以就要定义一个函数指针类型
typedef BOOL(*PFINDBOOL)(T*,PVOID);//外部要给链表传递查询条件的函数指针类型
QListEx<T>* FindArray(PFINDBOOL pBol,LPVOID lpData); //根据外部查寻条件返回符合条件的多个数据的临时链表用后要删除
//返回的链表用完用ClearNode函数清除节点内存,最后用Delete删除链表所在的内存
//注意:不要用ClearAll清除,不然数据域的内存也会被删除
template<class T>
inline QListEx<T>* QListEx<T>::FindArray(PFINDBOOL pBol,LPVOID lpData)
{
QListEx<T>* pList = new QListEx<T>;
pList->m_bTemList = TRUE; QNode<T>* pCurr = m_pHead;
while (pCurr != nullptr)
{
if (pBol(pCurr->pData,lpData))
{
pList->AddNode(pCurr->pData);
} pCurr = pCurr->pNext;
} return pList;
}
在测试中应用:
1定义数据域结构类型
struct Student
{
int id;
TCHAR name[10];
TCHAR sex[2];
UINT age;
TCHAR tel[12];
Student()
{
id = 0;
memset(&name, 0, sizeof(name));
memset(&sex, 0, sizeof(sex));
age = 0;
memset(&tel, 0, sizeof(tel)); }
Student(int id, LPCTSTR name, LPCTSTR sex, UINT age, LPCTSTR tel)
{
this->id = id;
_tcscpy_s(this->name,name);
_tcscpy_s(this->sex, sex);
this->age = age;
_tcscpy_s(this->tel, tel);
}
};
2.定义链表
QListEx<Student>* m_pStuArray=new QListEx<Student>;
3.添加数据或是从文件中读取数据到链表中
下面的实例是从文件中读取数据到链表中
QFile file;
if (!file.OpenFile(FILENAME, QFile::modulRead))//没有找到要打开的文件就新建一个
{
file.CreateNewFile(FILENAME);
}
else
{
//从文件中读取数据循环添加到链表中
int nLeng = file.GetFileSize();
int readLeng = 0;
while (nLeng)
{
Student* pStu = new Student;
readLeng = file.ReadBinaryFile(pStu, sizeof(Student));
m_pStuArray->AddNode(pStu);
nLeng = nLeng - readLeng;
}
m_pStuArray->ClearModfiy();//清除链表的修改标志
}
file.CloseFile();
3.根据外部函数给定的查询条件返回符合条件的多个数据
void MyMainWnd::OnFindBtnClick()
{
QListEx<Student>* pList = m_pStuArray->FindArray(FindListData, this);
if (!pList->IsNull())
{
ShowStuArrayToListCtrl(&m_wndListCtrl, pList);
}
pList.ClearNode(); //清除链表节点内存(不清除数据域内存)
delete pList;
pList = nullptr;
}
函数指针FindListData为全局函数
BOOL FindListData(Student* pStu, LPVOID lpData)
{
QWnd* pWnd = (QWnd*)lpData; //获得主窗口对象指针
BOOL bResult = FALSE; TCHAR editStr[10] = { 0 };
GetDlgItemText(pWnd->m_hWnd, IDC_FINDEDIT, editStr, 10);//获得编辑框中查询条件数据
TCHAR firChar = editStr[0]; QComboBox cmb = GetDlgItem(pWnd->m_hWnd, IDC_COMBO1); //获得组合框中分类数据
int nSel = cmb.GetCurSel();
UINT nVaule = 0;
//根据要查询的分类返回符合条件的数据
switch (nSel)
{
case 0://All
bResult = TRUE;
break; case 1://ID
#if 0 if (firChar == '>')
{
firChar = editStr[1];
if (firChar == '=')
{
nVaule = _ttoi(editStr + 2);
bResult = (pStu->id >= nVaule);
}
else
{
nVaule = _ttoi(editStr + 1);
bResult = (pStu->id > nVaule);
}
}
else if (firChar == '<')
{
firChar = editStr[1];
if (firChar == '=')
{
nVaule = _ttoi(editStr + 2);
bResult = (pStu->id <= nVaule);
}
else
{
nVaule = _ttoi(editStr + 1);
bResult = (pStu->id < nVaule);
}
}
else if (firChar == '=')
{
nVaule = _ttoi(editStr + 1);
bResult = (pStu->id == nVaule);
}
else
{
nVaule = _ttoi(editStr);
bResult = (pStu->id == nVaule);
}
#endif
bResult = CmpIntVaule(pStu->id, editStr);
break; case 2://Name
bResult = (_tcscmp(pStu->name, editStr) == 0);
break; case 3://Sex
bResult = (_tcscmp(pStu->sex, editStr) == 0);
break; case 4://Age
bResult = CmpIntVaule(pStu->age, editStr);
break; case 5://Tel
bResult = (_tcscmp(pStu->tel, editStr) == 0);
break; default:
break;
} return bResult;
}
模板链表类的扩展(QListEx<T>)的更多相关文章
- C++类功能扩展预留五招
第一招虚函数 通过派生类来进行功能扩展是基本的面向对象的方式,这种方式大如下: class base { public: virtual ~base(){} virtual void fun() { ...
- C++_进阶之函数模板_类模板
C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...
- C++复习:函数模板和类模板
前言 C++提供了函数模板(function template).所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表.这个通用函数就称为函数模板.凡是函数体 ...
- C++解析(26):函数模板与类模板
0.目录 1.函数模板 1.1 函数模板与泛型编程 1.2 多参数函数模板 1.3 函数重载遇上函数模板 2.类模板 2.1 类模板 2.2 多参数类模板与特化 2.3 特化的深度分析 3.小结 1. ...
- 数据结构-单链表-类定义2-C++
上一次的C++链表实现两个单链表的连接不太理想,此次听了一些视频课,自己补了个尾插法,很好的实现了两个链表的连接,当然了,我也是刚接触,可能是C++的一些语法还不太清楚,不过硬是花了一些时间尽量在数据 ...
- spring初始化源码浅析之关键类和扩展接口
目录 1.关键接口和类 1.1.关键类之 DefaultListableBeanFactory 1.2.关键类之XmlBeanDefinitionReader 1.3.关键类之ClassPathXml ...
- 7 HandlerSet 处理程序链表类——Live555源码阅读(一)基本组件类
这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 my.oschina.net/oloroso Handler ...
- 20Spring_JdbcTemplatem模板工具类
JdbcTemplate 是Spring提供简化Jdbc开发模板工具类.为了更好的了解整个JdbcTemplate配置数据库连接池的过程,这篇文章不采用配置文件的方式,而是采用最基本的代码 的方式来写 ...
- IOS基础之 (十二) 类的扩展
对OC类的扩展总结如下,共有4个: 1.子类 subClass 作用:可以使用类的继承来增添父类的变量和方法. 写法:在.h文件中 @interface Student : Person 2.分类 C ...
- [Reprint] C++函数模板与类模板实例解析
这篇文章主要介绍了C++函数模板与类模板,需要的朋友可以参考下 本文针对C++函数模板与类模板进行了较为详尽的实例解析,有助于帮助读者加深对C++函数模板与类模板的理解.具体内容如下: 泛型编程( ...
随机推荐
- PHP 使用非对称加密算法
加密的类型: 在日常设计及开发中,为确保数据传输和数据存储的安全,可通过特定的算法,将数据明文加密成复杂的密文.目前主流加密手段大致可分为单向加密和双向加密. 单向加密:通过对数据进行摘要计算生成密文 ...
- 题解:P10733 [NOISG2019 Prelim] Lost Array
题解:P10733 [NOISG2019 Prelim] Lost Array 思路 对于任意 \(\min(X_{A_{i}},X_{B_{i}})=C_{i}\). 只要让 \(X_{A_{i}} ...
- 兼容sentry协议的轻量级监控,glitchtip
前言 上一篇文章说了重启 sentry 的事 因为过程太折腾了,一度想过放弃 sentry 换成其他比较轻量级的开源监控系统 这不就给我找到了另外俩个 https://glitchtip.com/ h ...
- fasterWhisper和MoneyPrinterPlus无缝集成
MoneyPrinterPlus之前使用的是各种云厂商的语音识别服务来进行语音的视频和字幕的识别工作. 但是很多小伙伴说云服务用不起. 那么没办法,MoneyPrinterPlus上线最新版本,支持f ...
- 【云服务器】记录使用腾讯云服务器搭建个人blog网站-【1】服务器配置
服务器购买 第一次写博客,写的不好请见谅 腾讯云教育活动 配置还行,能搭建个网站了果断下单 选择系统 缺点(对我来说):参考于:人生不开窍:Windows Server各版本差异 不能安装window ...
- 写写Redis十大类型hyperloglog(基数统计)的常用命令
hyperloglog处理问题的关键所在和bitmap差不多,都是为了减少对sql的写操作,提高性能,用于基数统计的算法.基数就是一种数据集,用于收集去重后内容的数量.会有0.81%的误差 hyper ...
- 基于Hive的大数据分析系统
1.概述 在构建大数据分析系统的过程中,我们面对着海量.多源的数据挑战,如何有效地解决这些零散数据的分析问题一直是大数据领域研究的核心关注点.大数据分析处理平台作为应对这一挑战的利器,致力于整合当前主 ...
- cgroup限制进程cpu
编写一个死循环脚本 [root@workstation ~]# cat circle.sh #!/bin/bash a=1 while true do let a++ done 查看top 使用cgr ...
- Jmeter函数助手22-V
V函数用于执行变量名.嵌套函数.类似eval函数 Name of variable (may include variable and function references):必填,填入变量名称或者 ...
- RPC和 HTTP协议
RPC 和HTTP 的区别 服务发现 HTTP,知道服务域名,可以通过 DNS 解析 得到 服务的IP地址,从而进行访问 RPC 需要一个专门的中间服务去保存服务名和IP信息(注册中心,nacos.c ...