1.2数据结构 1.2.1数据结构的定义 数据结构(data structure))是指相互之间存在一种或多种特定关系的数据元素的集 合,即数据的组织形式。 数据结构作为计算机的一门学科,主要研究和讨论以下三个方面: (1)数据集合中个数据元素之间所固有的逻辑关系,即数据的逻辑结构: (②)在对数据元素进行处理时,各数据元素在计算机中的存储关系,即数据的存储结构: (3)对各种数据结构进行的运算。 讨论以上问题的目的是为了提高数据处理的效率,所谓提高数据处理的效率有两个方 面: (1)提高数据处理的速度: (2)尽量节省在数据处理过程中所占用的计算机存储空间。 数据(d ta/: 是对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并 被计算机程序处理的符号的总称。 数据元素(data element):是数据的基本单位,在计算机程序中通常作为一个整体进 行考虑和处理。 数据对象(data ob iect):是性质相同的数据元素的集合,是数据的一个子集 在一般情况下,在具有相同特征的数据元素集合中,各个数据元素之间存在有某种关系 (即连续),这种关系反映了该集合中的数据元素所固有的 一种结构。在数据处理领域中,通 常把数据元素之间这种固有的关系简单地用前后件关系(或直接前驱与直接后继关系)来描 述。 前后件关系是数据元素之间的一个基本关系,但前后件关系所表示的实际意义随具体对 象的不同而不同 来说,数据元素之间的任何关系都可以用前后件关系来描述。 数据 逻辑结 数据结构是指反映数据元素之间的关系的数据元素集合的表示。更通俗地说,数据结构 是指带有结构的数据元素的集合。所谓结构实际上就是指数据元素之间的前后件关系。 一个数据结构应包含以下两方面信息: (1)表示数据元素的信息: (②)表示各数据元素之间的前后件关系。 2、数据的存储结构 数据的逻辑结构在计算机存储空间中的存放形式称为数据的存储结构(也称为数据的物 理结构) 1.2.2数据结构的图形表示 数据结构除了用二元关系表示外,还可以直观地用图形表示, 在数据结构的图形表示中,对于数据集合D中的每一个数据元素用中间标有元素值的方 框表示,一般称之为数据结点,并简称为结点:为了进一步表示各数据元素之间的前后件关 系,对于关系R中的每一个二元组,用一条有向线段从前件结点指向后件结点。 在数据结构中,没有前件的结点称为根结点:没有后件的结点称为终端结点(也称为叶子 6
6 1.2 数据结构 1.2.1 数据结构的定义 数据结构(data structure)是指相互之间存在一种或多种特定关系的数据元素的集 合,即数据的组织形式。 数据结构作为计算机的一门学科,主要研究和讨论以下三个方面: (l)数据集合中个数据元素之间所固有的逻辑关系,即数据的逻辑结构; (2)在对数据元素进行处理时,各数据元素在计算机中的存储关系,即数据的存储结构; (3)对各种数据结构进行的运算。 讨论以上问题的目的是为了提高数据处理的效率,所谓提高数据处理的效率有两个方 面: (l)提高数据处理的速度; (2)尽量节省在数据处理过程中所占用的计算机存储空间。 数据(data):是对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并 被计算机程序处理的符号的总称。 数据元素(data element):是数据的基本单位,在计算机程序中通常作为一个整体进 行考虑和处理。 数据对象(data object):是性质相同的数据元素的集合,是数据的一个子集。 在一般情况下,在具有相同特征的数据元素集合中,各个数据元素之间存在有某种关系 (即连续),这种关系反映了该集合中的数据元素所固有的一种结构。在数据处理领域中,通 常把数据元素之间这种固有的关系简单地用前后件关系(或直接前驱与直接后继关系)来描 述。 前后件关系是数据元素之间的一个基本关系,但前后件关系所表示的实际意义随具体对 象的不同而不同。一般来说,数据元素之间的任何关系都可以用前后件关系来描述。 1、 数据的逻辑结构 数据结构是指反映数据元素之间的关系的数据元素集合的表示。更通俗地说,数据结构 是指带有结构的数据元素的集合。所谓结构实际上就是指数据元素之间的前后件关系。 一个数据结构应包含以下两方面信息: (1) 表示数据元素的信息; (2)表示各数据元素之间的前后件关系。 2、数据的存储结构 数据的逻辑结构在计算机存储空间中的存放形式称为数据的存储结构(也称为数据的物 理结构) 1.2.2 数据结构的图形表示 数据结构除了用二元关系表示外,还可以直观地用图形表示。 在数据结构的图形表示中,对于数据集合 D 中的每一个数据元素用中间标有元素值的方 框表示,一般称之为数据结点,并简称为结点;为了进一步表示各数据元素之间的前后件关 系,对于关系 R 中的每一个二元组,用一条有向线段从前件结点指向后件结点。 在数据结构中,没有前件的结点称为根结点;没有后件的结点称为终端结点(也称为叶子
结点)。 一个数据结构中的结点可能是在动态变化的。根据需要或在处理过程中,可以在一个数 据结构中增加 个新结点(称为插入运算 也可以 据结枸中的某个结点(称为删除 算)。插入与删除是对数据结构的两种基本运算。除此之外,对数据结构的运算还有查找 分类、合并、分解、复制和修改等。 1.2.3线性结构与非线性结构 如果在一个数据结构中一个数据元素都没有,则称该数据结构为空的数据结构。在一个 数据结构中有一个或者多个数据元素,则称该数据结构为非空数据结构。根据数据结构中各 数据元素之间前后件关系的复杂程度, 般将数据结构分为两大类型:线性结构与非线性结 构。 非空数据结构满足: (1)有且只有一个根结点: (2)每一个结点最多有一个前件,也最多有一个后件。 则称该数据结构为线性结构。线性结构又称为线性表 。一个线性表是个数据元素的有 限序列。至于 个元素的 具体 在不同的情况下各不相同 也可以是一页书,甚至其他更复杂的信息。如果一个数据结构不是线性结构,称之为非线 结构。线性结构与非线性结构都可以是空的数据结构。对于空的数据结构,如果对该数据结 构的运算是按线性结构的规则来处理的,则属于线性结构:否则属于非线性结构。 1.3线性表及顺序存储结构 13.1线性表的定义 线性表是n(n≥0)个元素构成的有限序列(a, da, .,a)。表中的每一个数据元素,除 了第一个外,有且只有一个前件,除了最后一个外,有且只有一个后件。即线性表是一个空 表,或可以表示为 其中a:(i=1,2,.,n)是属于数据对象的元素,通常也称其为线性表中的一个结点 其由 ,每个元素可以简单到是一个字母或是 一个数据 ,也可能是比较复杂的由多个数振 项组成的。在复杂的线性表中,由若干数据项组成的数据元素称为记录(r©cord),而由多 记录构成的线性表又称为文件(fil)。在非空表中的每个数据元素都有一个确定的位置,如 a是第一个元素,a,是最后一个数据元素,a是第i个数据元素,称i为数据元素在线性 表中的位序。 非空线性表有如下一些结构特征: ()有且只有一个根结点,它无前件: (2)有且只有一个终端结点a,它无后件: (3)除根结点与终端结点外,其他所有结点有且只有一个前件,也有且只有一个后件。 线性表中结点的个数n称为线性表的长度。当n=0时称为空表
7 结点)。 一个数据结构中的结点可能是在动态变化的。根据需要或在处理过程中,可以在一个数 据结构中增加一个新结点(称为插入运算),也可以删除数据结构中的某个结点(称为删除运 算)。插入与删除是对数据结构的两种基本运算。除此之外,对数据结构的运算还有查找、 分类、合并、分解、复制和修改等。 1.2.3 线性结构与非线性结构 如果在一个数据结构中一个数据元素都没有,则称该数据结构为空的数据结构。在一个 数据结构中有一个或者多个数据元素,则称该数据结构为非空数据结构。根据数据结构中各 数据元素之间前后件关系的复杂程度,一般将数据结构分为两大类型:线性结构与非线性结 构。 非空数据结构满足: (l)有且只有一个根结点; (2)每一个结点最多有一个前件,也最多有一个后件。 则称该数据结构为线性结构。线性结构又称为线性表。一个线性表是 n 个数据元素的有 限序列。至于每个元素的具体含义,在不同的情况下各不相同,它可以是一个数或一个符号, 也可以是一页书,甚至其他更复杂的信息。如果一个数据结构不是线性结构,称之为非线性 结构。线性结构与非线性结构都可以是空的数据结构。对于空的数据结构,如果对该数据结 构的运算是按线性结构的规则来处理的,则属于线性结构;否则属于非线性结构。 1.3 线性表及顺序存储结构 1.3.1 线性表的定义 线性表是 n(n≥0)个元素构成的有限序列(a1,a2,.,an)。表中的每一个数据元素,除 了第一个外,有且只有一个前件,除了最后一个外,有且只有一个后件。即线性表是一个空 表,或可以表示为 (a1,a2,.,an) 其中 ai(i=1,2,.,n)是属于数据对象的元素,通常也称其为线性表中的一个结点。 其中,每个元素可以简单到是一个字母或是一个数据,也可能是比较复杂的由多个数据 项组成的。在复杂的线性表中,由若干数据项组成的数据元素称为记录(record),而由多个 记录构成的线性表又称为文件(file)。在非空表中的每个数据元素都有一个确定的位置,如 a1 是第一个元素,an 是最后一个数据元素,ai 是第 i 个数据元素,称 i 为数据元素 ai 在线性 表中的位序。 非空线性表有如下一些结构特征: (1) 有且只有一个根结点 a1,它无前件; (2) 有且只有一个终端结点 an,它无后件; (3) 除根结点与终端结点外,其他所有结点有且只有一个前件,也有且只有一个后件。 线性表中结点的个数 n 称为线性表的长度。当 n=0 时称为空表
1.3.2线性表的顺序存储结构 线性表的顺序表指的是用一组地址连续的存储单元依次存储线性表的数据元素 线性表的顺序存储结构具备如下两个基本特征: (1)线性表中的所有元素所古的存储空间是连续的: (2)线性表中各数据元素在存储空间中是按逻辑顺序依次存放的。 假设线性表的每个元素需要占用k个存储单元,并以所占的存储位置ADR(a)和第 i个数据元素的存储位置ADR(a:)之间满足下列关系: ADR(a:.)=ADR(a.)+k 线性表第i个元素ai的存储位置为 ADR(a)=ADR(a)+(i-1)xk 式中ADR(a:)是线性表的第一个数据元素a的存储位置,通常称做线性表的起始位 置或基址」 线性表的这种表示称做线性表的顺序存储结构或顺序映像,这种存储结构的线性表 为顺序表。表中有 元素的存储位置都和线性表的起始位置相差一个和数据元素在线 性表中的位序成正比例的常数。知图1-1所示。 占K个字节 存储地址 a l 占K个字节 ADR (al) ADR (al)+k 占K个字节 ADR (al)+(i-1) an 占K个字节 ADR(a1)+(n-1) 图1-1顺序表 由此只要确定了存储线性表的起始位置,线性表中任一数据元素都可以随机存取,所以 线性表的顺序存储结构是一种随机存取的存储结构。 在程序设计语言中,通常定义一个一维数组来表示线性表的顺序存储空间。在用一维数 组存放线性表时,该一维数组的长度通常要定义得比线性表的实际长度大一些,以便对线性 表进行各种运算,特别是插入运算 1.3.3顺序表的插入运算 线性表的插入运算是指在表的第1(1≤i≤+1)个位置上,插入一个新结点x,使长度为 n的线性表 (a,a-a,.ya 变成长度为n+1的线性表
8 1.3.2 线性表的顺序存储结构 线性表的顺序表指的是用一组地址连续的存储单元依次存储线性表的数据元素。 线性表的顺序存储结构具备如下两个基本特征: (l)线性表中的所有元素所占的存储空间是连续的; (2)线性表中各数据元素在存储空间中是按逻辑顺序依次存放的。 假设线性表的每个元素需要占用 k 个存储单元,并以所占的存储位置 ADR(ai+1)和第 i 个数据元素的存储位置 ADR(ai)之间满足下列关系: ADR(ai+1)=ADR(ai)+k 线性表第 i 个元素 ai 的存储位置为 ADR(ai)=ADR(a1)+(i-1)×k 式中 ADR(ai)是线性表的第一个数据元素 a1 的存储位置,通常称做线性表的起始位 置或基址。 线性表的这种表示称做线性表的顺序存储结构或顺序映像,这种存储结构的线性表 为顺序表。表中每一个元素的存储位置都和线性表的起始位置相差一个和数据元素在线 性表中的位序成正比例的常数。如图 1-1 所示。 图 1-1 顺序表 由此只要确定了存储线性表的起始位置,线性表中任一数据元素都可以随机存取,所以 线性表的顺序存储结构是一种随机存取的存储结构。 在程序设计语言中,通常定义一个一维数组来表示线性表的顺序存储空间。在用一维数 组存放线性表时,该一维数组的长度通常要定义得比线性表的实际长度大一些,以便对线性 表进行各种运算,特别是插入运算。 1.3.3 顺序表的插入运算 线性表的插入运算是指在表的第 i(1≤i≤n+l)个位置上,插入一个新结点 x,使长度为 n 的线性表 (a1,.,ai-1,ai,.,an) 变成长度为 n+1 的线性表 存储地址 ADR(a1) ADR(a1)+k ADR(a1)+(i-1) k ADR(a1)+(n-1) k a 1 a 2 a i a n . . . . 占 K 个字节 占 K 个字节 占 K 个字节 占 K 个字节 .
a,a,。a,++,a) 现在分析算法的复杂度。这里的问题规模是表的长度,设它的值为。该算法的时间主 要花费在循环纠 点后移 句上 该语句的执行次数(即移动结点的次数)是一i+1。由此可 出,所需移动结点的次数不仅依赖于表的长度,而且还与插入位置有关 当=+1时,由于循环变量的终值大于初值,结点后移语句将不进行:这是最好情况, 其时间复杂度0(1): 当=1时,结点后移语句,将循环执行n次,需移动表中所有结点,这是最坏情况,其 时间复杂度为00 由于插入可能在表中任何位置上进行,因此需分析算法的平均复杂度 在长度为n的线性表中第i个位置上插入一个结点,令Eis(n)表示移动结点的 期望值(即移动的平均次数),则在第个位置上插入一个结点的移动次数为-i+l。故不失 般性,假设在表中任何位置(1≤i≤+1)上插入结点的机会是均等的,则 因此,在等插 pn+1=l/(a+) 的情况 就是说,在顺序表上做插入运算,平均要移动表 一半的结点。当表长n较大时,算法的效率相当低。虽然Eis(n)中n的的系数较小 但就数量级而言,它仍然是线性级的。因此算法的平均时间复杂度为O()。 1.3.4顺序表的删除运算 线性表的删除运算是指将表的第i(1≤i≤)个结点删除,使长度为n的线性表: .,a) 变成长度为n1的线性表 (ai 该算法的时间分析与插入算法相似,结点的移动次数也是由表长和位置i决定。若 =m,则由于循环变量的初值大于终值,前移语句将不执行,无需移动结点:若=1,则前 移语句将循环执行一1次,需移动表中除开始结点外的所有结点。这两种情况下算法的时 与插入算法相似。在长度为的线性表中删除一个结点,令 Ede()表示所需移动结点的平均次数,别除表中第i个结点的移动次数为m-i,故式子中, pi表示删除表中第ⅰ个结点的概率。在等概率的假设下, p1=p2=p3=+=pn=1/n 由此可得:即在顺序表上做删除运算,平均要移动表中约一半的结点,平均时间复杂度 也是0() 1.4栈和队列 1.4.1栈及其基本运算 1、什么是栈 栈实际也是线性表,只不过是一种特殊的线性表。栈(Sta©k)是只能在表的一端进行插 入和删除运算配线性表,通常称插入、删除的这一端为栈顶(TOp),另一端为栈底(Bot tom)。 当表中没有元素时称为空栈(栈顶元素总是后被插入的元素,从而也是最先被除的元素 9
9 (a1,.,ai-1,x,ai,.,an) 现在分析算法的复杂度。这里的问题规模是表的长度,设它的值为 n。该算法的时间主 要花费在循环结点后移语句上,该语句的执行次数(即移动结点的次数)是 n-i+1。由此可看 出,所需移动结点的次数不仅依赖于表的长度,而且还与插入位置有关。 当 i=n+1 时,由于循环变量的终值大于初值,结点后移语句将不进行;这是最好情况, 其时间复杂度 O(1); 当 i=1 时,结点后移语句,将循环执行 n 次,需移动表中所有结点,这是最坏情况,其 时间复杂度为 O(n)。 由于插入可能在表中任何位置上进行,因此需分析算法的平均复杂度。 在长度为 n 的线性表中第 i 个位置上插入一个结点,令 Eis ( n )表示移动结点的 期望值(即移动的平均次数),则在第 i 个位置上插入一个结点的移动次数为 n-i+1。故不失 一般性,假设在表中任何位置(1≤i≤n+1)上插入结点的机会是均等的,则 p1=p2=p3=.=pn+1=1/(n+1) 因此,在等概率插入的情况下, 也就是说,在顺序表上做插入运算,平均要移动表上 一半的结点。当表长 n 较大时,算法的效率相当低。虽然 Eis ( n )中 n 的的系数较小, 但就数量级而言,它仍然是线性级的。因此算法的平均时间复杂度为 O(n)。 1.3.4 顺序表的删除运算 线性表的删除运算是指将表的第 i(1≤i≤n)个结点删除,使长度为 n 的线性表: (a1,.,ai-1,ai,ai+1,.,an) 变成长度为 n-l 的线性表 (a1,.,ai-1,ai+1,.,an) 该算法的时间分析与插入算法相似,结点的移动次数也是由表长 n 和位置 i 决定。若 i=n,则由于循环变量的初值大于终值,前移语句将不执行,无需移动结点;若 i=1,则前 移语句将循环执行 n 一 1 次,需移动表中除开始结点外的所有结点。这两种情况下算法的时 间复杂度分别为 O(1)和 O(n)。 删除算法的平均性能分析与插入算法相似。在长度为 n 的线性表中删除一个结点,令 Ede(n)表示所需移动结点的平均次数,删除表中第 i 个结点的移动次数为 n-i,故式子中, pi 表示删除表中第 i 个结点的概率。在等概率的假设下, p1=p2=p3=.=pn=1/n 由此可得:即在顺序表上做删除运算,平均要移动表中约一半的结点,平均时间复杂度 也是 O(n)。 1.4 栈和队列 1.4.1 栈及其基本运算 1、 什么是栈 栈实际也是线性表,只不过是一种特殊的线性表。栈(Stack)是只能在表的一端进行插 入和删除运算配线性表,通常称插入、删除的这一端为栈顶(Top),另一端为栈底(Bottom)。 当表中没有元素时称为空栈(栈顶元素总是后被插入的元素,从而也是最先被删除的元素;
找底元素总是最先被插入的元素,从而也是最后才能被侧除的元素」 假设栈S=(a,a 小,则a称为栈底元素为栈顶元素。栈中元素按a a,a的次序进栈,退栈的第 一个元素应为栈顶元素。换句话说,栈的修政是按后进先 出的原则进行的。因此,栈称为先进后出表(FILO,First In Last Out),或“后进先出 表LIfO,Last In First0ut),如图1-2所示。 栈顶 top an a2 栈底bottom一 ai 图1-2先进后出表 2、栈的顺序存储及其运算 (1)入栈运算: 入栈运算是指在栈顶位置插入一个新元素。首先将栈顶指针加一(即t0 加1),然后将元素插入到栈顶指针指向的位置。当栈顶指针已经指向存储空间的最后一个 位置时,说明栈空间己满,不可能再进行入栈操作。这种情况称为栈“上溢”错误。 (2)退栈运算:退栈是指取出栈顶元素并赋给一个指定的变量。首先将栈顶元素(栈顶指 针指向的元素)赋给一个指定的变量,然后将栈顶指针减一(即to印减1)。当栈顶指针为。 时,说明栈空 ,不可进行退栈操作。这种情况称为栈的“下溢”错误 (④读栈顶元素:读栈项元素是指将栈项元素赋给一个指定的变量。这个运算不剧除栈 顶元素,只是将它赋给一个变量,因此栈顶指针不会改变。当栈顶指针为0时,说 明栈空,读不到栈顶元素。 1.4.2队列及其基本运算 1、什么是队列 队列(uu©)是只允许在一端刑除,在另一端插入的顺序表,允许除的一端叫做队头 (front),允许插入的一端叫微队尾(rear),当队列中没有元素时称为空队列。在空队列中 依次加入元素a,a2,a之后,a是队头元素,a是队尾元素。显然退出队列的次序也 只能是,a,.,a也就是说队列的修政是依先进先出的原则进行的。因此队列亦称作先 进先出(FIFO,First In First Out)的线性表,或后进后出LILO,Last In Last Out) 的线性表。往队列队尾插入一个元素称为入队运算,从队列的排头删除一个元素称为退队运 算,如图1-3所示
10 栈底元素总是最先被插入的元素,从而也是最后才能被删除的元素。 假设栈 S=(al,a2,a3,.,an),则 a1 称为栈底元素 an 为栈顶元素。栈中元素按 a1,a2, a3,.,an 的次序进栈,退栈的第一个元素应为栈顶元素。换句话说,栈的修改是按后进先 出的原则进行的。因此,栈称为先进后出表(FILO,First In Last Out),或“后进先出” 表(LIFO,Last In First Out),如图 1-2 所示。 图 1-2 先进后出表 2、 栈的顺序存储及其运算 (l)入栈运算:入栈运算是指在栈顶位置插入一个新元素。首先将栈顶指针加一(即 top 加 1),然后将元素插入到栈顶指针指向的位置。当栈顶指针已经指向存储空间的最后一个 位置时,说明栈空间已满,不可能再进行入栈操作。这种情况称为栈“上溢”错误。 (2)退栈运算:退栈是指取出栈顶元素并赋给一个指定的变量。首先将栈顶元素(栈顶指 针指向的元素)赋给一个指定的变量,然后将栈顶指针减一(即 top 减 1)。当栈顶指针为。 时,说明栈空,不可进行退栈操作。这种情况称为栈的“下溢”错误。 (4) 读栈顶元素:读栈顶元素是指将栈顶元素赋给一个指定的变量。这个运算不删除栈 顶元素,只是将它赋给一个变量,因此栈顶指针不会改变。当栈顶指针为 0 时,说 明栈空,读不到栈顶元素。 1.4.2 队列及其基本运算 1、 什么是队列 队列(queue)是只允许在一端删除,在另一端插入的顺序表,允许删除的一端叫做队头 (front),允许插入的一端叫做队尾(rear),当队列中没有元素时称为空队列。在空队列中 依次加入元素 a1,a2,.,an 之后,a1 是队头元素,an 是队尾元素。显然退出队列的次序也 只能是 a1,a2,.,an 也就是说队列的修改是依先进先出的原则进行的。因此队列亦称作先 进先出(FIFO,First In First Out)的线性表,或后进后出(LILO,Last In Last Out) 的线性表。往队列队尾插入一个元素称为入队运算,从队列的排头删除一个元素称为退队运 算,如图 1-3 所示。 栈顶 栈底 a n a 2 a i . top bottom