C++中也有相应的动态数组、动态链表、映射表的模板类,就是STL中的:vector、list、map
他们属于C++标准中的一部分,对于程序的移植性来说也是不错的,但是在MFC编程中使用 CArray、CList、CMap 会更方便一些!
CArray、CList、CMap 的由来?……
 
①、数组的基本说明:
数组是固定大小的,相同数据类型的元素的顺序集合,每个元素在数组中有一个固定的位置。
将10个数放入数组中,假设数组的名称为number,可以称数组中第一个元素为 number[0],第二个数为 number[1]……其中 0、1~9 称为元素的下标,
下标表明元素在数组中的相对位置。
 
例如,普通的常规静态数组定义为:
int number[20];
CPoint pt[10];
CButton btn[10];
====================================================
②、MFC中的动态数组类是:CArray
CArray 是一个模板类,类似于常规数组,但是长度可动态增长;
常规数组在使用前必须先知道元素的个数,即先确定大小,而MFC的动态数组类 CArray 创建的对象可以根据需要动态地增大或减小,
数组的起始下标是0,而上限可以是固定的,也可以随着元素的增加而增加,数组在内存中的位置仍然是连续的(这一点很关键)!
 
虽然 CArray 是一个模板类,但是微软在 MFC 中针对各种常用的变量类型分别定义了:
CByteArray、CDWordArray、CObArray、CPtrArray、CStringArray、CUIntArray、CWordrray 等,
所以,如果大家在程序中使用的数据结构有合适以上几种的类型的,可以直接拿过来用,无需重复定义,详见MSDN!
========================================================
③、CArray 类型对象的定义:其中带有 ARG_ 前缀的是传入类型,另外一个则是返回类型
CArray <int, int> arrInt;
CArray <CPoint, CPoint &> arrPoint;
CArray <CButton, CButton &> arrButton;
//在使用基本类型的时候,第二个参数可以不用传引用,但是使用类类型等符合类型的时候第二个参数最好传递对象的引用,
//这样可以避免拷贝构造函数的调用,提高效率!
 
CStringArray arrString;
CByteArray arrByte;
====================================================
④、CArray 类的使用:
// 插入节点、删除节点、遍历数组
INT_PTR idx = 0;
CArray <CPoint, CPoint &> arrPoint;
//arrPoint.SetSize(100, 10);
BOOL bRet = arrPoint.IsEmpty();
for (idx = 0; idx < 100; ++idx){
 CPoint pt;
 pt.SetPoint(idx, idx);
 arrPoint.Add(pt);//元素的添加
}
int nCount = arrPoint.GetCount();
int maxIdx = arrPoint.GetUpperBound();
bRet = arrPoint.IsEmpty();
CPoint point = arrPoint.GetAt(10);
arrPoint.RemoveAt(10, 5); //指定元素的删除
nCount = arrPoint.GetCount();
point = arrPoint.GetAt(10);
point = arrPoint[11];
 
//数组的遍历
for (idx = 0; idx < arrPoint.GetCount(); ++idx){
 CPoint pt = arrPoint.GetAt(idx);
 pt.x = 123;
}
 
point.x = point.y = 999;
arrPoint.SetAt(5, point);
 
for (idx = 0; idx < arrPoint.GetCount(); ++idx){
 CPoint pt = arrPoint.GetAt(idx);
 pt = pt;
}
 
arrPoint.RemoveAll();
nCount = arrPoint.GetCount();
bRet = arrPoint.IsEmpty();
====================================================
⑤、CArray 的效率问题:
问:CArray 确实很好用,但是为什么到了10万个数据以后,赋值的速度就很慢了呢?
答:CArray 是很好用的,只是因为你没有指定数组的最大尺寸。
因此,当你添加新元素时,该类会从堆中重新分配空间,不幸的是,该类会在每次插入新元素时都为数组重新分配空间,
如果你向它添加了很多新元素,所有这些分配和复制数组的操作会就会使它变慢。
 
解决该问题的方法是,你可以使用SetSize函数的第二个参数来改变这种重新分配的频率。
例如,如果你把该参数设置为500,则每次数组空间超出时它才重新分配并添加500个新空间,而不是1个,
这样一来,你就可以不用重新分配而添加了另外499个元素空间,这也会大大提高程序的运行速度。
 
====================================================
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
====================================================
⑥、链表的基本说明:
链表也是一个有序数据的集合,但每个元素包含下一个元素的地址。
每个元素包含两部分:数据和链(链是存储下一个元素地址的指针)
此处只讨论单链表,每个节点仅有一个指向后继节点的链。通常使用一个指针变量指向第一个元素,称为链表的头指针。链表的最后一个元素包含一个空指针,标识链表的结束。
链表是一种复杂的数据结构,其数据之间的相互关系使链表分成三种:单链表、循环链表、双向链表
 
链表在内存中的位置是不连续的(这一点很关键)!
 
例如,普通的链表节点定义为:
struct node
{
    int num;
    struct node *p;
} ;
====================================================
⑦、MFC中的动态链表类是:CList
CList 是双向链接表,因此 头、尾和表中已知位置(POSITION)的元素插入速度很快。
按值或者索引查找需要顺序搜索,然而如果表很长则速度可能慢!
 
虽然 CArray 是一个模板类,但是微软在 MFC 中针对各种常用的变量类型分别定义了:
CPtrList、CObList、CStringList 等,
所以,如果大家在程序中使用的数据结构有合适以上几种的类型的,可以直接拿过来用,无需重复定义,详见MSDN!
====================================================
⑧、CList 类型对象的定义:其中带有 ARG_ 前缀的是传入类型,另外一个则是返回类型
CList <int, int> arrInt;
CList <CPoint, CPoint &> arrPoint;
CList <CButton, CButton &> arrButton;
//在使用基本类型的时候,第二个参数可以不用传引用,但是使用类类型等符合类型的时候第二个参数最好传递对象的引用,
//这样可以避免拷贝构造函数的调用,提高效率!
====================================================
⑨、CList 类的使用:
int idx = 0;
CList <CPoint, CPoint &> ptList(100);
BOOL bRet = ptList.IsEmpty();
for (idx = 0; idx < 100; ++idx){
 CPoint pt;
 pt.SetPoint(idx, idx);
 ptList.AddTail(pt);//向链表结尾添加元素
}
int nCount = ptList.GetCount();
bRet = ptList.IsEmpty();
 
//POSITION ps = 10;
CPoint point = ptList.GetAt(ptList.FindIndex(10));
ptList.RemoveAt(ptList.FindIndex(10)); //指定元素的删除
nCount = ptList.GetCount();
point = ptList.GetAt(ptList.FindIndex(10));
 
//链表的遍历
POSITION pos = ptList.GetHeadPosition();
for (idx = 0; idx < ptList.GetCount(); ++idx) {
 CPoint pt = ptList.GetNext(pos);
 pt.x = 123;
}
 
point.x = point.y = 999;
ptList.SetAt(ptList.FindIndex(5), point);
 
pos = ptList.GetHeadPosition();
for (idx = 0; idx < ptList.GetCount(); ++idx) {
 CPoint pt = ptList.GetNext(pos);
 pt = pt;
}
 
ptList.RemoveAll();
nCount = ptList.GetCount();
bRet = ptList.IsEmpty();
 
⑩、※※※ 链表与数组的区别 ※※※
   数组是将元素在内存中连续存放,由于每个元素占用内存相同,所以可以通过下标迅速访问数组中任何元素。
但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。
同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。
 
   链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。如:上一个元素有个指针指到下一个元素,以此类推,直到最后一个元素。
如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了, 只要修改元素中的指针就可以了。
 
   ※※※ 从上面的比较可以看出,如果需要快速访问数据,很少或不插入和删除元素,就应该用数组,相反, 如果需要经常插入和删除元素就需要用链表了!
 
====================================================
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
====================================================
 
11、映射表的基本说明:
映射表类 也称作为“字典”,就像一种只有两列的表格,一列是关键字,一列是数据项,它们是一一对应的,是以键值对的形式出现的!
关键字是唯一的(※ 这点很重要),给出一个关键字,映射表会很快找到对应的数据项。
映射表的查找是以哈希表的方式进行的,因此在映射表中查找数值项的速度很快。
映射类最适用于需要根据关键字进行快速检索的场合。
 
例如:公司的所有职员都有一个工号和自己的姓名,工号就是关键字,给出一个工号,就可以很快的找到相应的姓名!
姓名可以重复,或者说有同名的情况,但是工号一定不能出现重复的!
 
12、MFC中的动态映射表类是:CMap
 
虽然 CMap 是一个模板类,但是微软在 MFC 中针对各种常用的变量类型分别定义了:
CMapWordToPtr、CMapPtrToWord、CMapPtrToPtr、CMapWordToOb、CMapStringToPtr、CMapStringToOb、CMapStringToString 等,
所以,如果大家在程序中使用的数据结构有合适以上几种的类型的,可以直接拿过来用,无需重复定义,详见MSDN!
 
13、CMap 类型对象的定义:其中带有 ARG_ 前缀的是传入类型,另外一个则是返回类型
CMap <int, int, CString, LPCTSTR> intMapString;
CMap <int, int, int, int> intMapInt;
CMap <int, int, CPoint, CPoint &> intMapPoint;
CMap <long, long, CButton, CButton &> longMapButton;
CMap <CString, LPCTSTR, int, int> strMapString;
//在使用基本类型的时候,第二、四个参数可以不用传引用,但是使用类类型等符合类型的时候第二、四个参数最好传递对象的引用,
//这样可以避免拷贝构造函数的调用,提高效率!
 
14、CMap 类的使用:
CMap<int, int, CString, LPCTSTR> intMapString(20);
 
CString strText;
for (int idx = 0; idx < 20; ++idx){
 strText.Format(_T("%s%d"), _T("The number is : "), idx);
 intMapString.SetAt(idx, strText);
}
 
int nCount = intMapString.GetCount();
BOOL bRet = intMapString.IsEmpty();
 
strText.Empty();
intMapString.Lookup(10, strText);//根据key查找元素
intMapString.RemoveKey(10); //根据key删除元素
nCount = intMapString.GetCount();
 
strText.Empty();
intMapString.Lookup(10, strText); //还能找到吗?
 
//映射表的遍历
int nKey = 0;
POSITION pos = intMapString.GetStartPosition();
while (pos != NULL) {
 strText.Empty();
 intMapString.GetNextAssoc(pos, nKey, strText);
}
 
intMapString.SetAt(5, _T("abcdefg123"));
 
intMapString.RemoveAll();
nCount = intMapString.GetCount();
bRet = intMapString.IsEmpty();
 
 
★ 课后作业:
1、练习使用 CStringArray 等类的使用;
------------------------------------- End -------------------------------------------

vc++基础班[28]---动态数组及动态链表的讲解的更多相关文章

  1. vc++基础班[24]---系统各种路径信息的获取

    vc++基础班[24]---系统各种路径信息的获取 ------------------------------------------ Begin ------------------------- ...

  2. vc++基础班[25]---系统信息的获取

    --------------------------------------------------------------------------- VC 驿站 WwW.CcTry.CoM 多抽出一 ...

  3. vc++基础班[23]---文件夹的基本操作

      ①.文件夹的创建:CreateDirectory ※※※ 注意:此函数只能创建一层目录,比如想在 C 盘下的 Temp 目录下创建新目录为:123 那么前提是 Temp 这个目录存在才可以!   ...

  4. vc++基础班[22]---文件的基本操作2

      MFC 中的 CFile 及其派生类中没有提供直接进行文件的复制操作,因而要借助于SDK API: SDK中的文件相关函数常用的有CopyFile().CreateDirectory().Dele ...

  5. vc++基础班[21]---文件的基本操作之CFile

    ①.文件的创建.打开.关闭: 文件的创建.打开:CFile::Open 文件的关闭:CFile::Close   CFile::modeCreate:以新建方式打开,如果文件不存在,则新建:如果文件已 ...

  6. vc++基础班[27]---实现一个简单的任务管理器

      因为任务管理器中涉及到进程的枚举操作,所以把两节课的知识点合并到一起来讲!   ①.设计界面.以及列表控件变量的绑定: ②.列表控件样式的指定: m_TaskList.SetExtendedSty ...

  7. vc++基础班[26]---进程的相关操作

      ①.ShellExecute 进行进程的创建,属于 shell api: //int iRet = (int)ShellExecute(m_hWnd, _T("open"), ...

  8. 一篇文章让你了解动态数组的数据结构的实现过程(Java 实现)

    目录 数组基础简单回顾 二次封装数组类设计 基本设计 向数组中添加元素 在数组中查询元素和修改元素 数组中的包含.搜索和删除元素 使用泛型使该类更加通用(能够存放 "任意" 数据类 ...

  9. C++ Primer : 第十二章 : 动态内存之动态数组

    动态数组的分配和释放 new和数组 C++语言和标准库提供了一次分配一个对象数组的方法,定义了另一种new表达式语法.我们需要在类型名后跟一对方括号,在其中指明要分配的对象的数目. int* arr ...

随机推荐

  1. 利用css3给座右铭设置漂亮的渐变色

    .footer-container .footer-content p .motto { font-weight: bolder; -webkit-background-clip: text; -we ...

  2. 【leetcode-100】 简单 树相关题目

    100. 相同的树 (1过,熟练) 给定两个二叉树,编写一个函数来检验它们是否相同. 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的. 示例 1: 输入: 1 1 / \ / \ 2 ...

  3. 搭建idea下的vue工程

    需要先安装好nodejs和npm 输入下面的命令查看是否成功安装 node -v npm -v 一.开始 工作目录:IdeaProjects使用idea新建Static Web项目:demo 在dem ...

  4. Nginx 之六: Nginx服务器的正向及反向代理功能

    一:Nginx作为正向代理服务器: 1.正向代理:代理(proxy)服务也可以称为是正向代理,指的是将服务器部署在公司的网关,代理公司内部员工上外网的请求,可以起到一定的安全作用和管理限制作用,正向代 ...

  5. adb server version (31) doesn't match this client (40); killing...

    删除360的手机助手即可解决,进程名字360MoblieMgr.exe

  6. ASP.NET Web API 2 使用 AuthorizationFilter(授权过滤器)实现 Basic 认证

    Ø  前言 在 Web 项目中授权认证方式有很多种,本文主要讲述基于 Basic 的认证方式.这是一种比较简单.常见的认证方式,主要是将请求的用户名和密码进行加密后返回给调用方,比较适合采用用户名.密 ...

  7. 二十一、Linux 进程与信号---进程查看和进程状态、进程调度和进程状态变化、进程标识

    21.1 进程查看和进程状态 21.1.1 ps 指令 ps 指令通常可以查看到进程的 ID.进程的用户 ID.进程状态和进程的 Command ps:查看当前用户启动的进程 ps -ef:详细查看后 ...

  8. 20155324 2016-2017-2 《Java程序设计》第2周学习总结

    20155324 2016-2017-2 <Java程序设计>第2周学习总结 教材学习内容总结 Java可区分为基本类型(Primitive Type)和类类型(Class Type)两大 ...

  9. java实现数据缓存

    摘抄自java并发实战 有时候需要对数据缓存.用Map缓存数据比较合适.但是由于对吞吐量,一致性,计算性能的要求,对数据进行缓存的设计还是需要慎重考虑的. 一.利用HashMap加同步 (1)说明 把 ...

  10. luogu P3244 [HNOI2015]落忆枫音

    传送门 md这题和矩阵树定理没半毛钱关系qwq 首先先不考虑有环,一个\(DAG\)个外向树个数为\(\prod_{i=2}^{n}idg_i(\)就是\(indegree_i)\),因为外向树每个点 ...