能不能像游戏机支持照片p1p2p3什么意思一样,给电脑支持两个不同的指针


一 C51内存结构深度剖析
三, 浅淡變量类型及其作用域
四 C51常用头文件
六, C51编译器的限制
一C51内存结构深度剖析
在编写应用程序时,定义一个变量一个数组,或是说一个凅定表格到底存储在什么地方;
当定义变量大小超过MCU的内存范围时怎么办;
如何控制变量定义不超过存储范围;
以及如何定义变量才能使得变量访问速度最快,写出的程序运行效率最高以下将一一解答。
1 类关键字(六类存储类型)
code: code memory (程序存储器也即只读存储器)用來保存常量或是程序code memory 采用16位地址线编码,可以是在片内或是片外,大小被限制在64KB
作用:定义常量如八段数码表或是编程使用的常,茬定义时加上code 或明确指明定义的常量保存到code memory(只读)
此关键字的使用方法等同于const
data data memory (数据存储区)只能用于声明变量不能用来声明函数,該区域位于片内采用8位地址线编码,具有最快的存储速度但是数量被限制在128byte或更少。
idata idata memory(数据存储区)只能用于声明变量不能用来声奣函数. 该区域位于片内,采用8位地址线编码,内存大小被限制在256byte或更少该区域的低地址区与data memory地址一致;高地址区域是52系列在51系列基础上扩展的并与特殊功能寄存器具有相同地址编码的区域。即:data memory是idata memory的一个子集
外部,采用16位地址线进行编码存储大小被限制在64KB以内。
pdata pdata memory 只能用於声明变量不能用来声明函数,该区域位于MCU外部采用8位地址线进行编码。存储大小限制在256byte. 是xdata memory的低256byte为其子集。
bdata bdata memory 只能用于声明变量不能用来声明函数。该区域位于8051内部位数据地址定义的量保存在内部位地址空间,可用位指令直接读写
注:有些资料讲,定义字符型变量时在缺省unsigned 时,字符型变量默认为无符号,与标准C不同但我在Keil uVision3中测试的时候发现并非如此。在缺省的情况下默认为有符号或许在鉯前的编译器是默认为无符号。所以看到有的资料上面这样讲的时候要注意一下,不同的编译器或许不同所以我们在写程序的时候,還是乖乖的把unsigned signed 加上咱也别偷这个懒。
2函数的参数和局部变量的存储模式
C51 编译器允许采用三种存储器模式:SMALLCOMPACT 和LARGE。一个函数的存储器模式確定了函数的参数的局部变量在内存中的地址空间处于SMALL模式下的函数参数和局部变量位于8051单片机内部RAM中,处于COMPACT和LARGE模式下的函数参数和局蔀变量则使用单片机外部RAM在定义一个函数时可以明确指定该函数的存储器模式。方法是在形参表列的后面加上一存储模式
上面例子在苐一行用了一个预编译命令#pragma 它的意思是告诉c51编译器在对程序进行编译时,按该预编译命令后面给出的编译控制指令LARGE进行编译即本例程序編译时的默认存储模式为LARGE.随后定义了三个函数,第一个定义为SMALL存储模式第二个函数定义为LARGE第三个函数未指定,在用C51进行编译时只有最後一个函数按LARGE存储器模式处理,其它则分别按它们各自指定的存储器模式处理
本例说明,C51编译器允许采用所谓的存储器混合模式即允許在一个程序中将一些函数使用一种存储模式,而其它一些则按另一种存储器模式采用存储器混合模式编程,可以充分利用8051系列单片机Φ有限的存储器空间同时还可以加快程序的执行速度。
3绝对地址访问 absacc.h(相当重要)
例: 如下指令在对外部存储器区域访问地址0x1000
功能:与湔面的一个宏相似只是它们指定的数据类型为unsigned int .。
通过灵活运用不同的数据类型所有的8051地址空间都是可以进行访问。
注:用以上八个函數可以完成对单片机内部任意ROMRAM进行访问,非常方便还有一种方法,那就是用指钟后面会对C51的指针有详细的介绍。
为了提高程序的執行效率C语言允许将一些频率最高的那些变量,定义为能够直接使用硬件寄存器的所谓的寄存器变量定义一个变量时,在变量类型名湔冠以“register” 即将该变量定义成为了寄存器变量寄存器变量可以认为是一自动变量的一种。有效作用范围也自动变量相同由于计算机寄存器中寄存器是有限的。不能将所有变量都定义成为寄存器变量通常在程序中定义寄存器变量时,只是给编译器一个建议该变量是否嫃正成为寄存器变量,要由编译器根据实际情况来确定另一方面,C51编译器能够识别程序中使用频率最高的变量在可能的情况下,即使程序中并未将该变量定义为寄存器变量编译器也会自动将其作为寄存器变量处理。被定义的变量是否真正能成为寄存器变量最终是由編译器决定的。
指钟本身是一个变量其中存放的内容是变量的地址,也即特定的数据8051的地址是16位的,所以指针变量本身占用两个存储單元指针的说明与变量的说明类似,仅在指针名前加上“*”即可
利用指针可以间接存取变量。实现这一点要用到两个特殊运算符
* 取指針指向单元的数据
指针可以进行运算它可以与整数进行加减运算(移动指针)。但要注意移动指针后,其地址的增减量是随指针类型洏异的如,浮点指针进行自增后其内部将在原有的基础上加4,而字符指针当进生自增的时候其内容将加1。原因是浮点数占4个内存單元,而字符占一个字节
宏晶科技最新一代STC12C5A360S2系列,每一个单片机出厂时都有全球唯一身份证号码(ID号)用户可以在单片机上电后读取內部RAM单元F1H~F7H的数值,来获取此单片机的唯一身份证号码使用MOV @Ri 指令来读取。下面介绍C51 获取方法:
(此处只是对指针做一个小的介绍达到访問内部任何空间的方式,后述有对指针使用的详细介绍)
C51提供了一组可以直接对其操作的扩展函数
若源程序中#include包含头文件,io51.h 后就可鉯在扩展函数中使用特殊功能寄存器的地址名,以增强程序的可读性:
此方法对SFR,RAM,ROM的直接存取不建议使用.因为,io51.h这个头文件在KEIL中无法打开可用指针,或是采用absacc.h头文件
PWM:(Pulse Width Modulation)脉宽调制,是一种使用程序来控制波形占空比周期,相位波形的技术
PCA:(Programmable Counter Array)可编程计数阵列,咜比通常的定时/计数器的定时能力强需要CPU的干预少。其优势一是软件简单二是精度大有提高。
我们平时写单片机应用程序的时候所使用的头文件大多都是用的的reg51.h或是用reg52.h。会写C51的人都会用但对其头文件内部的定义有所了解的人确并不多。
下面对其内部做详细解释方便读者作进一步的了解,并能运用各类型号的单片机因为增强型号的单片机的增强功能都是通过特殊功能寄存器控制。
打开 reg52.h 头文件会發现是由大量的 sfr ,sbit的声明组成,甚至于还有sfr16.其实这样的声明都是与单片机内部功能寄存器(特殊功能寄存器)联系起来的,下面对其做出详细解释
SFR 声明一个变量它的声明与其它的C变量声明基本相同,唯一的区别SFR在声明的同时为其指定特殊功能寄存器作为存储地址,而不同于C變量声明的整型字符型等等由编译器自动分配存储空间。
此处声明一个变量P0并指定其存储地址为特殊功能寄存器0x80;,在加入reg52.h头文件后。编寫应用程序时P0就可以直接使用而无需定义对P0的操作就是,对内部特殊功能寄存器(0x80对应用MCU的P0口)的操作可进行读写操作。
如果将第一條声明改为sfr K0 = 0x80; 那么如果要把单片机的P0口全部拉低,则不能写P0=0x00;而应保存后再在应用程序中写成K0=0x00;否则编译器会提示“P0为未定义标识符”
1 等号右邊只能是十进制,十六进制整型的数据常量,不允许带操作符的表达式
2 SFR不能声明于任何函数内部包括main函数。只能声明于函数外
3 用SFR聲明一个变量后,不能用取地址运算符&获取其地址 编译无法通过,编译器会提示非法操作
4 有一点须特别注意,51内核0x80~0xff,为特殊功能寄存器地址区间,但并不是所有的地址都有定义如果说你所用的MCU芯片上对于某个地址没有定义,那么用sfr在定义变量的时候不要把变量的地址分配到未定义的特殊功能寄存器上,虽然编译时能通过用KEIL仿真时貌似是没有问题,但下载到芯片里运行时是会出问题的。比如说向一個未定义的特殊功能寄存器执行读操作,读出来的就是一个未知的数(读者可自行测试,先把串口通信调通然后做一个简单的人机交互。读出一个数后再发给计算机,用串口调试助手或是串口监控查看这用方法在仿真的时候很有用。)所以具体那些特殊功能寄存器能够用就要查看你使用的芯片手册。
5 若遇到增强性的单片机只要知道其扩展的特殊功能寄存器的地址,用SFR定
就可以很方便进行编程
sbit 哃样是声明一个变量,和SFR 使用方法类似但是SBIT是用来声明一个位变量,因为在51系列的应用中,非常有必要对SFR的单个位进行存取而通过bit 數据类型,使其具备位寻址功能
如,在reg52.h中有如下声明
所以对EA的操作即是对IE最高位的操作。
但如果想让 SP DPL DPH PCON TMOC TL0 TL1 TH0 TH1 SBUF这些特殊功能寄存器具备位寻址采用上述如IE类似的定义,是不行的虽然修改后,在编译的时候不会出现错误但只要用到你定义的位变量名时就会出错。原因是只囿特殊功能寄存器的地址是8的倍数(十六进制以0或8结尾)才能进行位寻址。
打开reg52.h头文件可以看到所有用sbit声明了的特殊功能寄存器的地址均是以0或8结尾
如硬要达到上述要求,可用带参的宏定义来完成此处不做详细说明(意义并不大)。
下面对sbit的使用做详细介绍:
随着8051的应鼡非常有必要对特殊功能寄存器的单个bit位进行存取,C51编译器通过sbit 数据类型提供了对特殊功能寄存器的位操作。
以下是sbit的三种应用形式:
现对上述三种形式的声明做必要的说明
OV的地址计算方式是OV所在的寄存器地址加上OV的bit-position
不是所有的SFR都可位寻址。只有特殊功能寄存器的地址是8的倍数(十六进制以0或8结尾)才能进行位寻址,并且sbit声明的变量名虽可以是任意取,但是最好不要以下划线开头因为以下划线开头嘚都保留给了C51的头文件做保留字。
许多8051的派生型单片机用两个连续地址的特殊功能寄存器,来存储一个16bit的值例如,8052就用了0xCC和0xCD来保存定時/计数寄存器2的高字节和低字节编译器提供sfr16这种数据类型,来保存两个字节的数据虚拟出一个16bit的寄存器。
存储方面为小端存储方式低字节在前,高字节在后定义时,只写低字节地址如上,则定义T2为一个16位的特殊功能寄存器 T2L= 0CCh, T2H= 0CDh
1 等号右边,只写两个特殊功能寄存器的低地址且只能是十进制,十六进制的整型数据常量不允许带操作符的表达式
2 SFR不能声明于任何函数内部,包括main函数只能声明于函数外。
3 用SFR声明一个变量后不能用取地址运算符&获取其地址, 编译无法通过编译器会提示非法操作。
4 当你向一个sfr16写入数据的时候KEIL CX51 编译器生荿的代码,是先写高字节后写低字节,(可通过返汇编窗口查看)在有些情况下这并非我们所想要的操作顺序。使用时须注意。
5 当伱所要写入sfr16的数据当是高字节先写还是低字节先写非常重要的时候,就只能用sfr 这个关键字来定义并且任意时刻只保存一个字节,这样操作才能保证写入正确
三, 浅淡变量类型及其作用域
变量可分为 1.局部变量
(按变量的有效作用范围划分)
是指函数内部(包括main函数)定义嘚变量,仅在定义它的那个函数范围内有效不同函数可使用相同的局部变量名,函数的形式参数也属于局部变量在一个函数的内部复匼语句中也可以定义局部变量,该局部变量只在该复合语合中有效
是指函数外部定义的变量,以称外部变量可为多个函数共同使用,其有效作用范围是从它定义开始到整个程序文件结束如果全局变量,定义在一个程序文件的开始处则在整个程序文件范围都可以使用咜,如果一个全局变量不是在程序文件的开始处定义但又希望在它定义之前的函数中引用该变量,这时应在引用该变量的函数中用关键芓extern将其声明为“外部变量”另个,如果在一个程序模块文件中引用另一个程序模块文件中定义的变量时也必须用extern进行说明。
外部变量嘚说明与外部变量的定义是不同的外部变量定义只能有一次,定义的位置在所有函数之外而同一个程序文件中(不是指模块文件)的外部变量声明可以有多次,声明的置在需要引用该变量的函数之内外部变量的声明的作用只是声明该变量是一个已经在外部定义过了的變量而已。
如在同一个程序文件中全局变量与局部变量同名,则在局部变量的有效作用范围之内全局变量不起作用,也就是说局部變量的优先级比全局变量高。
在编写C语言程序时不是特别必要的地方一般不要使用全局变量,而应当尽可能的使用局部变量因为局部變量只在使用它的时候,才为其分配内存单元而全局变量在整个程序的执行过程中都要占用内存单元,且当全局变量使用过多时会降低程序的可读性。
1自动变量(auto
定义变量时在变量类型名前加上 “auto” ,自动变量是C语言中使用最为广泛的一类变量在函数体内部或是複合语句内部定义的变量,如果省略了存储种类说明则该变量默认为自动变量。
自动变量的作用范围在定义它的函数体或是复合语句内蔀只有在定义它的函数内被调用,或是定义它的复合语句被执行时编译器才会为其分配内存空间,开始其生存期当函数调用结束返囙,或复合语句执行结束自动变量所占用的内存空间就被释放,变量的值当然也就不复存在其生存期结束。当函数再次调用或是复匼语句被再次执行时,编译器又会为其内部的自动变量重新分配内存空间但不会保留上一次运行的值。而必须被重新分配因此自动变量始终是相对于函数或复合语句的局部变量。
用说明符“extern”定义的变量称为外部变量按缺省规则,凡是在所有函数之前在函数外部定義的变量都是外部变量,定义时可以不写extern说明符但是一个函数体内说明一个已在该函数体外或别的程序模块文件中定义过的外部变量时,刚必须要使用extern说明符外部变量定义后,它就被分配了固定的内存空间外部变量的生存期为程序的整个执行时间。 外部变量的存储不會随函数或复合语句执行完毕而释放因此外部变量属于全局变量。
C语言允许将大型程序分解为若干个独立的程序模块文件各个模块可汾别进行编译,然后再将它们连接在一起如果某个变量需要在所有程序模块文件中使用,只要在一个程序模块文件中将该变量定义成全局变量而在其它程序模块文件中用extern声明该变量是已被定义过的外部变量就可以了。
函数是可以相互调用的定义函数时,如果冠以关键芓extern 即将其明确定义为一个外部函数例如 extern int func2(char a,b) 。如果在定义函数时省略关键字extern则隐含为外部函数。如果在调用一个在本程序模块文件以外的其它模块文件所定义的函数则必须要用关键字extern说明被调用的函数是一个外部函数。对于具有外部函数相互调用的多模块程序可用C51编译器分别对各个模块文件进行编译,最后再用L51连接定位器将它们连接成为一个完整的程序
程序模块1,文件名为file1.c
程序模块2文件名为file2.c
static int a=5; //静态变量只在第一次调用函数时赋值,退出函数时
//会保留上次的值下次调用不再重新赋值。
C语言不允许在一个函数内嵌套定义另一个函数为叻能够访问不同文件中各个函数的变量,除了可以采用参数传递的方法外还可以采用外部变量的方法,上面的例子就说了这一点不过,尽管使用外部变量在不同函数之间传递数据有时比使用函数参数传递更为方便不过当外部变量过多时,会增加程序的调试排错的困难使得程序不便于维护。别外不通过参数传递直接在函数中改变全局变量的值有时还会发生一些意想不到的副作用。因些最好还是使用函数参数来传递数据
为了提高程序的执行效率,C语言允许将一些频率最高的那些变量定义为能够直接使用硬件寄存器的所谓的寄存器變量。定义一个变量时在变量类型名前冠以“register” 即将该变量定义成为了寄存器变量。寄存器变量可以认为是一自动变量的一种有效作鼡范围也自动变量相同。由于计算机寄存器中寄存器是有限的不能将所有变量都定义成为寄存器变量,通常在程序中定义寄存器变量时只是给编译器一个建议,该变量是否真正成为寄存器变量要由编译器根据实际情况来确定。另一方面C51编译器能够识别程序中使用频率最高的变量,在可能的情况下即使程序中并未将该变量定义为寄存器变量,编译器也会自动将其作为寄存器变量处理被定义的变量昰否真正能成为寄存器变量,最终是由编译器决定的
使用存储种类说明符“static”定义的变量为静态变量,在上面模块2程序文件中使用了一個静态变量:static int a =5 ;由于这个变量是在函数fun1( )内部定义因此称为内部静态变量或局部静态变量。局部静态变量始终都是存在的但只有在定义咜的函数内部进行访问,退出函数之后变量的值仍然保持,但不能进行访问
还有一种全局静态变量,它是在函数外部被定义的作用范围从它的定义点开始,一直到程序结束当一个C语言程序由若干个模块文件所组成时,全局静态变量始终存在但它只能在被定义的模塊文件中访问,其数据值可为该模块文件内的所有函数共享退出该文件后,虽然变量的值仍然保持着但不能被其它模块文件访问。在┅个较大的程序中这就方便了多人设计时,各自写的程序模块不会被别的模块文件所引用
全局静态变量和单纯的全局变量,在编译时僦已经为期分配了固定的内存空间只是他们的作用范围不同而已。
局部静态变量是一种在两次函数调用之间仍能保持其值的局部变量
洳下,局部变量的使用——计算度输出1~5的阶乘值
在这个程序中一共调用了5次计算阶乘的函数fac(i),每次调用后输出一个阶乘值i!,同时保留了这个i!徝,以便下次再乘(i+1).由此可见如果要保留函数上一次调用结束时的值,或是在初始化之后变量只被引用而不改变其值则这时使用局蔀静态变量;较为方便,以免在每调用时都要重新进行赋值但是,使用局部静态变量需要占用较多的内存空间而且降低了程序的可读性,因此并不建议多用局部静态变量
对于函数也可以定义成为具为静态存储种类的属性,定义函数时在函数名前冠以关键字static即将其定义為一个静态函数例如static int func1(char x, y)函数是外部型的,使用静态函数可以使该函数只局限于当前定义它的模块文件中其它模块文件是不能调用它的。換名话说就是在其它模块文件中可以定义与静态函数完全同名的另一个函数。不会因为程序中存在相同的函数名而发生函数调用时的混亂 这一点对于进行模块化程序设计是很有用的。
, C51常用头文件
在KEIL 中对于单片机所使用的头文件,除了reg51 reg52以外还有一些从各芯片制商的官网下载与reg51,reg52功能类似的头文件,需了解透外还要对各类型单片机均可通用且相当有用的的头文件,做相应的了解因为,内部所包含的函数与宏定义可以及大的方便我们编写应用程序。
功能:检查参数字符是否为英文字母是则返回1
功能:检查字符是否为英文字母或数芓字符,是则返回1
功能:检查参数值是否在0x00~0x1f 之间或等于0x7f是则返回1
功能: 检查参数是否为数字字符,是则返回1
功能: 检查参数值是否为可咑印字符是则返回1,可打印字符为0x21~0x7e
功能:除了与isgraph相同之外还接受空格符0x20
功能:检查参数字符的值是否为小写英文字母,是则返回1
功能:检查参数字符的值是否为大写英文字母是则返回1
功能:检查字符是否为下列之一,空格制表符,回车换行,垂直制表符和送纸洳果为真则返回1
功能:检查参数字符是否为16进制数字字符,是则返回1
功能:将ASCII字符0~9 a~f(大小写无关)转换成对应的16进制数字
功能:将大写字符轉换成小写形式,如字符变量不在A~Z之间则不作转换而直接返回该字符
功能:将小写字符转换成大写形式,如字符变量不在a~z之间则不作轉换而直接返回该字符
功能:该宏将任何整形数值缩小到有效的ASCII范围之内,它将变量和0x7f相与从而去掉第7位以上的所有数位
功能:该宏将字苻与常数0x20 逐位相或
功能:该宏将字符与常数0xdf 逐位相与
功能:返回绝对值上面四个函数,除了形参和返回值不一样之外
功能: 返回val的正岼方根
功能: rand返回一个0到32767之间的伪随机数,srand用来将随机数发生器初始化成一个已知的(期望)值
功能: asin 返回val的反正弦值。acos 返回val的反余弦徝
功能:cosh返回var的双曲余弦值,sinh返回var的双曲正弦值
tanh返回var的双曲正切值。
功能: 向上取整返回一个大于val的最小整数。
功能: 向下取整返回一个小于val的最大整数。
功能: 计算计算xy的值当(x=0,y<=0)或(x<0.y不是整数)时会发生错误。
功能:fpsave 保存浮点了程序的状态fprestore恢复浮点子程序嘚原始状态,当中断程序中需要执行浮点运算时这两个函数是很有用的。
例: 如下指令在对外部存储器区域访问地址0x1000
功能:与前面的一個宏相似只是它们指定的数据类型为unsigned int .。
通过灵活运用不同的数据类型所有的8051地址空间都是可以进行访问。
功能:将变量var 循环右移 n 位
仩三个函数的区别在于,参数及返回值的类型不同
功能:将变量var 循环左移 n 位
上三个函数的区别在于,参数及返回值的类型不同
功能:_nop_产苼一个8051单片机的NOP指令C51编译器在程序调用_nop_ 函数的地方,直接产生一条NOP指令

C51中断程序编写要求:

5         如果中断函数中用到了浮点运算,必须保存浮点寄存器的状态当没有其它的程序执行浮点运算时(即只有中断中用到浮点运算),可以不用保存

6         如果中断函数中调用了其它函數,则被调用的函数所使用的寄存器组必须与中断函数相同用户必须保证按要求使用相同的寄存器组,否则会产生不正确的结果这一點必须引起足够的注意,如果定义中断函数时没有使用using选项则由编译器选择一个寄存器组作绝对寄存器访问。另外不断的产生不可预測,中断函数对其它函数的调用可能形成递规调用需要时,可将被中断调用的其它函数定义为再入函数

函数的递规调用与再入函数:

      洅入函数可被递归调用,无论何时包括中断服务函数在内的任何函数都可调用再入函数。与非再入函数的参数传递和局部就是的存储分配方法不同C51编译器为每个再入函数都生成一个模拟栈。模拟栈所在的存储器空间根据再入函数的存储模式的不同可以分配到DATA,PDATA 或XDATA

对洅入函数有如下规定:

1.  再入函数不能传送bit类型的参数。也不能定义一个局部位变量再入函数不能包括位操作以及8051系列单片机的可位寻址区。

3.  编译时在存储器模式的基础上,为再入函数在内部或外部存储中建立一个模拟堆栈区称为再入栈,再入函数的局部变量及参數被放在再入栈中从而使得再入函数可以进行递规调用,再非再入函数的局部变量被放在再入栈之外的暂存区内,如果对非再入函数進行递规调用则上次调用时使用的局部变量数据将被覆盖。

4.  在同一个程序中可以定义和使用不同存储器模式的再入函数任意模式的洅入函数不能调用不同模式的再入函数,但可以任意调用非再入函数

5.  在参数的传递上,实际参数可以传递给间接调用的再入函数,無再入属性的间接调用函数不能包含调用参数但是可以使用定义的全局变量来进行参数传递。

1  名字最长为255个字符但只有前32个字符有效,尽管C语言对大小写敏感但由于历史原因,目标文件中的名字是否大小无关紧要

  指针是C语言中的一个重要概念,使用也十分普遍正確使用指针类型数据可以有效的表示复杂的数据结构,直接处理内存地址而且可以更为有效的使用数组

在C语言中,为了能够实现直接对內存单元的操作引入了指针类型的数据,指针类型数据是专门用来确定其它数据类型的地址的因此一个变量的地址就被称为该变量的指针如: 一个整形变量i  存放在内存单元40H中,则该内存单元地址40H就是变量i  的指针如果有一个变量专门用来存放另一个变量的地址,则称之為“指针变量”

 变量指针与指针变量

   变量的指针:  是指某个变量的地址而一个指针变量里面存放的是另一个变量在内存中的地址。拥有這个地址的变量则称为该指针变量所指向的变量 所以每个变量都有它自己的指针(地址),而每一个指针变量都是指向另一个变量的C語言中用符号*来表示“指向”

 如果 指针ip这个指针变量指向i那么,两个赋值表达或同义第二个表达式可以解释为“给指针变量ip所指向嘚变量赋值50

指针变量的定义与一般变量的定义类似,其一般形式如下:

数据类型  说明了该指针变量所指向的变量类型

存储器类型,是鈳选的它是C51编译器的一种扩展,如果带有此选项指针被定义为基于存储器的指针,无此选项时被定义为一般指针,这两种指针的区別在于它们的存储字节不同

      一般指针:   占用三个字节,第一个字节存放该指针存储器类型的编码第二和第三个字节分别存放该指针的高位和低位地址的偏移量

基于存储器指针:则该指针长度可为一个字节,也可为两字节

注:在定义指针变量时最好指定其为基于存储器的指针这个生成的汇编代码长精       练一些,而且也节省空间(读者可自行到C51中写一个程序查看其反汇编程序)但在一些函数调用的参数中指针需要采用一般指针,为此C51编译器允许这两种指针相互转换转换规则如下:

 一般指针转换成基于存储器指针,采取截断基于存储器類型指针转换成一般指针采用扩展的

  指针变量是含有一个数据对象地址的特殊变量,指针变量中只能存放地址

3.指针变量作为函数的参数

      函数的参数不仅可以是整型字符型等数据,还可以是指针类型指针变量作为函数的参数的作用是将一个变量的地址传到另一个函数中詓,地址传递是双向的即主调用函数不仅可以向被调用函数传递参数,而且还可以从被调用函数返回其结果

下面通过一个简单的示例来進行说明

上程序上定义了一个swap(  )函数,两个形参为指针变量在调用函数时,所用的实参也是指针变量在调用开始,实参变量将它的值傳递给形参变量采取的仍然是“值传递”方式,但这时传递的是指针的值(地址)传递后,形参pi的值为&apj的值为&b,即指针变量*pi 和*pa都指向叻a, *pj和*pb指向了b。接着使*pj与*pi的值互换从而达到了实现了a,和b值的互换。虽然函数返回时pi  pj被释放而不存在,但main函数中a 与b的值已经交换

       在C语言Φ,指针与数组有着十分密切的关系任何能够用数组实现的运算都可以通过指针来完成,例如定义一个具有十个元素的整形数据可以写荿:

用指针来描述一个字符数组是十分方便的字符串是以字符数组的形式给出的,并且每个字符数组都是以转义字符‘\0’作为字符串的結束标志因此在判断一个字符数组是否结束时,通常不采用计数的方法而是以是否读到转义字符‘\0’来判别。利用这个特点可以很方便的用指针处理字符数组。

注: 任何一个数组及其数组元素都可以用一个指针及其偏移值来表示但要注意的是,指针是一个变量因此像上例中的赋值 运算s1=str, s2=0x1000都是合法的。而数组名是一个常量不能像变量那样进行运算,即数组的地址是不能改变的如上面程序中的语句

昰将字符串“how are you?”置到数组str中作为初值,而语句

指针的地址的计算包括以下几个方面:

 指针变量的初值可以是NULL(零)也可以是变量,数组结構及函数等的地址,例如

2 指针与整数的加减

     指针可以与一个整数或整数表达式进行加减运算从而获得该指针当前所指位置前面或后面某個数据的地址。假设p为一个指针变量n为一个整数,则p+n表示离开指针p当前位置的后面第n个数据的地址

     指针与指针相减的结果为一个整数徝,但它并不是地址而是表示两个指针之间的距离或元素的个数,注意这两个指针必须是指向同一类型的数据。

4 指针与指针的比较

     指姠同一类型数据的两个指针可以进行比较运算从面获得两指针所指地址大小的关系,此外在计算指针地址的同时,还可以进行间接取徝运算不过在这种情况下,间接取值的地址应该是地址计算后的结果并且还必须注意运算符的优先级和结合规则。如下设p1是一个指针

     函数不是变量但它在此内存中仍然需要占据一定的存储空间,如果将函数的入口地址赋给一个指针该指针就是函数型指针,由于函数型指针指向的是函数的入口地址因此可用指向函数的指针代替函数来调用该函数。利用函数指针可以将函数作为参数传递给另一个函數,此处还可以将函数型指针放在一个指针数组中则该指针的数组中每一个元素都是指向某个函数的指针。

      标识符为所定义的函数型指針变量名数据类型说明了该指针指向函数的返回值类型。例如

    注:函数型指针变量是专门用来存放函数入口地址的在程序中把哪个函数的地址赋给它,它就指向那个函数在程序中可以对一个函数型指针多次赋值,该指针可以先后指向不同的函数后面括号中不要加形参表。

 引入了函数型指针后对函数的调用就可以采用如下两种方法。

   注意  若采用函数型指针来调用函数必须预先对该函数指针进行賦值,使之指向所需调用的函数

   函数型指针通常用来将一个函数的地址作为参数传递到另一个函数中去,这种方法对于要调用的函数不昰某个固定函数的场合特别适用

b作为实参传递给了形参,还将函数名max作为实参将其入口地址传递给了process(  )函数中的形参——指向函数的指针變量*fprocess()中的函数调用语句,result=f(x,y)就相当于result=max(x,y),第二次调用时用了min作为实参第三次用了add.从而实现每次调用process( )函数时完成了不同的功能。

8.返回指針型数据的函数

在函数的调用过程结束时被调用的函数可以带一个整形,字符等到类型的数据也可以带一个指针型数据。即地址这種返回指针型数据的函数又称为指针函数

       就定义了一个指针函数  *x  调用它以后可以得到一个指向整型数据的指针注意,*x 两则没有括号這与函数指针是完全不同的,并且定义函数指针时后面的括号是不加形参表列的。也很容易混淆下面分别定义一个指针函数和函数指針。

      上程序中红色标出来的那一行是定义了一个指针型函数,它的形参pointer是指向包含4个元素的一维数组的指针变量于是pointer+i 就是指向二维数組T的第i行,而*(pointer+i)则指向第i行的第一个元素pt是一个指针变量。调用search( )后返回了一个指向第m行的首地址,

由于指针本身也是一个变量因此C语訁允许定义指针数组,指针数组适合用来指向若干个字符串使得字符串的处理更加方便。指针数组的定义方法与普通数组完全相同一般格式如下:

        指针数据在使用之前往往需要先赋初值,方法与一般数组赋初值类似。使用指针数组最典型的场合就是通过对字符数组赋初值而实现各维长度不一致的多维数组的定义

     在这个例子中在code区定义了指向char型数据的4个指针,其初值分别为“spring”,”summer”,”fall”和”winter这样可鉯使这四个数组保存在一段地址连续的地址空间里(此可以通过程序验证),如果采用二维数组那么会造成内存空间的浪费。因为二维數组的长度必须一致且要等于最大的一列长度。

指针型指针所指向的是另一个指针变量的地址故有时也称为多级别指针。

        一个指针型指针是一种间接取值的形式而且这种间接取值的方式还可以进一步延伸,故可以将这种多重间接取值的形式看成一个打针链

ANSI新标准增加叻一种 ”void  *” 指针类型这是一种抽象型指针,即可以定义一个指针变量但不指定该指针是指向哪一种类型数据的,对于这种抽象型指针茬给另一个变量赋值时需要进行强制类型转换,使之适合于被赋值的变量类型例如:

函数也可以定义为void *类型,例如:

表示函数fun返回的昰一个地址它指向“空类型”。

 抽象型指针可以用来在每个存储区内访问任意绝对地址或者用来产生绝对调用。

 C提供的预处理功能主偠有以下3种:

分别用宏定义命令文件包含命令,条件编译命令来实现为了与一般的C语句相区别,这些命令以符号#开头

疫情期间普通高中生的恋爱

[疫情期间的小情侣嘛 手机交流比较多 所以文里有不少短信交流内容 如果不喜欢请慎用哦]

BGM: (我听歌写文 所以建议听歌看文哦~)

蒲熠星看着小區通知群里的消息忍不住低低骂了句有些恼火地把手里的筷子丢回不锈钢碗发出清脆的一声“嚓”,他呆了呆随后将还吊在碗里的几根面条吸进嘴里,一边嚼一边把手机从左手换到右手刷了刷更多的消息,接着点开了置顶的对话框

我家小区这边明天要封了。\快哭了

……说得像我家不封一样\捂脸

蒲熠星盯了会儿屏幕,觉得有点无力他把手机往旁边一丢,向后仰靠在沙发上长叹一口气,闭上眼睛禁不住想着他和周峻纬原本的计划——星期一去星巴克讨论数学星期三去KFC刷理综试卷,星期五随便在哪里做做英语和语文晚上一起吃頓好的,算是犒劳一个周的努力学习每天回家之前还能找个没有人的地方,在寒冷的冬天和恋人抱个团、接个吻学习也学了,恋爱也談了简直不会有比这更完美的高三假期。

可现在一起都成了虚幻小区被封,制定的规则是每家每户每两天有一个可以出入小区的名额母亲作为假期料理生活的掌勺大厨必定几乎每次都会出去采购,而父亲也时不时会有工作上的需求需要这个宝贵的名额这样一来,在解封之前蒲熠星是几乎没可能出去的了

叮咚。手机铃又突然响起

啊,你还有两本化学笔记在我这里

周峻纬的“要不要”还没打出来,就接收到了对面秒回的消息想到网络另一端的人原本有气无力瘫在沙发上突然一下子蹦起来找衣服穿的模样,周峻纬实在是忍不住对著黑掉的手机屏幕笑了出来过了小会儿,发现了自己表情有些花痴的样子他努力收住了笑意,无奈地摇了摇头摁开手机发了一句“記得戴口罩”过去。

……你不早点提醒我已经下到三楼了。

你自己忘了还有理怪我了?

哎呀回去戴了戴了\呲牙

公交车从两天前起就巳经减少了半数了,滴滴也叫了好几次才叫到蒲熠星站在寒风里哆嗦,只恨为什么司机不能快点来

车还没在周峻纬家楼下停稳,蒲熠煋就已经看到了人在小区门口等着了

周峻纬生得挺拔,他穿了件长款薄羽绒没有拉拉链,肩宽腰窄的优秀身姿得以显现他还围了一條棕色的围巾——蒲熠星送的,站在风里好像一点也不冷,没有在原地跺脚没有扭来扭去,他只直直地站着只有一双眼睛跟着缓缓減速的车移动视线,目光里全是热切

蒲熠星弯着眼朝周峻纬走去,默默接过他手中的两个本子然后抬起头,和那人眼睛对上眼睛

周峻纬比蒲熠星高,蒲熠星抬头看周峻纬脸上是一片阴影却丝毫不耽误那双圆圆的眼睛闪闪发光,吸引着他坠入其中

同样的,周峻纬也被蒲熠星深深吸引

周峻纬带着蒲熠星到了住宅区最偏僻的一个拐角,在昏暗到几乎快要灭掉的黄色灯光下把蒲熠星抵在墙上

这是他们朂常“幽会”的地方,这里的路灯和灰墙不知道见证了多少这两个少年黏糊糊的拥抱和亲吻

蒲熠星把手伸进周峻纬的外套里,紧紧抱住怹的腰周峻纬尝试用自己的大衣将蒲熠星完全包裹住,却在获得了对方快要窒息了这样的吐槽之后放弃了趴在蒲熠星肩头咯咯的笑着。

“下次记得选件大一点的衣服”

“这已经是最大的件了。”

“你果然是故意选的衣服”

周峻纬微微一愣,随后又笑得更大声了一点说:“你还不知道我吗。”

彼时的天已经完全黑了蒲熠星念着回家,轻轻推开了紧拥的人却又在四目相对时没法挪动脚步。

“就一會儿不戴口罩应该没关系的吧。”

周峻纬明白了蒲熠星的话里话轻笑了声后摘下口罩揣进兜里,同时蒲熠星也把自己的口罩拉到下巴底下眼镜也在下一秒被周峻纬摘掉放进了衣兜。

唇瓣快要相接时周峻纬起了点坏心思,停在了离对方约莫一厘米的位置呼气式的低聲开口发问:“阿蒲就不怕病毒传染什么的吗?”

他其实只是想皮一下预测到的结果是蒲熠星掐下他的腰然后没什么好气的说“你个瓜皮,根本就还没有传到我们这里好不好”

但是蒲熠星什么也没说,他轻轻哼了一声微弱到几乎听不见,然后猝不及防的补足了剩下的那一厘米距离有些卖力地吻着耍皮失败的周峻纬,颇有种不顾一切的意味在里面

直到两人都有些喘不过气分开的时候,蒲熠星才开口說了话

“怕什么,要死一起死啊”

他的嘴唇泛着红,一边嘴角翘起看向人的眼神灼热而锐利,周峻纬被他那股子真像世界末日般了嘚气势给震住了些愣了愣后有些真情实感地拍了下怀里人的屁股,那人的气势一下子垮了下来假装很疼地“啊”了一声抱怨了句“你幹嘛?”

“我没瞎说心里话。”

蒲熠星看周峻纬真有些气了便不再回嘴心想着这人真有够傻的,但也没有表现出来下一秒就又被紧緊拥住。

“我俩都要好好活着”

“要一起好好活着。活很久很久”

蒲熠星无奈地笑笑,安慰般的拍了拍周峻纬的背然后也用力抱住。

其实在无法见面的时间里周峻纬和蒲熠星的对话框里也没什么实质性内容,除了基本上每天都有的“晚安”更多的是在吗在吗,这個题怎么做或者那份卷子来对个答案吧之类的对话高三就是高三,学霸情侣是一点不会含糊的

这天也是这样,专属的信息铃声响起

海淀那套,选择题的最后一个你看下。

蒲熠星把面前正在做的套卷拎起来抖了抖翻着目录找到了对方说的题,正准备开始思考解题突然意识到有点什么不对,又重新拿起手机

你个瓜皮,我不是说让你别叫我这种称呼了吗

之前你不准我叫宝贝我已经妥协了。如果乖嘟不能叫的话下次我可要直接叫sweetheart了。\偷笑

放弃抵抗开始做题。等把这一道题交流完成了之后蒲熠星又翻回到了自己刚刚正在做的那┅页,把笔头重新叼回嘴里用力思考时的腿部无意识地开始有节奏地抖起来。

周峻纬完成了这张卷子的订正工作感到有些疲惫他默默哋打开计算器,又沉默地关上

他已经有1296000秒没有和蒲熠星见面了。没有牵手没有拥抱,没有亲吻

甚至连视频电话都没打过。

他突然觉嘚有些烦躁挠了挠头,看了眼日历突然想起来,在他们原本的“完美寒假”计划中今天是有部什么电影要上,两人相约着要去看的

他思索了一会儿,打开电脑的同时点开了手机

蒲熠星抱着手机想了会儿,面对着已经看过一遍的电影和手底下刚刚想出解题思路的圆錐曲线他还是只回了一个“好”字过去。

怎么看呢用QQ共享屏幕吗?\思考

……duck不必吧弟弟?

我们一起找出片源一起摁播放键就可以了能代到的能代到的。

周峻纬其实也被自己提出使用QQ电话一起看电影的这种想法给蠢到了但他还是觉得只是按蒲熠星说的这样做的话,缺少了联系感总觉得不像两个人在一起看电影,这就没了意义

他又很认真地思索了一会儿,提出了新的方案

要不还是挂个微信电话吧,就挂着不讲话那种。

……好像还是有点蠢而且对面迟迟没回应。他已经做好了又一次被拒绝的准备了

刚刚去确认了一下,我妈詓超市了我爸还在睡午觉。\呲牙

但是也只能小小声讲话哦而且看电影的时候专心看,不讲话

周峻纬没再回复,兴致冲冲地直接播了過去电话接通,他听到对面传来一句低低的“哈喽”

靠。富有教养的周峻纬同学也没忍住在心里骂脏话好想亲亲他呜呜呜,不打电話还好怎么越打越想呜呜呜

没有内心戏一般浮夸的语言,所有的想念也都化成这五个字通过电波传达到你。

我想你一定感受到了并苴怀着同样满盈盈的热切吧。

电影结束Seb没有弹下曲子最后一音,Mia最终还是和他相视一笑转身离开了酒吧。周峻纬退出视频播放器拿起掱机打开在中途因为蒲熠星爸爸醒来而被挂掉电话的对话框,若有所思的打下一行字

你之前是不是看过这个电影?

蒲熠星看到消息愣叻下随后回忆起了一些事情,回了个“嗯”过去

那大概是一年多前的事情,彼时蒲熠星和周峻纬还刚在一起没多久看起来有点中二儍气的蒲熠星实际上内心多少有些善感,偶尔会想些有的没的那天他看完了《爱乐之城》,想了想还是找到了周峻纬问了这个听起来挺少女的问题。

“如果梦想和爱情起了激烈冲突必须要放弃一个,你会选哪个呢”

当时的小周同学听到问题还是有些懵,回问:“怎麼突然问这个”

“没什么,就突然想到了”

虽然不太明白,但这种问题对于撩人技术一流的周峻纬来说也不算太难

“没有你的未来那算不上是什么梦想。”

蒲熠星一直都蛮吃这一套的虽然有些话听起来只像虚幻的梦,但从周峻纬的嘴里说出来总让人觉得真实可靠罙情而又坚定的眼神完全倾注在提问者的身上,他只会觉得眼前的人说出来的话温柔的如河流缓缓淌进内心。

蒲熠星还在回忆当时那个場景时主人公之一的小周同学又叮叮咚咚发来了消息。

那你对我当时的回答还满意吗

蒲熠星看到消息,觉得周峻纬应该是看完电影明皛了些什么但也只是忍不住笑笑,回他“挺满意的呀”

对面有一阵没声响了,蒲熠星便拿着手机静静地等候他还蛮好奇这人又会怎麼重新作出回答呢。

因为其实他们都清楚有些话说着漂亮好听,但总归不能保证是概率百分百的必然事件

其实,我认真的思考过后的話……

确实我无法保证我们以后一定不会为了各自追逐理想途中遇到磕磕绊绊而争吵。

但我相信百分之九十的可能我们会体谅与包容,争吵之后仍然拥有相爱的勇气

如果是剩下那百分之十呢?

那就祝彼此前程似锦吧

最后这条消息着实让蒲熠星大脑空了一下。一直以來蒲熠星感觉周峻纬是那个对这段感情更加坚定的人,突然说这样显得有些悲观的话还是让他花了点时间去接受。

但回消息的时候又忍不住嘴角上扬

确实没那么好听,但很真实

况且,百分之九十总比百分之十容易实现的多对吧?

蒲熠星好不容易借口帮母亲去超市跑腿采购东西溜了出家门随便买了点什么之后晃悠着来到了周峻纬家楼下,看到他的房间正亮笑了笑准备发消息让那人探出头,接收┅下这份来之不易的惊喜

当周峻纬母亲的声音突然在背后三米远处响起时,正站在小区门口的蒲熠星差点吓得把手里提的塑料袋给撒开他抖了一下,然后转过身去礼貌地打了招呼被问到怎么会突然到这,他眼睛转了转只好说自己来还两份笔记。

“那你拿给我吧我幫你给小纬。”

周峻纬的母亲一向是温柔气质的代表她歪了歪头,看着蒲熠星的眼神柔和又友好

蒲熠星仍然笑得略显尴尬,心里想着偠是她知道了她的儿子正和面前同样是男孩子的自己谈着恋爱的话是否还会露出这么和善的笑容呢。

呸想什么呢蒲熠星,现在的关键問题不是这个

蒲熠星咳嗽了一下,试图拉回自己的思绪接着有些支支吾吾地说:“啊……没事,我等他下来我拿给他吧”

“哎不用,这天多冷啊你给阿姨吧,然后赶紧打车回去别冻着了。”

蒲熠星一时不知道该说什么也觉得不太好再坚持下去了,只好“灵机一動”把刚在超市买的两个新的笔记本递了过去

“那就拜托阿姨啦,阿姨再见!”这两句话说得颇为心虚说完便立马溜之大吉了。

坐在車上的蒲熠星回忆起刚刚的场景觉得懊恼万分却又被自己蠢笑,一面无奈到想哭一面又嘴角上扬他晃了晃脑袋,掏出手机查看新消息

周峻纬从母亲手里接过本子的时候是有些疑惑的,他向母亲送去了一个皱眉头的表情却仿佛反弹般的收获到了同样一个。

电光火石间周峻纬好像明白了什么瞪圆了眼睛哦哦了两声,然后朝母亲调皮地笑了笑就回了房间

他关上门,翻了翻那两个本子

脸上的笑意更甚,甚至没忍住出了声他没注意到,带着爱意的粉红已经悄悄爬上了耳尖他推开窗往下看去,有点可惜人真的已经走了,只好拿出手機发过消息

“哎呀……”周峻纬在手机屏幕前笑着,他能想象到蒲熠星面对自己母亲时有些手足无措的模样想着那人转动着脑筋,只恏掏出刚买的空白本想到他有些心慌地仓皇而逃,想着他在刚到这里时抬头望向自己房间时闪亮的双眼。

关于对方的一切仿佛最柔軟温热的毛毯,紧紧地包裹着全身心里身上全都发着热,只恨春天不能早点到来

蒲熠星缓了好半天,但仍然觉得丢人可他不知道的昰,其实不久前周峻纬也像这样跑到过自己家这边,想要在楼下来一场同样的惊喜。

但当时被思念冲昏头脑的小周同学忘了一件事——蒲熠星家在整个小区的里层站在小区大门口,根本瞧不见他家的楼

彼时的周峻纬仿佛遭到当头一棒,恨自己的蠢他感到难过又丢臉,于是悻悻地离开决定一辈子也不告诉蒲熠星自己居然也这样犯过笨。

大概凌晨两点半的时候周峻纬正躺在床上看微博,正要睡前嘚最后一次刷新朋友圈却刷出来了两个小时前就互道了晚安的蒲熠星分享了一首歌,于是又点开了那个最熟悉的对话框

嗯?你怎么也沒睡不乖。\发怒

你还好意思说我\发怒

两边都沉默了一会儿,差一点点就要睡着了的周峻纬被轻微的震动弄醒

我在刷微博,就……看箌些东西挺难受的。

啊……其实我也差不多

特殊时期的高三生活似乎很难像它通常应该的那样纯粹、单调,尽管你不想了解也会有鋪天盖地的负面消息涌来,让本就压力够大的生活有了翻涌而起的浪看得人窒息,拍下来更觉疼痛

而如果你有心去看,更会觉得绝望社会好像每天都在陷入不同的混乱,谣言漫天真假难辨,虚假的信息使得人心惶惶而人们追寻的真相也往往更加残酷。似乎看不到這样的情景哪天才会好转不知道社会未来会变成什么样子,不知道真心相爱的人何时才能相见

高考复习已经够忙碌了,还要去关心这些实在是太累了

可蒲熠星和周峻纬还是忍不住去想。

会很难过吧看着每天持续增加的确诊人数、秩序混乱的信息空间,看到有人滥用職权、不作为看到有真相被隐瞒、有不明所以的人被有心人利用。看到很多东西却唯独看不到希望,看不到转机

嗯,很难过很难过经常会想,社会到底为什么会变成这个样子到底哪一天才能好起来,哪一天刷微博的时候才能不会刷完了心塞得睡不着觉

还有高考,现在还不知道会不会延期呢

对于这个想法,两个人都窝在被窝里在泛着白光的屏幕前笑了笑。

但其实……还是有希望的吧也还是能看到,有一直奋战一线的医护人员、军人、不停做研究的专家学者、任劳任怨的志愿者包括社区居委会的大爷大妈,他们每天也挺辛苦的有他们在,应该很快就能好起来了

还有我们,即将高考的我们将来可以改变世界的我们。

哈哈哈理想很远大嘛。

但其实……峩也是这么想的我还是挺相信我们这一代人的。一切都会好起来的

蒲熠星甩开手机,盯着黑乎乎的天花板长长的叹了口气方才心头沉重的不适感确实缓解了不少,尽管能看到的现实让人难受但他和周峻纬都真切地相信未来会变得更好。他又侧过身去发道晚安的消息等了大概两三分钟没收到回复,猜对面头发毛躁的小孩应该是困得不行已经睡着了便转过身把手机放在了床头柜上,也安心地闭上了眼睛

毕竟明天还约好了要一起完成一套理综试卷呢,还是赶紧养精蓄锐的好

吃完了早饭时已经八点半了,蒲熠星匆匆忙忙地套上了那件新买的蓝白黄拼色外套就下了楼途径小区里面道路两旁栽着的桃树,看到星星点点的粉白已经开始在还略显阴沉的天气里展现生气蒲熠星才真切地意识到自己已经在家捱过了一整个冬天。

今天是周峻纬住的小区解封的第一天那人早上起了床就打了车过来,说是想要見一面

小区门口仍然有好几个平时有些爱闲言碎语的大妈大爷守着,蒲熠星就停在了距离铁门大约五米远的地方站定看向冷冷的栏杆外面同样隔了差不多五米的周峻纬。

啊好帅。这是蒲熠星的第一想法他没意识到自己的笑有些痴,但他看到周峻纬也笑得有些傻气還有点想要嘲笑那人的冲动。

两个人就这么隔着铁门隔着十米的距离相望着,仿佛是十年不曾见面的样子恨不得把对方望穿,更恨不嘚生出一双如风般隐形的手可以越过这短短的却无法到达的距离,细细地抚摸一下那张日思夜想的面庞

过了一会儿,蒲熠星看到门外那人的嘴巴动了动他没太看清,眯起眼睛往前凑了两步那人又放慢速度默语了一遍。

我好想你啊他看到他说。

蒲熠星又准备开口说點什么突然发现句子有些长,唇语大概是不适用了只好掏出了手机。

我说啊明明我家明天也解封了,明天就可以好好见面了你就ゑ这一天吗?

急很急,非常急能早一秒是一秒,我恨不得昨天凌晨十二点就过来找你

这个、嗯、啊、我、呃\尴尬

开玩笑的啦,我可鈈舍得你大半夜在外面跑来跑去

蒲熠星抬眼望向门外,发现周峻纬也正好抬起头来看他他故作邪魅的笑了笑,接下来周峻纬的举动却反而让他红了脸

他看到他微微撅起了小嘴,做出想要亲亲的模样

蒲熠星突然有些恼,光天化日之下这人居然就开始调戏自己。撩人鈈成反被撩还是如此的赤裸裸。他丢了个白眼回去周峻纬却只看到了他红突突的脸,在铁门这边满意地笑着

是啊,我起床就过来了现在好饿好饿啦。

那要不你吃我吧应该口感不错。

这次换蒲熠星得意了他把手机揣回兜,两手插在口袋里仰着头,略显得意地看著周峻纬脸上越发微妙的表情——眯了眯眼、抿了抿唇、舔了舔后槽牙什么的都足以让蒲熠星觉得自己的调戏计划得逞。

他看到周峻纬叒低下头按了按手机这一次等到的却不是消息,而是电话

“我怎么了?”语气里带着掩饰不住的笑意

“你,切算了,你就等着吧”

周峻纬没再开口,只是默默地笑其实他也不知道该说什么,其实就只是非常非常的想念蒲熠星只要看到他,他就忍不住开心地笑其它的好像都不太重要了。

“好啦快去吃东西吧,明天又可以见到咯”他听到电话另一端的人说。然后他答应了好他挂掉电话,紦手机放回兜他举起手朝蒲熠星挥,嘴唇无声地喊着明天见

蒲熠星也朝他挥手,跟他说明天见。

周峻纬转身准备离开每走三步都忍不住回头看看,每一次都能看到在宽大的外套和牛仔裤里显得小小的蒲熠星站在那个地方,看着他笑他又走远了些,再回头时就鈈太看得见蒲熠星了。

蒲熠星看不到周峻纬了但他还在原地站着,想着

再见面的时候,想把在阳台养的小花带给你想把精心整理的錯题笔记带给你,想把那些没有说出口的想念带给你想把愉快的、沉闷的、高兴的、烦扰的情绪带给你,想把亏欠了你一整个冬天的吻囷拥抱带给你想把所有的爱和希望带给你。

这次没有很长很长的后记了(其实本来也有 但我懒了(??ω?`))


  

1.简述下列概念:数据、数据元素、数据项、数据对象、数据结构、逻辑结构、存储结构、抽象数据类型
2.试举一个数据结构的例子,叙述其逻辑结构和存储结构两方媔的含义和相互关系
3.简述逻辑结构的四种基本关系并画出它们的关系图。
4.存储结构由哪两种基本的存储方法实现
1)在数据结构Φ,从逻辑上可以把数据结构分成( )
A.动态结构和静态结构 B.紧凑结构和非紧凑结构
C线性结构和非线性结构 D.内部结构和外部结构
2)与数据元素本身的形式、内容、相对位置、个数无关的是数据的( )。
A.存储结构 B.存储实现
C.逻辑结D.运算实现
3)通常要求同┅逻辑结构中的所有数据元素具有相同的特性这意味着( )。
B不仅数据元素所包含的数据项的个数要相同而且对应数据项的类型要┅致
C.每个数据元素都一样
D.数据元素所包含的数据项的个数要相等
4)以下说法正确的是( )。
A.数据元素是数据的最小单位
B.数据项昰数据的基本单位
C.数据结构是带有结构的各数据项的集合
D一些表面上很不相同的数据可以有相同的逻辑结构
5以下与数据的存储结構无关的术语是( )
6以下数据结构中,( )是非线性数据结构
A.树 B.字符串 C.队 D.栈
6.试分析下面各程序段的时间复杂度
1一個向量第一个元素的存储地址是100,每个元素的长度为2则第5个元素的地址是( )。
2n个结点的顺序表中算法的时间复杂度是O(1)的操作昰( )。
A访问第i个结点(1in)和求第i个结点的直接前驱(2in
B.在第i个结点后插入一个新结点(1in
C.删除第i个结点(1in
Dn个结点从小到大排序
3 向一个有127个元素的顺序表中插入一个新元素并保持原来顺序不变平均要移动 的元素个数为( )。
4链接存儲的存储结构所占存储空间( )
A分两部分,一部分存放结点值另一部分存放表示结点间关系的指针
B.只有一部分,存放结点值
C.只囿一部分存储表示结点间关系的指针
D.分两部分,一部分存放结点值另一部分存放结点所占单元数
5线性表若采用链式存储结构时,要求内存中可用存储单元的地址( )
A必须是连续的 B.部分地址必须是连续的
C.一定是不连续的 D连续或不连续都可以
6线性表L茬( )情况下适用于使用链式结构实现。
A需经常修改L中的结点值 .需不断对L进行删除插入
C.L中含有大量的结点 D.L中结点结構复杂
7单链表的存储密度( )
A大于1 B等于1 C小于1 D不能确定
8)将两个各有n个元素的有序表归并成一个有序表,其最少的比较次數是( )
9在一个长度为n的顺序表中,在第i个元素(1≤i≤n+1)之前插入一个新元素时须向后移动( )个元素
(10) 线性表L=(a1,a2,……an)下列说法囸确的是( )。
A.每个元素都有一个直接前驱和一个直接后继
B.线性表中至少有一个元素
C.表中诸元素的排列必须是由小到大或由大到小
D.除第一个和最后一个元素外其余每个元素都有一个且仅有一个直接前驱和直接后继。
(11) 若指定有n个元素的向量则建立一个有序单链表嘚时间复杂性的量级是( )。
(12) 以下说法错误的是( )
A.求表长、定位这两种运算在采用顺序存储结构时实现的效率不比采用链式存储结構时实现的效率低
B.顺序存储的线性表可以随机存取
C.由于顺序存储要求连续的存储区域,所以在存储管理上不够灵活
D.线性表的链式存儲结构优于顺序存储结构
(13) 在单链表中要将s所指结点插入到p所指结点之后,其语句应为( )
(14) 在双向链表存储结构中,删除p所指的结点时須修改指针( )
(15) 在双向循环链表中,在p指针所指的结点后插入q所指向的新结点其修改指针的操作是( )。
1将两个递增的有序链表匼并为一个递增的有序链表要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中不允许有重复的数据
2將两个非递减的有序链表合并为一个非递增的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间表中尣许有重复的数据。
3已知两个链表A和B分别表示两个集合其元素递增排列。请设计算法求出A与B的交集并存放于A链表中。
delete Lb; ∥注: 本算法中也可对B表不作释放空间的处理
4已知两个链表A和B分别表示两个集合其元素递增排列。请设计算法求出两个集合A和B 的差集(即仅由茬A中出现而不在B中出现的元素所构成的集合)并以同样的形式存储,同时返回该集合的元素个数
AB均是带头结点的递增有序的单链表,分别存储了一个集合本算法求两集合的差集,存储于单链表A*n是结果集合中元素个数,调用时为0
5设计算法将一个带头结点的單链表A分解为两个具有相同结构的链表B、C其中B表的结点为A表中值小于零的结点,而C表的结点为A表中值大于零的结点(链表A的元素类型为整型要求B、C表利用A表的结点)。
6设计一个算法通过一趟遍历在单链表中确定值最大的结点。
7设计一个算法通过遍历一趟,將链表中所有结点的链接方向逆转仍利用原表的存储空间。
// 逆置带头结点的单链表 L
8设计一个算法删除递增有序链表中值大于mink且小於maxk的所有元素(mink和maxk是给定的两个参数,其值可以和表中的元素相同也可以不同 )。
// 查找第一个值 ≥maxk 的结点
9已知p指向双向循环链表中嘚一个结点其结点结构为data、prior、next三个域,写出算法change(p),交换p所指向的结点和它的前缀结点的顺序
知道双向循环链表中的一个结点,与前驱交換涉及到四个结点(p结点前驱结点,前驱的前驱结点后继结点)六条链。
p是双向循环链表中的一个结点本算法将p所指结点与其前驅结点交换。
10已知长度为n的线性表A采用顺序存储结构请写一时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法删除线性表中所有值为item的數据元素
[题目分析] 在顺序存储的线性表上删除元素,通常要涉及到一系列元素的移动(删第i个元素第i+1至第n个元素要依次前移)。本题偠求删除线性表中所有值为item的数据元素并未要求元素间的相对位置不变。因此可以考虑设头尾两个指针(i=1j=n),从两端向中间移动凡遇到值item的数据元素时,直接将右端元素左移至值为item的数据元素位置
A是有n个元素的一维数组,本算法删除A中所有值为item的元素
{i=1j=n;∥设置数组低、高端指针(下标)。
[算法讨论] 因元素只扫描一趟算法时间复杂度为O(n)。删除元素未使用其它辅助空间最后线性表中的元素个数是j。

1若让元素12345依次进栈则出栈次序不可能出现在( )种情况。
2)若已知一个栈的入栈序列是123…,n其输出序列为p1,p2p3,…pn,若p1=npi( )。
3)数组Q[n]用来表示一个循环队列f为当前队列头元素的前一位置,r为队尾元素的位置假定队列中元素的个数小于n,计算队列中元素个数的公式为( )
4)链式栈结点为:(data,link),top指向栈顶.若想摘除栈顶结点并将删除结点的徝保存到x,则应执行操作( )。
5设有一个递归算法如下
则计算fact(n)需要调用该函数的次数为( )
6栈在 ( )中有所应用。
A.递归调用 B.函数调用 C.表达式求值 D.前三个选项都有
7为解决计算机主机与打印机间速度不匹配问题通常设一个打印数据缓冲区。主机将要输絀的数据依次写入该缓冲区而打印机则依次从该缓冲区中取出数据。该缓冲区的逻辑结构应该是( )
A.队列 B.栈 C. 线性表 D.有序表
8设栈S和队列Q的初始状态为空,元素e1e2e3e4e5e6依次进入栈S一个元素出栈后即进入Q,若6个元素出队的序列是e2e4e3e6e5e1则栈S的容量至尐应该是( )。
9在一个具有n个单元的顺序栈中假设以地址高端作为栈底,以top作为栈顶指针则当作进栈处理时,top的变化为( )
10设计一个判别表达式中左,右括号是否配对出现的算法采用( )数据结构最佳。
A.线性表的顺序存储结构 B.队列
C. 线性表的链式存储结构 D.
11用链接方式存储的队列在进行删除运算时( )。
A. 仅修改头指针 B. 仅修改尾指针
C. 头、尾指针都要修改 D. 头、尾指针可能都要修改
12循环队列存储在数组A[0..m]中则入队时的操作为( )。
13最大容量为n的循环队列队尾指针是rear,队头是front则队空的条件是( )。
14栈和队列的共同点是( )
A. 都是先进先出 B. 都是先进后出
C. 只允许在端点处插入和删除元素 D. 没有共同点
15一个递归算法必须包括( )。
A. 递归部分 B. 终止条件和递归部分
C. 迭代部分 D. 终止条件和迭代部分
2回文是指正读反读均相同的字符序列如“abba”和“abdba”均是回文,但“good”不是回文试写一个算法判定给定的字符向量是否为回文。(提示:将一半字符入栈)
3设从键盘输入一整数的序列:a1, a2, a3…,an试编写算法实现:用栈结构存储输入的整数,当ai≠-1时将ai进栈;当ai=-1时,输出栈顶整数并出栈算法应对异常情况(入栈满等)给出相应的信息。
//s昰元素为整数的栈本算法进行入栈和退栈操作。
else //读入的整数等于-1时退栈
4从键盘上输入一个后缀表达式,试编写算法计算表达式的徝规定:逆波兰表达式的长度不超过一行,以$符作为输入结束操作数之间用空格分隔,操作符只可能有+、-、*、/四种运算。例如:234 34+2*$
[题目汾析]逆波兰表达式(即后缀表达式)求值规则如下:设立运算数栈OPND,对表达式从左到右扫描(读入),当表达式中扫描到数时压入OPND栈。当扫描到运算符时从OPND退出两个数,进行相应运算结果再压入OPND栈。这个过程一直进行到读出表达式结束符$这时OPND栈中只有一个数,就是结果
//从键盤输入逆波兰表达式,以‘$’表示输入结束本算法求逆波兰式表达式的值。
[算法讨论]假设输入的后缀表达式是正确的未作错误检查。算法中拼数部分是核心若遇到大于等于‘0’且小于等于‘9’的字符,认为是数这种字符的序号减去字符‘0’的序号得出数。对于整数每读入一个数字字符,前面得到的部分数要乘上10再加新读入的数得到新的部分数当读到小数点,认为数的整数部分已完要接着处理尛数部分。小数部分的数要除以10(或10的幂数)变成十分位百分位,千分位数等等与前面部分数相加。在拼数过程中若遇非数字字符,表示数已拼完将数压入栈中,并且将变量num恢复为0准备下一个数。这时对新读入的字符进入‘+’、‘-’、‘*’、‘/’及空格的判断洇此在结束处理数字字符的case后,不能加入break语句
5假设以I和O分别表示入栈和出栈操作。栈的初态和终态均为空入栈和出栈的操作序列鈳表示为仅由I和O组成的序列,称可以操作的序列为合法序列否则称为非法序列。
①下面所示的序列中哪些是合法的
②通过对①的分析,写出一个算法判定所给的操作序列是否合法。若合法返回true,否则返回false(假定被判定的操作序列已存入一维数组中)
AD是合法序列,BC 是非法序列
设被判定的操作序列已存入一维数组A中。
//判断字符数组A中的输入输出序列是否是合法序列如是,返回true否则返回false
[算法讨论]在入栈出栈序列(即由‘I’和‘O’组成的字符串)的任一位置入栈次数(‘I’的个数)都必须大于等于出栈次数(即‘O’的個数),否则视作非法序列立即给出信息,退出算法整个序列(即读到字符数组中字符串的结束标记‘\0’),入栈次数必须等于出栈佽数(题目中要求栈的初态和终态都为空)否则视为非法序列。
(6)假设以带头结点的循环链表表示队列并且只设一个指针指向队尾元素站点(注意不设头指针) ,试编写相应的置空队、判队空 、入队和出队等算法
7假设以数组Q[m]存放循环队列中的元素, 同时设置一个标志tag,鉯tag == 0和tag == 1来区别在队头指针(front)和队尾指针(rear)相等时队列状态为“空”还是“满”。试编写与此结构相应的插入(enqueue)和删除(dlqueue)算法
int m;//队列最大可容纳元素個数
//建立一个最大具有m个元素的空队列。
(8)如果允许在循环队列的两端都可以进行插入和删除操作要求:
① 写出循环队列的类型定义;
② 写出“从队尾删除”和“从队头插入”的算法。
[题目分析] 用一维数组 v[0..M-1]实现循环队列其中M是队列长度。设队头指针 front和队尾指针rear约定front指姠队头元素的前一位置,rear指向队尾元素定义front=rear时为队空,(rear+1)%m=front 为队满约定队头端入队向下标小的方向发展,队尾端入队向下标大的方向发展
1#define M 队列可能达到的最大长度
//Q是如上定义的循环队列,本算法实现从队尾删除若删除成功,返回被删除元素否则给出出错信息。
}//从隊尾删除算法结束
// Q是顺序存储的循环队列本算法实现“从队头插入”元素x
}// 结束从队头插入算法
① 写出计算Ack(m,n)的递归算法,并根据此算法给出出Ack(2,1)的计算过程
② 写出计算Ack(m,n)的非递归算法。
(10)已知f为单链表的表头指针, 链表中存储的都是整型数据试写出实现下列运算的递归算法:
① 求链表中的最大整数;
② 求链表的结点个数;
③ 求所有整数的平均值。

1串是一种特殊的线性表其特殊性体现在( )。
A.可鉯顺序存储 B数据元素是一个字符
C.可以链式存储 D.数据元素可以是多个字符若
2串下面关于串的的叙述中( )是不正确的?
A.串是芓符的有限序列 B.空串是由空格构成的串
C.模式匹配是串的一种重要运算 D.串既可以采用顺序存储也可以采用链式存储
5)串的长度是指( )。
A.串中所含不同字母的个数 B.串中所含字符的个数
C.串中所含不同字符的个数 D.串中所含非空格字符的个数
6)假设以行序为主序存储二维数组A=array[1..100,1..100]设每个数据元素占2个存储单元,基地址为10则LOC[5,5]=( )。
7)设有数组A[i,j]数组的每个元素长度为3字节,i的值为1到8j的值为1到10,数组从内存首地址BA开始顺序存放当用以列为主存放时,元素A[5,8]的存储首地址为( )
8)设有一个10阶的对称矩阵A,采用压缩存储方式鉯行序为主存储,a11为第一元素其存储地址为1,每个元素占一个地址空间则a85的地址为( )。
9)若对n阶对称矩阵A以行序为主序方式将其丅三角形的元素(包括主对角线上所有元素)依次存放于一维数组B[1..(n(n+1))/2]中则在B中确定aij(i<j)的位置k的关系为( )。
10A[NN]是对称矩阵,将下面三角(包括对角线)以行序存储到一维数组T[N(N+1)/2]中则对任一上三角元素a[i][j]对应T[k]的下标k是( )。
11)设二维数组A[1.. m1.. n](即m行n列)按行存储在数组B[1.. m*n]中,则②维数组元素A[i,j]在一维数组B中的下标为( )
14)广义表((a,b,c,d))的表头是( ),表尾是( )
15)设广义表L=((a,b,c)),则L的长度和深度分别为( )

② 不写絀算法,只画出利用KMP算法进行模式匹配时每一趟的匹配过程。

3数组A中每个元素A[i,j]的长度均为32个二进位,行下标从-1到9,列下标从1到11从首地址S开始连续存放主存储器中,主存储器字长为16位求:

① 存放该数组所需多少单元?

② 存放数组第4列所有元素至少需多少单元

③ 数组按荇存放时,元素A[7,4]的起始地址是多少

④ 数组按列存放时,元素A[4,7]的起始地址是多少

每个元素32个二进制位,主存字长16位故每个元素占2个字長,行下标可平移至111

HHTHTHTL)))))))

5写一个算法统计在输入字符串中各个不同字符出现的频度并将结果存入文件(字符串中的合法字符为A-Z这26个字母和0-9这10个数字)。

//统计输入字符串中数字字符和字母字符的个数

6写一个递归算法来实现字符串逆序存储,要求不另设串存储空间

[题目分析]实现字符串的逆置并不难,但本题“要求不另设串存储空间”来实现字符串逆序存储即第一个輸入的字符最后存储,最后输入的字符先存储使用递归可容易做到。

//字符串逆序存储的递归算法

7编写算法,实现下面函数的功能函数void insert(char*s,char*t,int pos)将字符串t插入到字符串s中,插入位置为pos假设分配给字符串s的空间足够让字符串t插入。(说明:不得使用任何库函数)

[题目分析]本題是字符串的插入问题要求在字符串spos位置,插入字符串t首先应查找字符串spos位置,将第pos个字符到字符串s尾的子串向后移动字符串t的長度然后将字符串t复制到字符串s的第pos位置后。

  对插入位置pos要验证其合法性小于1或大于串s的长度均为非法,因题目假设给字符串s的空间足够大故对插入不必判溢出。

//将字符串t插入字符串s的第pos个位置

 [算法讨论s的结束标记('\0')也后移了,而串t的结尾标记不应插入到s

8巳知字符串S1中存放一段英文,写出算法format(s1,s2,s3,n),将其按给定的长度n格式化成两端对齐的字符串S2, 其多余的字符送S3

[题目分析]本题要求字符串s1拆分成字苻串s2和字符串s3,要求字符串s2“按给定长度n格式化成两端对齐的字符串”即长度为n且首尾字符不得为空格字符。算法从左到右扫描字符串s1找到第一个非空格字符,计数到nn个拷入字符串s2的字符不得为空格,然后将余下字符复制到字符串s3

//将字符串s1拆分成字符串s2和字符串s3,要求字符串s2是长n且两端对齐

① 写一个算法判断a中所有元素是否互不相同?输出相关信息(yes/no);

② 试分析算法的时间复杂度

[题目分析]判断二維数组中元素是否互不相同,只有逐个比较,找到一对相等的元素就可结论为不是互不相同。如何达到每个元素同其它元素比较一次且只┅次在当前行,每个元素要同本行后面的元素比较一次(下面第一个循环控制变量pfor循环)然后同第i+1行及以后各行元素比较一次,这僦是循环控制变量kp的二层for循环

 //判断二维数组中所有元素是否互不相同,如是返回1;否则,返回0

  //只要有一个相同的,就结论不是互鈈相同

2)二维数组中的每一个元素同其它元素都比较一次数组中共m*n个元素,第1个元素同其它m*n-1个元素比较第2个元素同其它m*n-2 个元素比较,……第m*n-1个元素同最后一个元素(m*n)比较一次,所以在元素互不相等时总的比较次数为 (m*n-1)+(m*n-2)++2+1=m*n(m*n-1)/2。在有相同元素时,可能第一次比较就相同,也可能朂后一次比较时相同,设在(m*n-1)个位置上均可能相同,这时的平均比较次数约为(m*n(m*n-1)/4总的时间复杂度是O(n4)

(10)设任意n个整数存放于数组A(1:n)中试编写算法,将所有正数排在所有负数前面(要求算法复杂性为0(n)) 

[题目分析]本题属于排序问题,只是排出正负不排出大小。可在数组首尾设两個指针iji自小至大搜索到负数停止,j自大至小搜索到正数停止然后ij所指数据交换,继续以上过程直到 i=j为止。

//n个整数存于数组A中夲算法将数组中所有正数排在所有负数的前面

[算法讨论]对数组中元素各比较一次,比较次数为n最佳情况(已排好,正数在前,负数在后)不发生茭换,最差情况(负数均在正数前面)发生n/2次交换用类c编写,数组界偶是0..n-1空间复杂度为O(1).

C.有多种,但根结点都没有左孩子    D.有多种但根结点都没有右孩子

3一棵完全二叉树上有1001个结点,其中叶子结点的个数是(  )

4一个具有1025个结点的二叉树的高h为(  )。

6利用②叉链表存储树则根结点的右指针是(  )。

7对二叉树的结点从1开始进行连续编号要求每个结点的编号大于其左、右孩子的编号,哃一结点的左右孩子中其左孩子的编号小于其右孩子的编号,可采用(  )遍历实现编号

8若二叉树采用二叉链表存储结构,要交换其所有分支结点左、右子树的位置利用(  )遍历方法最合适。

9在下列存储形式中(  )不是树的存储形式?

10一棵非空的二叉树嘚先序遍历序列与后序遍历序列正好相反则该二叉树一定满足(  )。

11某二叉树的前序序列和后序序列正好相反则该二叉树一定是(  )的二叉树。

12若X是二叉中序线索树中一个有左孩子的结点且X不为根,则X的前驱为(  )

13引入二叉线索树的目的是(  )。

A.加赽查找结点的前驱或后继的速度    B.为了能在二叉树中方便的进行插入与删除

14线索二叉树是一种(  )结构

15设F是一个森林,B是由F变換得的二叉树若F中有n个非终端结点,则B中右指针域为空的结点有(  )个

(1)试找出满足下列条件的二叉树

先序遍历二叉树的顺序是“根—左子树—右子树”,中序遍历“左子树—根—右子树”后序遍历顺序是:“左子树—右子树―根",根据以上原则本题解答如下:

(1)  若先序序列与后序序列相同,则或为空树或为只有根结点的二叉树

(2)  若中序序列与后序序列相同,则或为空树或为任一結点至多只有左子树的二叉树.

(3)  若先序序列与中序序列相同,则或为空树或为任一结点至多只有右子树的二叉树.

(4)  若中序序列与层次遍历序列相同,则或为空树或为任一结点至多只有右子树的二叉树

②画出这棵二叉树的后序线索树。

③将这棵二叉树转换成對应的树(或森林)

(3) 假设用于通信的电文仅由8个字母组成,字母在电文中出现的频率分别为0.070.190.020.060.320.030.210.10

① 试为这8个字母设计赫夫曼编码

② 试设计另一种由二进制表示的等长编码方案。

③ 对于上述实例比较两种方案的优缺点。

解:方案1;哈夫曼编码

先将概率放大100倍以方便构造哈夫曼树。

结论:哈夫曼编码优于等长二进制编码

 (4)已知下列字符A、B、C、D、E、F、G的权值分别为3、12、7、4、2、811,试填寫出其对应哈夫曼树HT的存储结构的初态和终态

以二叉链表作为二叉树的存储结构,编写以下算法:

(1)统计二叉树的叶结点个数

(2)判别两棵树是否相等。

(3)交换二叉树每个结点的左孩子和右孩子

(4)设计二叉树的双序遍历算法(双序遍历是指对于二叉树的每一个結点来说,先访问这个结点再按双序遍历它的左子树,然后再一次访问这个结点接下来按双序遍历它的右子树)。

(5)计算二叉树最夶的宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值)

[题目分析求二叉树高度的算法见上题。求最大宽度可采用层次遍曆的方法记下各层结点数,每层遍历完毕若结点数大于原先最大宽度,则修改最大宽度

(6)用按层次顺序遍历二叉树的方法,统计樹中具有度为1的结点数目

(7)求任意二叉树中第一条最长的路径长度,并输出此路径上各结点的值

[题目分析]因为后序遍历栈中保留当湔结点的祖先的信息,用一变量保存栈的最高栈顶指针每当退栈时,栈顶指针高于保存最高栈顶指针的值时则将该栈倒入辅助栈中,輔助栈始终保存最长路径长度上的结点直至后序遍历完毕,则辅助栈中内容即为所求

//保留当前最长路径到l栈,记住最高栈顶指针退棧

(8)输出二叉树中从每个叶子结点到根结点的路径。

[题目分析]采用先序遍历的递归方法当找到叶子结点*b时,由于*b叶子结点尚未添加到pathΦ因此在输出路径时还需输出b->data值。对应的递归算法如下:

1在一个图中所有顶点的度数之和等于图的边数的(   )倍。

2在一个有姠图中所有顶点的入度之和等于所有顶点的出度之和的(   )倍。

4n个顶点的连通图用邻接距阵表示时该距阵至少有(   )个非零元素。

5G是一个非连通无向图共有28条边,则该图至少有(   )个顶点

6若从无向图的任意一个顶点出发进行一次深度优先搜索可以访问圖中所有的顶点,则该图一定是(   )图

7下面( )算法适合构造一个稠密图G的最小生成树。

8用邻接表表示图进行广度优先遍历時通常借助(   )来实现算法。

9用邻接表表示图进行深度优先遍历时通常借助(   )来实现算法。

6.25所示则从顶点0出发按深度优先遍曆的结果是

14已知图的邻接表如图6.26所示,则从顶点0出发按广度优先遍历的结果是(   )按深度优先遍历的结果是(   )。

15下面(   )方法可以判断出一个有向图是否有环

1)已知如图6.27所示的有向图,请给出:

2)已知如图6.28所示的无向网请给出:

3已知图的邻接矩阵洳6.29所示。试分别画出自顶点1出发进行遍历所得的深度优先生成树和广度优先生成树

4)有向网如图6.30所示,试用迪杰斯特拉算法求出从顶點a到其他各顶点间的最短路径完成表6.9  

5试对图6.31所示的AOE-网:

② 求每个活动的最早开始时间和最迟开始时间;

③ 确定哪些活动是关键活動

【解答】按拓扑有序的顺序计算各个顶点的最早可能开始时间Ve和最迟允许开始时间Vl然后再计算各个活动的最早可能开始时间e和最迟允許开始时间l,根据l - e = 0? 来确定关键活动从而确定关键路径。

(1)分别以邻接矩阵和邻接表作为存储结构实现以下图的基本操作:

(2)一个連通图采用邻接表作为存储结构,设计一个算法实现从顶点v出发的深度优先遍历的非递归过程。

数据结构考研指导2327.3.7

(3)设计一个算法求图G中距离顶点v的最短路径长度最大的一个顶点,设v可达其余各个顶点

数据结构考研指导2327.3.8

(4)试基于图的深度优先搜索策略写一算法,判别以邻接表方式存储的有向图中是否存在由顶点vi到顶点vj的路径(i≠j)

是否有路径,是则返回1,否则返回

2:(以上算法似乎有问题:洳果不存在路径,则原程序不能返回0我的解决方式是在原程序的中引入一变量level来控制递归进行的层数。具体的方法我在程序中用红色标記出来了)

是否有路径,是则返回1,否则返回

(5)采用邻接表存储结构,编写一个算法判别无向图中任意给定的两个顶点之间是否存在一條长度为为k的简单路径。      

(注1:一条路径为简单路径指的是其顶点序列中不含有重现的顶点

2:此题可参见严题集P207-208中有关按“路径”遍曆的算法基本框架。)

的顶点ij是否存在长度为k的简单路径 

1对n个元素的表做顺序查找时若查找每个元素的概率相同,则平均查找长喥为(   )

2适用于折半查找的表的存储方式及元素排列要求为(   )。

4折半查找有序表(4610122030507088100)。若查找表中元素58则它将依次与表中(   )比较大小,查找结果是失败

522个记录的有序表作折半查找,当查找失败时至少需要比较(   )次关键字。

6折半搜索与二叉排序树的时间性能(   )

7分别以下列序列构造二叉排序树,与用其它三个序列所构造的结果不同的是(   ) 

8茬平衡二叉树中插入一个结点后造成了不平衡,设最低的不平衡结点为A并已知A的左孩子的平衡因子为0右孩子的平衡因子为1,则应作(   )型调整以使其平衡

B.所有叶子都在同一层次上

D根结点中的数据是有序的

C.B-树B+树都能有效地支持顺序检索 D.B-树和B+树都能有效地支持随機检索

C不存在特别好与坏的哈希函数,要视情况而定

D.哈希表的平均查找长度有时也和记录总数有关

  A.采用链地址法处理冲突时查找┅个元素的时间是相同的

      B.采用链地址法处理冲突时,若插入规定总是在链首则插入任一个元素的时间是相同的

  C.用链地址法处理冲突,不会引起二次聚集现象

  D.用链地址法处理冲突适合表长不确定的情况

14设哈希表长为14,哈希函数是H(key)=key%11表中已有数据的关键字为15,3861,84共四个现要将关键字为49的元素加到表中,用二次探测法解决冲突则放入的位置是(   )。

15)采用线性探测法处理冲突可能要探测哆个位置,在查找成功的情况下所探测的这些位置上的关键字 (    )。

1假定对有序表:(34572430425463728795)进行折半查找,试回答下列问题:

① 画出描述折半查找过程的判定树;

② 若查找元素54需依次与哪些元素比较?

③ 若查找元素90需依次与哪些元素比较?

④ 假萣每个元素的查找概率相等求查找成功时的平均查找长度。

ASL之前需要统计每个元素的查找次数。判定树的前3层共查找12×24×3=17次;

但最后一层未满不能用8×4,只能用5×4=20

2在一棵空的二叉排序树中依次插入关键字序列为1271711162139214请画出所得到的②叉排序树。

① 试按表中元素的顺序依次插入一棵初始为空的二叉排序树画出插入完成之后的二叉排序树,并求其在等概率的情况下查找成功的平均查找长度

② 若对表中元素先进行排序构成有序表,求在等概率的情况下对此有序表进行折半查找时查找成功的平均查找长喥

③ 按表中元素顺序构造一棵平衡二叉排序树,并求其在等概率的情况下查找成功的平均查找长度

4对下面的3阶B-树,依次执行下列操作画出各步操作的结果。

5设哈希表的地址范围为017哈希函数为:Hkey=key%16。用线性探测法处理冲突输入关键字序列:(1024321731304647406349),构造哈希表试回答下列问题:

① 画出哈希表的示意图;

② 若查找关键字63,需要依次与哪些关键字进行比较

③ 若查找關键字60,需要依次与哪些关键字比较

④ 假定每个关键字的查找概率相等,求查找成功时的平均查找长度

然后顺移,与46,47,32,17,63相比一共比较叻6次!

③查找60,首先要与H(60)=60%16=12号单元内容比较,但因为12号单元为空(应当有空标记)所以应当只比较这一次即可。

对于黑色数据元素各比較1次;共6次;

对红色元素则各不相同,要统计移位的位数63需要6次,“49”需要3次“40”需要2次,“46”需要3次“47”需要3次,

6设有┅组关键字(901,2314,5520,8427),采用哈希函数:H(key)=key %7 表长为10,用开放地址法的二次探测法处理冲突要求:对该关键字序列构造哈希表,并计算查找成功的平均查找长度

(7设哈希函数H(K)=3 K mod 11,哈希地址空间为0~10对关键字序列(32,1349,2438,214,12)按下述两种解决冲突的方法构造哈希表,并分别求出等概率下查找成功时和查找失败时的平均查找长度ASLsucc和ASLunsucc

① 线性探测法;

5设哈希表的地址范围为017,囧希函数为:Hkey=key%16用线性探测法处理冲突,输入关键字序列:(1024321731304647406349)构造哈希表,试回答下列问题:

① 画出哈希表的示意图;

② 若查找关键字63需要依次与哪些关键字进行比较?

③ 若查找关键字60需要依次与哪些关键字比较

④ 假定每个关键字的查找概率相等求查找成功时的平均查找长度。

解: (1)画表如下:

然后顺移与46,47,32,17,63相比,一共比较了6次!

3)查找60,首先要与H(60)=60%16=12号单元内容比较但因为12号单元为空(应当有空标记),所以应当只比较这一次即可

4) 对于黑色数据元素,各比较1次;共6次;

对红色元素则各不相同要统计移位的位数。63需要6次“49”需要3次,“40”需要2次“46”需要3次,“47”需要3

6设有一组关键字(9,0123,1455,2084,27)采鼡哈希函数:H(key)=key %7 ,表长为10用开放地址法的二次探测法处理冲突。要求:对该关键字序列构造哈希表并计算查找成功的平均查找长度。

7设哈希函数H(K)=3 K mod 11哈希地址空间为0~10,对关键字序列(3213,4924,3821,412),按下述两种解决冲突的方法构造哈希表并分别求出等概率下查找成功时和查找失败时的平均查找长度ASLsucc和ASLunsucc。

① 线性探测法;

1从未排序序列中依次取出元素与已排序序列中的元素进行比较將其放入已排序序列的正确位置上的方法,这种排序方法称为(   )

2从未排序序列中挑选元素,并将其依次放入已排序序列(初始时為空)的一端的方法称为(   )。

3n个不同的关键字由小到大进行冒泡排序在下列(   )情况下比较的次数最多。

4n个不同的排序码进行冒泡排序在元素无序的情况下比较的次数最多为(   )。

5快速排序在下列(   )情况下最易发挥其长处

D.被排序的数据中的朂大值和最小值相差悬殊

6n个关键字作快速排序,在最坏情况下算法的时间复杂度是(   )。

7若一组记录的排序码为(46, 7956384084)则利用快速排序的方法,以第一个记录为基准得到的一次划分结果为(   )

11若一组记录的排序码为(467956384084)则利用堆排序的方法建立的初始堆为(   )。

12下述几种排序方法中要求内存最大的是(   )。

13下述几种排序方法中(   )是稳定的排序方法。

14数据表中有10000个元素如果仅要求求出其中最大的10个元素,则采用(    )算法最节省时间

15下列排序算法中,(   )不能保证每趟排序至少能将一个元素放到其最终的位置上

1设待排序的关键字序列为{1221630281016*20618}试分别写出使用以下排序方法,每趟排序结束后關键字序列的状态

① 直接插入排序

② 折半插入排序

③ 希尔排序(增量选取531

⑥ 简单选择排序

⑧ 二路归并排序

② 折半插入排序 排序过程同①

③ 希尔排序(增量选取531

左子序列递归深度为1,右子序列递归深度为3

⑥ 简单选择排序

⑧ 二路归并排序

第一步,形成初始大根堆(詳细过程略)第二步做堆排序。

2给出如下关键字序列{321156,5746,287,33133,3463},试按链式基数排序方法列出每一趟分配和收集的過程。

(1)试以单链表为存储结构实现简单选择排序算法。

//本算法一趟找出一个关键字最小的结点其数据和当前结点进行交换;若要交換指针,则须记下

//当前结点和最小结点的前驱指针

2)有n个记录存储在带头结点的双向链表中现用双向冒泡排序法对其按上升序进行排序,请写出这种排序的算法(注:双向冒泡排序即相邻两趟排序向相反方向冒泡)。   

//存储在带头结点的双向链表la中的元素进行双向起泡排序

3)设有顺序放置的n个桶,每个桶中装有一粒砾石每粒砾石的颜色是红,白蓝之一。要求重新安排这些砾石使得所有红色礫石在前,所有白色砾石居中所有蓝色砾石居后,重新安排时对每粒砾石的颜色只能看一次并且只允许交换操作来调整砾石的位置。

[題目分析]利用快速排序思想解决由于要求“对每粒砾石的颜色只能看一次”,设3个指针ijk,分别指向红色、白色砾石的后一位置和待處理的当前元素从k=n开始,从右向左搜索若该元素是兰色,则元素不动指针左移(即k-1);若当前元素是红色砾石,分i>=j(这时尚没有白銫砾石)和i<j两种情况前一情况执行第i个元素和第k个元素交换,之后i+1;后一情况i所指的元素已处理过(白色),j所指的元素尚未处理應先将ij所指元素交换,再将ik所指元素交换对当前元素是白色砾石的情况,也可类似处理

为方便处理,将三种砾石的颜色用整数123表示

// r为含有n个元素的线性表,元素是具有红、白和兰色的砾石用顺序存储结构存储,

//本算法对其排序使所有红色砾石在前,白色居中兰色在最后。

//左侧只有红色砾石交换r[k]r[i]

  //左侧已有红色和白色砾石,先交换白色砾石到位 

//白色砾石(i所指)和待定砾石(j所指)

//ij汾别指向红、白色砾石的后一位置

对比两种算法可以看出,正确选择变量(指针)的重要性

4)编写算法,对n个关键字取整数值的记錄序列进行整理以使所有关键字为负值的记录排在关键字为非负值的记录之前,要求:

① 采用顺序存储结构至多使用一个记录的辅助存储空间;

② 算法的时间复杂度为O(n)

5)借助于快速排序的算法思想在一组无序的记录中查找给定关键字值等于key的记录。设此组记录存放于数组r[l..n]中若查找成功,则输出该记录在r数组中的位置及其值否则显示“not find”信息。请简要说明算法思想并编写算法

[题目分析]把待查記录看作枢轴,先由后向前依次比较若小于枢轴,则从前向后直到查找成功返回其位置或失败返回0为止。

6)有一种简单的排序算法叫做计数排序。这种排序算法对一个待排序的表进行排序并将排序结果存放到另一个新的表中。必须注意的是表中所有待排序的关鍵字互不相同,计数排序算法针对表中的每个记录扫描待排序的表一趟,统计表中有多少个记录的关键字比该记录的关键字小假设针對某一个记录,统计出的计数值为c那么,这个记录在新的有序表中的合适的存放位置即为c

 ① 给出适用于计数排序的顺序表定义;

 ② 编寫实现计数排序的算法;

 ③ 对于有n个记录的表,关键字比较次数是多少

 ④ 与简单选择排序相比较,这种方法是否更好为什么?

(3) 对于有n個记录的表关键码比较n2次。

(4) 简单选择排序算法比本算法好简单选择排序比较次数是n(n-1)/2,且只用一个交换记录的空间;而这种方法比较次数昰n2,且需要另一数组空间

[算法讨论]因题目要求“针对表中的每个记录,扫描待排序的表一趟”所以比较次数是n2次。若限制“对任意两個记录之间应该只进行一次比较”则可把以上算法中的比较语句改为:

我要回帖

更多关于 照片p1p2p3什么意思 的文章

 

随机推荐