计算机二级C语言公共基础.docx
《计算机二级C语言公共基础.docx》由会员分享,可在线阅读,更多相关《计算机二级C语言公共基础.docx(45页珍藏版)》请在冰豆网上搜索。
计算机二级C语言公共基础
第一章数据结构与算法
第一节算法
一、基本概念
一个程序应包括以下两个方面的内容:
(1)对数据的描述。
在程序中要指定数据的类型和数据的组织形式,即数据结构(datastructure)
(2)对操作的描述。
即操作步骤,也就是算法(algorithm)。
数据是对操作的对象,操作的目的是对数据进行加工处理,以得到期望的结果。
也就是指一组有穷的指令集,是解题方案的准确而完整的描述。
1、算法的特征:
(1)确定性。
一个算法中的每一个步骤都必须有明确的定义,不允许有多义性和模棱两可的解释。
(2)可行性
算法中描述的操作都可以通过已经实现的基本运算操作,执行有限次来实现。
(3)有穷性
一个算法必须能存有限的时间内执行完,即算法必须能够终止。
比如说,如果一个算法需要执行千万年,那其显然失去了使用的价值。
(4)拥有足够的情报
我们要使所设计的算法有效,就必须拥有足够的情报。
2、算法的组成要素
(1)对数据对象的运算和操作
①算术运算:
主要包括“+”、“—”、“*”、“/”等运算;
②逻辑运算:
主要包括“与”、“或”、“非”等运算;
③关系运算:
主要包括“>”、“<”、“!
=”等运算;
④数据传输:
主要包括赋值、输入、输出等操作;
(2)算法的控制结构
一个算法所实现的功能不仅与其选用的操作有关,而且还与各操作之间的执行顺序有关。
算法中各操作之间的执行顺序称为算法的控制结构。
算法的基本结构主要分为顺序、选择、循环三种。
3、算法设计的基本方法
(1)列举法
列举法是指对待解决的问题,列举所有可能的情况,并用问题中给定的条件来检验哪些是必须的,哪些是不需要的。
其特点是原理比较简单,但当列举的可能情况较多时,执行列举算法的工作量将会很大。
(2)归纳法
归纳法是从特殊到一般的抽象过程。
通过分析少量的特殊情况,找出一般的关系。
归纳法比列举法更能反映问题的本质,并可以解决无限列举量的情况。
但是归纳法不容实现。
(3)递推
递推实际上也属于归纳法。
不过它是指从已知的初始条件出发,逐次推出所要求的各中间结构的最后结果。
(4)递归
递归分为直接递归与间接递归两种。
如果一个算法A显示调用自己则称为直接递归。
如果算法A调用另一个算法B,而算法B又调用算法A,则称为间接递归调用。
(5)减半递推技术
所谓减半递推技术是指把规模较大,较复杂的问题,分成几个小规模,较简单的问题。
(6)回溯法
对需要解决的问题进行一条线索逐步试探,如果试探成功,就找到了解决的方法;如果试探失败,就逐步回退,然后换另一条线索进行试探。
二、算法的复杂度
算法的复杂度包括空间复杂度和时间复杂度
1、算法的空间复杂度
算法的空间复杂度是对算法所需存储空间的度量,是指执行这个算法所需要的内存空间。
一个算法的空间复杂度,一般是指执行这个算法所需要的内存空间。
一个算法所占用的存储空间包括算法所占的空间、输入的初始数据所占的存储空间,以及算法执行过程中所需要的额外空间。
在许多世纪问题中,为了减少算法所占的存储空间,通常采用压缩存储技术,以便尽量减少不必要额外空间。
2、算法的时间复杂度
算法的时间效率也称为时间复杂性或时间复杂度,它是算法运行时间的相对度量,一个算法的运行时间是指在计算机上从算法开始运行到结束所花费的时间,它与计算机系统的硬件、软件及问题的规模等因素有关。
由于这些因素将影响算法在计算机中的运行时间,也容易掩盖算法本身的优劣,因此,我们用“语句频度”和算法的“渐进时间复杂度”这两个与计算机软件和硬件无关的量来讨论算法的时间复杂度。
语句频度指的是算法中每条语句的执行次数与其运行一次所需时间的乘积。
当算法转化为程序之后,每条语句执行一次所需的时间取决于计算机的指令性能、速度及编译所产生的代码质量,这是很难确定的。
假设每条语句执行一次所需的时间均为单位时间,则语句频度就是该语句重复执行的次数。
因此,一个算法所消耗的时间就是该算法中所有语句频度之和。
如果算法的语句频度为T(n),有某个辅助函数F(n),使得当问题规模n趋于无穷大时,则有
=常数≠0
则称函数T(n)与F(n)是同阶的,或者说,T(n)和F(n)只相差一个常数倍,其数量级是相同的,记做:
O(F(n))=T(n)
将O(F(n))称做算法的渐进时间复杂度,简称为算法的时间复杂度或时间复杂性。
实际上,时间复杂度就是语句频度的数量级表示。
它表示随问题规模n的增大,算法执行时间的增长率和F(n)的增长率是相同的。
在实际分析一个算法的时间复杂度的时候,其所执行的基本运算次数可能与特定的输入有关,此时,我们一般采用下面两个方法来分析算法的工作量。
(1)平均性态
在这种方法中,使用各处特定输入下的基本运算次数的加权平均值来度量算法的工作量。
设X是所有可能输入中的某个特定输入,P(x)是X出现的概率(即输入为X的概率),t(x)是算法输入为X时所执行的基本运算次数,则算法的平均性态定义为:
A(n)=∑P(x)t(x)
X∈Dn
其中Dn表示当规模为n时,算法执行时所有可能输入的集合。
这个式子中的t(x)可以通过分析算法来加以确定;而P(x)必须由经验或用算法中有关的一些特定信息来确定,通常是不能解析地加以计算的
(2)最坏情况复杂性
这种方法是在规模为n时,求出算法所执行的基本运算的最大次数。
它定义为
W(n)=max{t(x)}
X∈Dn
显然,W(n)的计算要比A(n)的计算方便得多。
由于W(n)实际上是给了算法工作量的一个二界,因此,它比A(n)更具有实际价值。
第二节数据结构的基本概念
“数据结构”是计算机学科中重要的基础课程。
在计算机科学领域中,尤其涉及系统软件和应用软件的设计和设计中,都肯定要设计各种数据结构。
学校“数据结构”既为进一步学校其他计算机软件课程提供了必要的准备知识,同时又有助于提高软件设计和程序编制水平。
一、数据结构定义
数据结构是整个计算机科学与技术领域上广泛被使用的术语。
它用来反映一个数据的内部构成,即一个数据由哪些成分构成,以什么方式构成,呈现什么样的结构。
数据结构分为逻辑上的数据结构和物理上的数据结构。
逻辑上的数据结构反映成分数据间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。
所以,简单的说,数据结构是数据存在的形式。
或者可以这样说:
数据结构研究的是数据逻辑结构和物理结构以及它们之间的相互关系,并对这样结构定义相应的运算,而且确保经过这些运算后所得到的新结构仍然是原来的结构类型。
因此,数据结构是信息的一种组织方式,目的是为了提高算法的效率。
它通常与一组算法的集合相对应,通过这组算法集合可以对数据结构中的数据进行某种操作。
作为一门学科,数据结构主要研究数据的各种逻辑结构和存储结构以及对数据的各种操作。
因此,数据结构主要研究三个方面的内容:
1数据的逻辑结构
2数据的物理结构
3对数据允许进行的操作(或算法),也称数据处理或数据运算。
基本名词术语:
1、数据
数据(Data)是人们利用文字符号、数字符号以及其他一些规定的符号对现实世界的事物及其活动所做的描述。
因此,可以把一本小说、一片论文、一张图标甚至一个句子、一个单词、一个算式以至一个数值、一个字符等都可以当成的数据。
在计算机领域,人们把能够被计算机加工的对象,或者说能够被计算机输入、存储、处理和输出的一切信息都叫做数据。
2、数据元素
数据元素(DataElement)是一个数据整体中相对独立的单位。
如对于一个文件来说,每个记录就是它的数据元素;对于一个字符串来说,每个字符就是它的数据元素;对于一个数组来说,每个数组元素就是它的数据元素。
数据和数据元素的相对而言的。
如对于一个数据库中的记录来说,它相对于所在的数据表文件被认为是数据元素,而它相对于其中的每个属性又被认为是数据。
3、数据记录
数据记录(DataRecord)简称记录,是数据处理领域组织数据的基本单位。
它有是由更小的单位——数据项(Item)所组成。
一个数据记录一般包括或若干个固定的数据项(当然每一个数据项还可以是记录的形式)。
4、数据对象
数据对象(DataObject)是指性质相同的数据元素的集合,是数据的一个子集。
数据对象可以是有限的,也可以是无限的。
5、数据结构
前面已经介绍过数据结构(DataStructure)的概念,这里,分别给出它的简单定义和二元组定义。
(1)简单定义
数据结构是相互之间存在一种或多种特定关系的数据元素的集合。
(2)二元组定义
为了更确切地描述数据结构,通常采用二元组表示:
G=(D,R)
G是一种数据的逻辑结构。
它由数据元素的集合D和D上的二元关系的集合R所组成。
其中
D={di|1≤i≤n,n≥0}
R={rj|1≤i≤m,m≥0}
di表示第i个数据元素。
N为G中数据元素的个数。
若n=0,则D是一个空集,因而也就无结构可言,是数据结构中的一种特殊情况。
Rj表示第j个关系,m为R上关系的个数。
6、逻辑结构和物理结构
被计算机加工的数据元素不想互相孤立的,它们彼此间一般存在着某些逻辑上的关系,这些联系在对数据进行存储和加工时反映出来。
数据结构主要指逻辑结构和物理结构。
(1)数据的逻辑结构
数据的逻辑结构只抽象地反映数据元素的逻辑关系,而不管其在计算机中的存储表示方式。
数据的逻辑结构分为线性结构和非线性结构。
若各元素之间的逻辑关系可言用一个线性序列简单地表示出来,则称为线性结构,否则称为非线性结构。
线性表是典型的线性结构,而树、图等都是非线性结构。
如果分得更细的话,数据的逻辑结构通常分为以下四类基本结构。
①集合结构中的数据元素除了同属于一种类型外,别无其他关系
②线性结构结构中的数据元素之间存在一对一的关系
③树形结构结构中的数据元素之间存在一对多的关系
④图状结构或网状结构结构中的数据元素之间存在多对多的关系。
(2)数据的物理结构
数据的物理结构是逻辑结构在计算机存储器里的实现。
为全面地表示一个逻辑结构,它在存储器中的存储应包括数据元素自身值的表示和数据元素之间关系的表示两个方面。
7、数据处理
数据处理(DataProcessing)也称数据运算,是指对数据进行查找、插入、删除、合并、排序、统计、简单计算等操作过程。
数据运算是定义在数据的逻辑结构上的,但运算的具体实现要在存储结构上进行。
数据的各种逻辑结构有相应的各种运算,每种逻辑结构都有一个运算的集合。
常用的运算有检索、插入、删除、更新、排序等。
8、数据存储方式
有很多种不同的方式可以实现数据的逻辑结构在计算机存储中的存储。
下面将介绍两种最主要的存储结构——顺序存储和链式存储。
(1)顺序存储结构
顺序存储结构主要应用于线性的数据结构,它把逻辑上相邻的数据元素存储在物理上相邻的存储单元里。
节点之间的关系由存储单元的邻接关系实现。
顺序存储结构主要特点是:
①数据节点中只有自身信息域(即只存储数据的值),没有连接信息域,因此存储密度大,存储空间利用率高。
②可以通过计算直接确定数据结构中第i个数据节点的存储地址Li,计算机公式为Li=L0+(i-1)*m,其中L0为第一个节点的存储地址,m为每个数据节点所占用的存储单元个数;
③插入、删除运算不便,会引起大量数据节点的移动。
(2)链式存储结构
链式存储结构就是在每个节点中至少包括一个指针域,用指针来表现数据元素之间逻辑上的关系。
这种存储结构把人们从计算机存储单元的连续性限制中解放出来。
它可以把逻辑上相邻的两个元素存放在物理上不相邻的存储单元中;还可以在线性编址的计算机存储器中表示数据节点之间的非线性联系。
链式存储结构的主要特点是:
①数据节点中除自身信息外,还有表示连接信息的指针域(即不仅仅存储数据的值还同时存储数据的联系),因此比顺序存储结构的存储密度小,存储空间利用率低。
②逻辑上相邻的节点物理上不必邻接,可用于线性表、树、图等多种逻辑结构的存储表示;
③插入、删除操作灵活方便,不必移动数据节点,只要改变数据节点中的指针即可。
除了上述两种主要存储方式外,索引存储、散列存储也是在线性表和集合的存储表示中常用的两种重要存储方式。
9、数据类型
数据类型(DataType)是指在一种程序设计语言中变量所具有的数据种类。
数据类型是某一种语言中具体实现数据结构必须掌握的知识。
第三节线性表
一、线性表的定义
线性表(LinearList)是有n(n≥0)个数据元素(节点)a1,a2,ai···,an组成的有限序列。
通常,我们把非空的线性表(n>0)记为:
A=(a1,a2,a3····,an)
其中,
1A是线性表的表名。
一个线性表可以用一个标识符来命名。
2ai(1≤i≤n)是表中的数据元素。
其具体含义在不同的情况是不相同的,它可以是
一个数、一个字符、一个字符串,也可以是一条记录,甚至还可以是更为复杂的数据对象。
数据元素的类型可以是高级语言所提供的简单类型或者用户自定义的任何类型。
本书采用C语言实现,数据元素所具有的类型有整型、实型、字符型、结构体等
③n是线性表中数据元素的个数,也称为线性表的长度。
N=0的线性表称为空表,此时表中不包含任何数据元素。
线性表中数据元素在位置上是有序的。
表中除第一个元素a1外,每个元素有且仅有一个前驱元素,除最后一个元素an外,每个元素有且仅有一个后继元素。
如果ai和ai+1是相邻的具有前后关系的两个元素,则ai称为ai+1的前驱元素,ai+1称为ai的后继元素。
线性表中数据元素之间的逻辑关系就是其相互位置上的邻接关系。
线性表是一种线性结构。
二、线性表的基本运算
线性表上常用的基本运算有一些9中:
1、线性表的初始化:
将线性表设置成一个空表;
2、求表的长度:
求线性表的长度;
3、取出表的元素:
访问线性表中的第i个元素;
4、查找运算:
查找线性表中具有某个特征的数据元素;
5、插入运算:
在线性表中的第i个元素之前或之后插入一个新元素;
6、删除运算:
删除线性表中第i个元素或满足给定条件的第一个元素;
7、排序运算:
将线性表中第i个元素按给定的关键字进行排序;
8、归并运算:
把两个线性表合并为一个线性表;
9、分离运算:
将线性表按某一要求分解成两个或几个线性表;
三、线性表的顺序存储结构
线性表的顺序存储指的是用一组地址连续的存储单元依次存储线性表的数据元素。
线性表的顺序存储结构具有以下两个基本特点:
(1)线性表所有元素所占的存储空间爱是连续的;
(2)线性表中各数据元素在存储空间中是按逻辑顺序依次存放的;
在此,还必须注意一点:
在一个线性结构中插入或删除任何一个节点后,还应该是线性结构,否则,原数据结构不是线性结构。
四、顺序表的插入运算
(1)在顺序表中插入一个新节点x
线性表的插入运算是指在表的第i(1≤i≤n+1)个位置上,插入一个新的结点x,使长度为n的线性表:
(a1,···,ai-1,ai,ai+1,···,an)
变成为长度为n+1的线性表:
(a1,···,a-1,ai,ai+1,···,an)
由于顺序表中结点在计算机中是连续存放的,若在第i个结点之前插入一个新结点x,就必须将表中下标位置为i,i+1,···,n上的结点依次向后移动到i+1,i+2,···,n+1的位置上,空出第i个位置,然后在该位置上插入新结点x。
仅当插入位置i=n+1时,才无须移动结点,直接将x插到表的末尾。
新结点插入后,线性表的长度变成n+1。
在顺序表中插入一个新结点的过程如下:
①检查顺序表的存储空间是否已满,若满则停止插入,退出程序运行;
②将第i~~n个结点之间的所有结点依次向后移动一个位置,空出第i个位置;
③将新结点x插入第i个位置;
④修改线性表的长度,使其加1;
⑤若插入成功,则函数返回值为1,否则函数值返回值为0;
(2)顺序表的删除运算
线性表的删除运算是指将表中第i(1≤i≤n+1)个结点删去,使长度为n的线性表,
(a1,···,ai-1,ai,ai+1,···,an)
变长度为n-1的线性表:
(a1,···,ai-1,ai+1,···,an)
若要删除表中的第i个结点,就必须把表中第i+1个结点到第n个结点之间的所有结点依次向前移动一个位置,以覆盖其前一个位置上的内容,使线性表的长度变成n-1.
在顺序表中删除给定位置的结点的过程如下:
①检查给定结点的删除位置是否正确,若删除位置有错,显示出错信息,退出程序运行;
②把表中第i+1~n个结点之间的所有结点依次向前移动一个位置;
③将线性表的长度减1
④若删除成功,函数返回1,否则函数返回0.
第四节线性链表
一、线性链表概念
在链式存储结构中,存储数据结构的存储空间可以不连续,各数据结点的存储顺序与数据元素之间的逻辑可以不一致,而数据元素之间的逻辑关系是由指针域来确定的。
链式存储方式既可用于线性结构,也可用于表示非线性结构。
一般来说,在线性表的链式存储结构中,各数据结点的存储序号是不连续的,并且各结点在存储空间中的位置关系与逻辑关系也不一致。
对于线性链表,可以从头指针开始,沿各结点的指针扫描到链表中的所有结点。
二、线性链表的逻辑结构
链式存储结构中的每一个数据结点对应于一个存储单元(若干个字节),这种存储单元称为存储结点,简称结点。
在链式存储方式中,要求每个结点由两部分组成:
一部分用于存放数据元素值,称为数据域;另一部分用于存放指针,称为指针域。
其中指针用于指向该结点的前一个或后一个结点,从而可以表示数据元素之间的前后件关系。
三、线性表的基本运算
(1)在线性链表中查找指定元素
在非空线性链表中寻找包含指定元素值x的前一个结点p的基本方法如下:
从头指针指向的结点开始往后沿指针进行扫描,直到后面已没有结点或下一个结点的数据域为x为止。
因此,有这种方法找到的结点p有两种可能:
当线性链表中存在包含元素x的结点时,则找到的p为第一次遇到的包含元素x的前一个结点序号;当线性链表中不存在包含元素的结点时,则找到的p为线性链表中的最后一个结点号。
(2)线性链表的插入
为了在线性链表中插入一个新元素,首先要给该元素分配一个新结点,以便用于存储元素的值。
新结点可以从可利用栈中取得。
然后将存放新元素值的结点连接到线性表中指定的位置。
多个线性链表可以共享栈,从而很方便地实现了存储空间的动态分配。
线性链表在插入过程中不发生数据元素移动的现象,只需要改变有关结点的指针即可。
从而提高插入的效率。
(3)线性链表的删除
为了在线性链表中删除包含指定元素的结点,首先要在线性链表中找到这个结点,然后将要删除结点放回可利用栈。
在线性链表中删除一个元素后,不需要移动表的数据元素,只需改变被删除元素所在结点的前一个结点的指针域即可。
当从线性链表中删除一个元素后,该元素的存储结点就变为空闲,应将该空间结点放回可利用栈。
四、循环链表及其基本运算
循环链表的结构与前面所讨论的线性链表相比,具有以下两个特点:
(1)在循环链表中增加了一个表头结点,其数据为任意或者根据需要来设置,指针域指向线性表的第一个元素的结点,循环链表的头指针指向表头结点。
(2)循环链表中最后一个结点的指针域不是空,而是指向表头结点,即循环链表中所有结点的指针构成了一个环状链。
在循环链表中,只要指出表中任何一个结点的位置,就可以从它出发访问到表中其他所有的结点,而线性单链表做不到这一点。
因此在对循环链表进行插入与删除的操作时,无须对空表和对第一个结点的处理必须单独考虑,是空表与非空表的操作得到了统一,从而克服了线性链表的两个缺点。
H表头结点b1b2···bn
图1为非空循环链表
H表头结点
图2为空循环链表
第五节栈及其基本运算
一、栈的基本概念
栈又称为堆栈,是一种“特殊”的线性表,这种线性表的插入和删除运算指允许在表的一端进行。
允许进行插入和删除运算的这一端称为栈顶,不允许进行插入和删除运算的另一端则称为栈底;向栈中插入一个新元素称为入栈或压栈,从栈中删除一个元素称为出栈或退栈;通常,记录栈顶元素位置的变量称为栈顶指针,处于栈顶元素位置的变量称为栈顶指针,处于栈顶位置的数据元素称为栈顶元素;而不含任何数据元素的栈则称为空栈。
栈是按照“先进后出”或“后进先出”的原则组织数据的,因此,栈也被称为“先进后出”或“后进先出”的线性。
因此栈具有记忆功能。
通常用指针top来指示栈顶的位置,用指针bottom指向栈底。
向栈中插入一个元素称为进栈操作,从栈中删除一个元素称为出栈操作。
栈顶指针top动态反映了栈中元素的变化情况。
下图是站的示意图:
进栈出栈
↓↑
bn
·
·
b1
b2
栈顶top→
栈底botton→
栈的示意图
栈这种数据结构在日常生活中是很常见的。
火车调度站就是一种栈的应用列子。
又如子弹夹也是一种栈的结构,最后压入的子弹总是最先被弹出的,而最先压入的子弹最后才能被弹出,遵循“后进先出”的原则;
二、栈的存储方式
1、栈的顺序存储
在程序设计语言中,用一维数组S(1:
m)作为栈的顺序存储空间,其中m为栈的最大容量,S(bottom)通常为栈底元素(在栈非空的情况下),S(top)为栈顶元素。
Top=0表示栈空;top=m表示栈满。
通常,栈底指针指向栈空间的低地址一端(即数组的起始地址一端)。
2、带链的栈
栈是线性表,也可以采用链式存储结构
三、栈的基本运算
1、入栈运算
进栈运算是指在栈顶位置插入一个新元素。
其过程是:
先将栈顶指针加一(即top加1),然后将新元素放到栈顶指针指向位置。
当栈顶指针已经指向存储空间的最后一个位置时,说明栈空间已满,不能再进栈,这种情况称为栈“上溢”错误。
2、退栈运算
出栈运算是指取出栈顶元素。
其过程是:
先将栈定指针指向的元素赋给一个指定的变量,然后将栈顶指针减1(即top减1)。
当栈顶指针为0时,说明栈空,不能在出栈,这种情况称为栈“下溢”错误。
3、读栈顶元素
读栈顶元素是指将栈顶元素赋给一个指定的变量。
因此,在这个运算中,栈顶指针不好改变。
当栈顶指针为0时,说明栈空,读不到站定元素。
第六节队列及其基本运算
一、队列的基本概念
队列也是一种特殊的线性表,是一种只允许在一端进行插入、而在另一端进行删除的线性表。
允许插入的一端称为队尾,通常用一个称为尾指针(rear)的指针指向队尾元素;允许删除的一端称为对头,通常也用一个对头指针(front)指向队头元素的钱一个位置。
队列是按照“先进先出”的原则组织数组的,因此队列又称为“后进后出”的线性表。
在队列中,队尾指针与队头指针共同反映了队列元素中元素动态变化的情况。
下图为队列示意图。
a
b
c
d
出队←←进队
↑↑
frontrear
队列示意图
二、队列的存储方式
1、队列的顺序存储
与栈类似,在程序设计语言中,用一维数据作为队列的顺序存储空间
2、循环队列
循环队列是一种将顺序队列臆造为一个环状的空间方法,通常将队列存储空间的第一个位置作为队列最后一个位置的下一个位置,从而形成逻辑上的环状空间,供队列循环使用。
循环队列的初始状态为空,即rear=front=0,如下图所示:
A(1:
n)
·
·
A.reat→n
A.fornt→
2
1
循环队列存