数据结构--队列-泛型OC&C++混编-泛型编程

在这篇文章里, 您可以学习到:

  1. 数据结构简介
  2. 数据结构的逻辑结构和物理结构
  3. 队列
  4. OC和C++在Xcode中的混编
  5. 泛型编程思想
  6. 泛型编程实现循环队列和链表队列
  7. 博客中使用的图片均来自网络

一.数据结构简介

数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。

帮你理解

  1. 数据结构的实现与语言无关, 它可以被任何语言实现.
  2. 一个好的抽象, 可以适用普遍数据类型. 除了特定场合和教学示例外, 你不能只支持某种特定的数据类型.

谈到数据结构, 一定会涉及到的两个概念: 数据 和 数据之间的关系.

  • 数据: 我们前面提到, 数据结构不分数据类型, 这个数据可以是任何数据, 你可以把它想象成是一个收纳盒, 盒子内可以放任何东西.

  • 关系: 按照相面的比喻, 关系就是指这些收纳盒之间的映射关系. 比如我规定一种关系: 把这些盒子排成一列, 对于中间的某个盒子来讲, 它的前面和后面都有一个和它紧挨的盒子. 我们可以说, 这个盒子和它前面和后面的盒子有关系, 和它不相邻的盒子没有关系. 那么我们可以把这样的模型剥离出来, 得到一种数据结构 – 线性结构, 又叫线性表.

推理
按照这种抽象模型的过程, 我们可以把下面的关系抽离出另一种数据结构.
file-listfile-list
还可以继续抽象, 元素之间的关系式任意的, 就得到了网状结构, 也就是我们所说的.
file-listfile-list

抽象出状结构之后, 我们基本已经无法再从对应关系上来细分了, 不信您就想想, 你所成想到的关系, 全部包含在这几种抽象中了

吗?

当然不是, 空间还能抽象到11维呢!

事实上, 上述数据结构的共性–每个元素至少与其他元素建立了联系. 这种规则是人为规定的, 没人要求我们一定这样抽象数据, 所以, 我们可以假设所有的盒子之间两两都没有关系, 所有盒子都是独立的, 就像一堆硬币, 我们把这种数据结构成为集合:

file-listfile-list

至此, 我们得到了四种结构

线性表: 数据结构中的元素存在一对一的相互关系
树: 数据结构中的元素存在一对多的相互关系
图: 数据结构中的元素存在多对多的相互关系
散列(集合): 数据结构中的元素之间除了“同属一个集合” 的相互关系外,别无其他关系

  • 注意: 数据结构只有这四种吗?
    现实世界中的结构千变万化,没有通用结构可以解决所有问题。甚至一个小问题,某个适应此类问题很优秀的结构却未必就适合它。
    我们提炼的4种结构, 相对来讲是最具普遍性的, 能适应现实世界的大多数场景.
    你可以提炼你自己的数据结构.

二. 数据结构的逻辑结构和物理结构

书承上文
数据结构指同一数据元素类中各数据元素之间存在的关系。数据结构分别为逻辑结构存储结构(物理结构)和数据的运算. 数据的逻辑结构是从具体问题抽象出来的数学模型,是描述数据元素及其关系的数学特性的,有时就把逻辑结构简称为数据结构.

逻辑结构: 我们上面赘述了那么多, 都是描述的逻辑结构(不涉及实现问题, 只是描述它们的关系).
存储结构(物理结构): 真正有关数据在计算机中是如何存储方式.

这个’存储’是指在内存中的存在形式(并非外设, 如硬盘/U盘/光盘).

假设我们有10个盒子, 它们是线性结构, 这10个盒子应该如何摆放呢?

既然是线性结构, 难道不是依次摆放吗? 一个挨着一个的样子.

您要是这么想得话, 说明您没有明白物理结构和逻辑结构的区别.
假如我们把盒子分别放到不同的地方, 然后在每个盒子上写明: 它上一个盒子是放在哪里, 下一个盒子放在哪里.
那么您是不是可以根据盒子上的位置找到下一个盒子呢? 当然可以了.

这就是逻辑结构(线性关系)和物理结构(摆放位置)的区别.

事实上, 我们在内存中存放数据的格式确实有两种: 顺序存储链式存储

顺序存储: 顾名思义, 数据放在一块儿连续的内存空间, 工作指针的移动可以很方便的找到其他元素(我说的是其他元素, 而不是下一个元素, 因为这样的存储方式也不一定完全为线性表存储)
链式存储: 所有元素均任意存放在内存中, 元素之间是通过元素内的指针互相寻找对方的.

三.队列

队列是一种特殊的线性表,特殊之处在于它只允许在表的 前端(head) 进行删除操作,而在表的 后端(tail) 进行插入操作,队列是一种操作受限制的线性表。进行插入操作的端称为 队尾 ,进行删除操作的端称为 队头

队列特点是先进先出,后进后出.

file-listfile-list

队列的定义, 除了点名了它元素之间的逻辑关系, 也定义了它的部分算法.

算法与数据结构密不可分, 它依附于数据结构而存在, 对于任何算法的编写,必须依赖一个已经存在的数据结构来对它进行操作,数据结构成为算法的操作对象,这也是为什么算法和数据结构两门分类不分家的概念,算法在没有数据结构的情况下,没有任何存在的意义. 而数据结构没有算法就等于是一个尸体而没有灵魂

对于一个线性表来说, 必须实现下面5种基本方法才能被称为是队列:

  • 初始化队列:Init_Queue(q) ,初始条件:队q 不存在。操作结果:构造了一个空队
  • 入队操作: In_Queue(q,x),初始条件: 队q 存在。操作结果:对已存在的队列q,插入一个元素x 到队尾,队发生变化
  • 出队操作: Out_Queue(q,x),初始条件: 队q 存在且非空,操作结果: 删除队首元素,并返回其值,队发生变化
  • 读队头元素:Front_Queue(q,x),初始条件: 队q 存在且非空,操作结果: 读队头元素,并返回其值,队不变
  • 读队头元素:Front_Queue(q,x),初始条件: 队q 存在且非空,操作结果: 读队头元素,并返回其值,队不变

以上只是要求实现的基本方法, 你可以为队列添加其他的方法,我们规定上面的方法是普世大多数应用场景, 如果你的需求特殊, 完全可以进行扩展.

  • 队列的实现方式

    队列是一种受限制的线性表, 所以它的实现和线性表的实现一样, 可以分为 顺序存储链式存储

    队列的顺序存储分为两种: 顺序队列和循环队列, 具体我们在下面详解.
    队列的链式存储是一种链表实现.

  • 顺序队列

    建立顺序队列结构必须为其静态分配或动态申请 一片连续的存储空间 ,并设置两个指针(下标)进行管理。一个是队头指针head,它指向队头元素;另一个是队尾指针tail,它指向下一个入队元素的存储位置.

file-listfile-list

  • 每次在队尾插入一个元素是,tail增1
  • 每次队头删除一个元素时,head增1。
  • 随着插入和删除操作的进行,队列元素的个数不断变化,队列所占的存储空间也在为队列结构所分配的连续空间中移动。
  • 当head==tail时,队列中没有任何元素,称为 空队
  • 当tail增加到指向分配的连续空间之外时,队列无法再插入新元素.成为 满队
  • 这时往往还有大量可用空间未被占用,这些空间是已经出队的队列元素曾经占用过得存储单元。这种现象叫做 “溢出”

事实上, 顺序队列有三种溢出:

  • “下溢”现象:当队列为空时,做出队运算产生的溢出现象。“下溢”是正常现象,常用作程序控制转移的条件.
  • “真上溢”现象:当队列满时,做进栈运算产生空间溢出的现象。“真上溢”是一种出错状态,应设法避免.
  • “假上溢”现象:由于入队和出队操作中,头尾指针只增加不减小,致使被删元素的空间永远无法重新利用。当队列中实际的元素个数远远小于向量空间的规模时,也可能由于尾指针已超越向量空间的上界而不能做入队操作。该现象称为”假上溢”现象.

“下溢”和”真上溢”是我们无法避免的, 他们本身也不属于异常现象. 但是”假上溢”会使我们程序发生异常,我们要避免它.
如何利用使用过的空间呢?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值