跳到主要内容

数据类型与数据结构

A-Level 计算机科学 · 第 10 主题

训练
讲义 词汇表
10.1

数据类型与记录

大纲
Candidates should be able to: Notes and guidance
Select and use appropriate data types for a problem solution including integer, real, char, string, Boolean, date (pseudocode will use the following data types: INTEGER, REAL, CHAR, STRING, BOOLEAN, DATE, ARRAY, FILE)
Show understanding of the purpose of a record structure to hold a set of data of different data types under one identifier Write pseudocode to define a record structure
Write pseudocode to read data from a record structure and save data to a record structure

来源:剑桥国际大纲

每个变量都需要一个数据类型(data type)——它容纳的值的种类和允许的操作:

  • INTEGER — 一个整数(42-7)。用于计数、索引、ID。
  • REAL — 一个带小数部分的数(3.14)。用于金额、测量。
  • STRING — 引号中的字符("Hello")。用于文本。
  • CHAR — 一个单一字符('A')。
  • BOOLEANTRUEFALSE。用于标志。
  • DATE — 一个日历日期。

选择适合的最小而精确的类型:INTEGER 用于整数计数,BOOLEAN 用于标志(而不是字符串 "yes"/"no")。

词汇表 训练
英文 中文 拼音
data type 数据类型 shù jù lèi xíng
10.1

记录

一个记录(record,一个记录结构(record structure))在一个名称下容纳几个不同类型的字段——当几个值描述同一件事物时很有用。

TYPE TStockItem
    DECLARE ItemID : INTEGER
    DECLARE Category : STRING
    DECLARE ItemCost : REAL
    DECLARE InStock : BOOLEAN
ENDTYPE

这定义了类型 TStockItem;声明它的变量:

DECLARE Item1 : TStockItem
DECLARE Items : ARRAY[1:100] OF TStockItem

用点记法访问每个字段(field):

Item1.Category ← "Fruit"
OUTPUT Item1.Category, " costs ", Item1.ItemCost

当值总是属于一起时(一个客户、一个库存商品)用一个记录;对无关的值用分开的变量。

一个 TStockItem 记录被画成一个名称下四个字段的堆叠——ItemID(INTEGER)、Category(STRING)、ItemCost(REAL)、InStock(BOOLEAN)——用点记法如 Item1.Category 访问
一个记录在一个名称下容纳几个不同类型的字段
探索

A record groups fields under one name

A record bundles related fields together. Each field is a named label you reach with dot notation — Item1.Category — not by a numeric index.

词汇表 训练
英文 中文 拼音
record 记录 jì lù
field 字段 zì duàn
record structure 记录结构 jì lù jié gòu
10.2

数组

大纲
Candidates should be able to: Notes and guidance
Use the technical terms associated with arrays Including index, upper bound and lower bound
Select a suitable data structure (1D or 2D array) to use for a given task
Write pseudocode for 1D and 2D arrays
Write pseudocode to process array data Sort using a bubble sort Search using a linear search

来源:剑桥国际大纲

一个数组(array)是同一类型的项的一个有序集合,在一个名称下,用一个索引(index)访问。

  • 元素(element)——数组中的一项。
  • 边界(bounds)——最低和最高的有效索引。
  • 维度(dimension)——1-D(一个列表)、2-D(一个表格),等等。

1-D arrays

DECLARE Names : ARRAY[1:5] OF STRING
Names[3] ← "Cara"
OUTPUT Names[3]

用一个 FOR 循环处理每个元素:

FOR i ← 1 TO 5
    OUTPUT Names[i]
NEXT i
一行名为 myList 的带索引单元,索引从 0 到 8,标出下界(第一个索引)和上界(最后一个索引)
一个 1-D 数组(一个列表),带索引和边界

2-D arrays (2D array)

DECLARE Grid : ARRAY[1:3, 1:4] OF INTEGER
Grid[2, 3] ← 99

第一个索引是行,第二个是列。用嵌套循环访问每个单元。对一个单一序列用 1-D,对两个自然维度(一个网格,行 × 列)用 2-D

一个 3 乘 4 的网格,带行索引和列索引;第 2 行第 3 列的单元被高亮
一个 2-D 数组(一个表格),带行索引和列索引

Common operations

一个线性查找(linear search)检查每个元素直到找到:

FOR i ← 1 TO n
    IF A[i] = Target THEN
        OUTPUT "Found at ", i
    ENDIF
NEXT i

要求一个和、计数、最大值或最小值,设一个运行中的变量,然后扫过:

Max ← A[1]
FOR i ← 2 TO n
    IF A[i] > Max THEN Max ← A[i]
NEXT i

一个冒泡排序(bubble sort)把一个数组排序:扫过它,比较每个相邻对,并交换任何顺序错误的;重复各趟直到某一趟不再有交换。

对 5、2、8、1 的一趟冒泡排序:比较 5 和 2 并交换得到 2、5、8、1;比较 5 和 8(已经有序);比较 8 和 1 并交换得到 2、5、1、8,所以最大值 8 到达末端
冒泡排序的一趟:相邻对被比较并交换,把最大值冒泡到末端
探索

A 2-D array

Pick a row and column to read one element — how a grid of data is stored and indexed.

词汇表 训练
英文 中文 拼音
index 索引 suǒ yǐn
element 元素 yuán sù
bounds 边界 biān jiè
dimension 维度 wéi dù
linear search 线性查找 xiàn xìng chá zhǎo
bubble sort 冒泡排序 mào pào pái xù
10.3

文件

大纲
Candidates should be able to: Notes and guidance
Show understanding of why files are needed
Write pseudocode to handle text files that consist of one or more lines

来源:剑桥国际大纲

一个文件(file)是存储在辅助存储器(secondary storage)上的数据,在程序运行之间保留。RAM 中的变量在程序结束时消失,所以要永久保存数据(高分、记录、设置),程序写入一个文件。文件也让程序共享数据并从一个保存的状态重启。

RAM 中的变量在程序结束时丢失,但磁盘上的一个文件在运行之间保留,所以程序保存到它并从它加载
RAM 中的变量在程序结束时消失;磁盘上的一个文件在运行之间持久保留

一个文本文件(text file)容纳一行或多行可读字符;程序逐行读写文本文件。使用前打开一个文件,用后关闭它:

OPENFILE "data.txt" FOR READ      // or FOR WRITE, FOR APPEND
WHILE NOT EOF("data.txt") DO
    READFILE "data.txt", LineString
    OUTPUT LineString
ENDWHILE
CLOSEFILE "data.txt"

EOF 在读取之前测试文件结束(end of file)。要写入:

OPENFILE "log.txt" FOR WRITE
FOR i ← 1 TO 100
    WRITEFILE "log.txt", "Event " & i
NEXT i
CLOSEFILE "log.txt"

总是关闭每个文件——否则缓冲的写入可能丢失,而且其他程序可能被锁在外面。

探索

Handling a file: open → use → close

Step through the lifecycle every file follows. The two easy-to-forget parts are testing EOF while reading in a loop, and always closing at the end.

词汇表 训练
英文 中文 拼音
file 文件 wén jiàn
secondary storage 辅助存储器 fǔ zhù cún chǔ qì
text file 文本文件 wén běn wén jiàn
end of file 文件结束 wén jiàn jié shù
10.4

抽象数据类型(ADT)导论

大纲
Candidates should be able to: Notes and guidance
Show understanding that an ADT is a collection of data and a set of operations on those data
Show understanding that a stack, queue and linked list are examples of ADTs Describe the key features of a stack, queue and linked list and justify their use for a given situation
Use a stack, queue and linked list to store data Candidates will not be required to write pseudocode for these structures, but they should be able to add, edit and delete data from these structures
Describe how a queue, stack and linked list can be implemented using arrays

来源:剑桥国际大纲

链表:通过重新连接指针来插入
栈对队列:LIFO 和 FIFO

一个抽象数据类型(Abstract Data Type,ADT)是一组数据加上对它的操作,由它做什么定义,而不是它如何存储。用户只通过操作工作;实现被隐藏,所以它可以改变而不影响使用该 ADT 的代码。要知道三个:栈、队列、链表。

Stack

一个(stack)以 LIFO(后进先出,Last In, First Out)顺序工作。操作:入栈(push,加到顶部)、出栈(pop,从顶部移除)、peek(查看顶部),以及对空/满的测试。用途:撤销历史、函数调用返回地址、表达式解析、回溯。

一个存储在数组中的栈以三个状态显示;Top 指针在一次 push 后上移、在一次 pop 后下移,而栈的底保持固定
push 和 pop 改变顶指针;底指针保持不动
一摞高高的书,一本平放在另一本上面
一摞书就是一个看得见的栈。你只能从顶部加书或取书,所以最后放上去的是第一个取下来的——这正是 LIFO(后进先出)

Queue

一个队列(queue)以 FIFO(先进先出,First In, First Out)顺序工作。操作:入队(enqueue,加到后端)、出队(dequeue,从前端移除),以及对空/满的测试。用途:打印假脱机、调度、广度优先搜索、缓冲。

一个存储在数组中的线性队列以三个状态显示;enqueue 推进 Rear 指针,dequeue 推进 Front 指针,留下起始单元空着并被浪费
enqueue 在后端添加;dequeue 从前端移除
一条很长的人龙,一个接一个地等着,沿着一堵墙延伸到远处
一队人就是一个看得见的队列。你从后面加入,从前面被服务,所以等得最久的人最先被服务——这正是 FIFO(先进先出)

Linked list

一个链表(linked list)把数据存储为一系列节点(nodes)。每个节点容纳一个值和一个指向下一个节点的指针(pointer);一个头指针标记起点,而最后一个节点的指针是一个哨兵(例如 NULL)。操作:插入、删除、搜索,以及遍历(traverse,按顺序访问每个节点)。它相对数组的优点是廉价的插入/删除(只需调整指针);它的缺点是慢的随机访问(你必须从头跟随指针)。

一行四个节点,每个容纳一个值和一个 next 指针字段;一个头指针指向第一个节点,最后一个节点的指针是 NULL
一个链表:每个节点指向下一个
探索

A linked list: nodes joined by pointers

Each node stores a value and a pointer to the next node. Inserting or deleting just re-links pointers — no items shift along, unlike an array.

探索

Stacks and queues

Push and pop. A stack is last-in-first-out; a queue is first-in-first-out — two key ADTs.

词汇表 训练
英文 中文 拼音
abstract data type 抽象数据类型 chōu xiàng shù jù lèi xíng
stack zhàn
LIFO 后进先出 hòu jìn xiān chū
push 入栈 rù zhàn
pop 出栈 chū zhàn
queue 队列 duì liè
FIFO 先进先出 xiān jìn xiān chū
enqueue 入队 rù duì
dequeue 出队 chū duì
linked list 链表 liàn biǎo
node 节点 jié diǎn
pointer 指针 zhǐ zhēn
traverse 遍历 biàn lì
10.4

用数组实现抽象数据类型

Stack using an array

把项保存在 Stack[1:MaxSize] 中,带一个整数 Top(空时为 0)。

  • Push(x):若 Top = MaxSize 则栈满(溢出(overflow));否则 Top ← Top + 1;Stack[Top] ← x
  • Pop():若 Top = 0 则栈空(下溢(underflow));否则返回 Stack[Top]Top ← Top - 1

Queue using a circular array

一个简单队列让 FrontRear 走出末端,浪费起始部分。修正是一个循环数组(circular array)——当一个指针到达 MaxSize 时它绕回到 1:

  • Enqueue(x):检查满;否则 Rear ← (Rear MOD MaxSize) + 1;Queue[Rear] ← x
  • Dequeue():检查空;否则返回 Queue[Front]Front ← (Front MOD MaxSize) + 1

跟踪一个单独的计数以区分空和满。

例如,当 MaxSize = 6 时:若 Rear = 5,则 (5 MOD 6) + 1 = 6,所以下一项放入单元 6;若 Rear = 6,则 (6 MOD 6) + 1 = 1,所以指针绕回到单元 1。

一个存储在数组中的循环队列;填充的单元越过最后一个单元绕回到起点,一条曲线箭头显示指针从最后一个索引绕回到单元 1
一个循环队列把指针绕回到数组的起点

Linked list using an array

用一个记录的数组,每个带一个 Next 索引:

TYPE TNode
    DECLARE Value : INTEGER
    DECLARE Next : INTEGER     // index of the next node, or -1 for end
ENDTYPE

DECLARE Nodes : ARRAY[1:MaxSize] OF TNode
DECLARE Head : INTEGER         // index of first node, -1 if empty
DECLARE FreeListHead : INTEGER // first available free node

一个空闲列表(free list)把未使用的槽链在一起,正如数据列表把它用过的槽链在一起。要插入:从 FreeListHead 取一个槽,设新节点的值和 Next,并更新前一个节点的 Next(或 Head)。要删除:解开该节点的链接并把它的槽还给空闲列表。这给出一个链式结构的灵活性和一个数组的静态分配。

一个 Value 数组和一个平行的 Next 数组实现一个链表;一个 Head 指针链起用过的节点,一个 FreeListHead 指针链起空闲的槽,每个都以 Next = -1 结束
一个存储在数组中的链表:一个数据数组和一个指针数组

例题。 一个循环队列存放在大小为 5 的数组中(下标 0 到 4),此时 Front = 3Rear = 3,存有一个元素。先加入两个元素,再移除两个。指针各在哪里?为什么要用循环队列?每次移动都用 (指针 + 1) MOD 大小,所以指针会回绕。加入两次会移动 Rear:$3 \rightarrow 4$,然后 $4 \rightarrow 0$(因为 $(4+1) \bmod 5 = 0$),所以 Rear = 0,存有三个元素。移除两次同样地移动 Front:$3 \rightarrow 4$,然后 $4 \rightarrow 0$,剩下 Front = 0 和一个元素。回绕正是它的意义所在:在线性数组队列中,指针一路走到末端,前面腾出的空间即使队列已空也被浪费掉。记住队列在 Front 端移除、在 Rear 端加入 - 而栈的两端共用一个指针。

探索

Implementing ADTs with arrays

FIFO

A queue is first-in-first-out — enqueue at the back, dequeue from the front.

词汇表 训练
英文 中文 拼音
array 数组 shù zǔ
overflow 溢出 yì chū
underflow 下溢 xià yì
circular array 循环数组 xún huán shù zǔ
free list 空闲列表 kòng xián liè biǎo
10.4

考试技巧

  • 选择正确的数据结构并为它辩护(一个记录用于混合字段,一个 2-D 数组用于网格)。
  • 知道如何用一个数组和指针实现一个栈、队列和链表(top;front/rear;next)。
  • 区分一个 ADT(它的行为)和它的实现(数组加指针)。

本主题的互动课程

逐步学习,并即时检测练习。

A-Level 计算机科学历年真题

A-Level 计算机科学的更多主题

登录或创建账号

IGCSE, A-Level & AP