设一维数组中有n个数组元素,则读取第i个数组元素的平均时间复杂度为(O(1))
稀疏矩阵一般采用三元组顺序表方法压缩存储
数组作为函数参数传递的是数组的首地址
在二分查找中,如果剩下的子序列有奇数个数字,就取中间那个为middle。如果有偶数个数字,取前一半的最后一个为middle
数组静态分配内存,链表动态分配内存;
数组在内存中连续,链表不连续;
数组元素在栈区,链表元素在堆区;
数组利用下标定位,时间复杂度为O(1),链表定位元素时间复杂度O(n);
数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)。
线性表采用链式存储时,其地址连续与否均可。线性表的链式存储可用连续或不连续的存储单元来存储线性表中的元素,也即线性表中的元素存储地址连续与否均可。 王道考研2019版第四页第七题提到,链式存储设计时,结点内的存储单元地址一定连续。因此很多同学认为此题应选部分地址必须连续。这里的部分应指结点间,而非结点内。
线性表若采用链式存储表示时所有结点之间的存储单元地址可连续可不连续。
顺序存储,占用内存的地址连续,表现为数组,插入删除,需要移动当前下标以后的数据的位置; 链式存储,占用非连续的内存地址,每个节点都有数据data部分以及next指针,故插入删除只需要改变指针的指向就行,不需要移动数据位置。
线性表可以为空 ,除第一个和最后一个元素外,其余每个元素都有且仅有一个直接前驱和直接后继
1 下面哪项是数组优于链表的特点? D
方便删除
方便插入
长度可变
存储空间小
1: 数组内存空间少比链表少
2:数组支持随机访问,链表不具有随机访问的特性
3:插入和删除是链表优于数组,数组需要移动被删除或者插入位置之后的元素
https://blog.csdn.net/u014082714/article/details/44259029
D 链表要保存指向下个节点的指针,占用空间比数组更大
2 在C++中,以下定义和初始化的两数组a1和a2,那么下列说法正确的是( D)。
a1和a2完全相同
a1和a2不同,a1是指针
a1和a2存储单元的数目相同
a1和a2不同,a1的存储单元数目多
a1中存储的是字符串,因此在末尾存在字符’\0’;而a2中没有’\0’字符,所以sizeof(a1)=8,sizeof(a2)=7,a1存储单元数目多
3 以下二维数组声明中,正确的是( B)。
char b[2][3]={
"a","b","c"};
char b[][3]={
0};
char b[2][]={
0};
char b[][]={
0}
A.char str[2][3]表示声明了一个字符串的数组,最多可以存放两个字符串,每一个字符串的长度为3。题中{“a”,“b”,“c”}为三个字符串。
C.在声明数组时,数组个数可以缺省,数组长度不能缺省。该项中数组长度缺省。
D.同上。
4 数组A=array[1…100,1…100]以行序为主序存储,设每个数据元素占2个存储单元,基地址为10,则LOC[5,5]应为C
1020
1010
818
808
[(5-1)*100+(5-1)]*2+10=818,第一个5表示以行为序列,所以要使用列中的5,而不是使用行中的5,即使用A[5][5]中的第二个5,即(5-1)100(这里的100表示列,相当于A[100][100]中的第二个100,),因为行和列都是从1开始,所以行和列都要-1,每个数据元素占2个存储,所以行和列都要2,基地址为10,意思为首地址为10,所以选818
5 以下操作中,数组比链表速度更快的是____ACE
原地逆序
头部插入
返回中间节点
返回头部节点
选择随机节点
A选项,如果是数组只要遍历一半元素就可以了,翻转的思想类似于字符串逆序,但链表如果要完成逆序,就算只是修改指针也要把所有的元素遍历完,所以相比而言数组还是比链表快的。
B链表只需插入一个节点,数组需移动n个元素
C选项的访问中间节点,数组可以通过array[length/2]访问,链表需要依次查找到中间节点。
D头结点都一样
E 数组是顺序存储的线性表,相对于链表而言主要的优点就是可以通过下标随机访问数组中的任意元素。
6 在表长为n的顺序表上做插入运算,平均要移动的结点数为(C ) 。
n/4
n/3
n/2
n
假设长度为n数组a, 从数组最前(插到a[0]前)到最后(插到a[n-1]后)共n+1种情况,分别需要移动n,n-1,…,0次,每种情况等概率P=1/(n+1), 期望为(n+n-1+…+0)/(n+1) = (1+n)*n/2/(n+1)=n/2
7 需要频繁的插入删除操作使用什么结构比较合适?C
数组
队列
链表
栈
A,数组是连续地址的,插入和删除都需要移动大量元素,不适合插入删除操作
B,队列适合一端插入另一端删除的情况
C,链表适合插入和删除,不需要移动元素
D, 栈适合在同一端插入和删除的操作
在四种结构中,数组是连续占据一块空间,如果进行插入等操作,在中间数据的话就比较困难。而队列和栈,一个是先进先出,一个后进先出,对于插入等更是困难。链表的话,通过修改前一个结点的指向地址,然后将先前指向地址放进去新添加的即可。
数组和链表方式实现顺序表,各有其优缺点。数组的优点是较高的存储效率和快速的随机存取,缺点是数组不能动态的增长,并且在插入和删除时,平均会移动n/2的数据,不适用于随机位置插入和删除很频繁的操作。而链表则恰好具备此优点,一般来说链表的插入和删除基本是固定时间的,链表的缺点是不太适合于随机访问,而在连续访问时,链表也具有很好的表现。
队列(queue)和栈是一种操作受限的线性表。栈的操作受限表现在插入和删除只能对栈顶元素进行,删除的元素永远是最新插入的,即操作遵循后入先出(LIFO)原则。队列中的操作原则与栈的相反。删除的元素是最早插入到队列中的,就像排队一样,排在最前面的人将最先从队伍中出列。这样的操作原则常常称作先入先出。所以对于栈和队列的频繁随机插入删除不合适
8 以下能对一维数组 a 进行正确初始化的语句是( BC )
int a[10]=(0, 0, 0, 0, 0);
int a[10]={
};
int a[]={
0};
int a[10]={
10*a};
9 顺序存储结构的主要缺点是不利于插入或删除操作(√)
在计算机中用一组地址连续的存储单元依次存储线性表的各个数据元素,称作线性表的顺序存储结构.
顺序存储结构是存储结构类型中的一种,该结构是把逻辑上相邻的节点存储在物理位置上相邻的存储单元中,结点之间的逻辑关系由存储单元的邻接关系来体现。由此得到的存储结构为顺序存储结构,通常顺序存储结构是借助于计算机程序设计语言(例如c/c++)的数组来描述的。
顺序存储结构的主要优点是节省存储空间,因为分配给数据的存储单元全用存放结点的数据(不考虑c/c++语言中数组需指定大小的情况),结点之间的逻辑关系没有占用额外的存储空间。采用这种方法时,可实现对结点的随机存取,即每一个结点对应一个序号,由该序号可以直接计算出来结点的存储地址。但顺序存储方法的主要缺点是不便于修改,对结点的插入、删除运算时,可能要移动一系列的结点。
**10 稀疏矩阵一般的压缩存储方式有两种,即 **
三元组和十字链表
所谓三元组就是一个元素存放三个信息,矩阵中的行号,列号以及值,这样就可以不存放值为0的元素,实现压缩。 十字链表相当于是邻接表和逆邻接表的合集,在一个元素里面存放了值以及出度表和入度表,这样也不需要像邻接矩阵那样存放大量0元素,而且找一个节点的入节点和找出节点一样快。
11 数组Q[0…m-1]用来表示一个循环队列, 用front指向队头元素,rear指向队尾元素的后一个位置 ,则当前队列中的元素数是。(队列总的元素数不会超过队列大小) A
(rear-front+m)% m
rear-front+1
rear-front-1
rear-front
因为是循环链表 rear不一定就比front地址高 所以有可能rear-fornt得到结果是负数 所以为了正确性起见需要+m再%m
12 长度为n 的非空顺序表,若在第i个位置插入新的元素X,则i的取值范围是 1≤i≤n+1,需要移动的元素个数为( D )。
i
n-i-1
n-i
n-i+1
新的元素替换掉了原来在i的元素,原先在i位置上的元素以及后面元素都往后移,所以需要 + 1
13 在一个有8个int数据的数组中,随机给出数组的数据,找出最大和第二大元素一定需要进行(B)次比较:
8
9
10
11
14 若数组A[0…m-1][0…n-1]按列优先顺序存储,则aij地址为( A)。
LOC(a00)+[j*m+i]
LOC(a00)+[j*n+i]
LOC(a00)+[(j-1)*n+i-1]
LOC(a00)+[(j-1)*m+i-1]
以0开始,下标是几就是多少个,从1开始,下标减1
15 下列叙述中正确的是( A)。
顺序存储结构的存储一定是连续的,链式存储结构的存储空间不一定是连续的
顺序存储结构只针对线性结构,链式存储结构只针对非线性结构
顺序存储结构能存储有序表,链式存储结构不能存储有序表
链式存储结构比顺序存储结构节省存储空间
1.顺序表的特点是逻辑上相邻的数据元素,其物理存储位置也相邻,并且顺序表的存储空间需要预先分配;
2.链式存储中逻辑上相邻的数据元素其物理存储位置不一定相邻,是因为链表通过指针实现元素间的逻辑关系;
3.顺序存储结构适合频繁的查询时使用,链式存储结构适合频繁的插入,删除和更新元素时使用
链式存储结构既可以针对线性结构也可以针对非线性结构,所以B与C错误。链式存储结构中每个结点都由数据域与指针域两部分组成,增加了存储空间,所以D错误
常见线性结构包括:线性表,栈,队列,数组 常见非线性结构:二维数组,***数组,广义表,树,图 Java中队列都可以通过LinkedList实现,说明链式结构可以实现线性结构
16 希望用最快的速度从一个无序数组中挑选出其中前十个最大的元素,在以下的排序方法中(B)
快速排序
堆排序
归并排序
基数排序
用堆排序最好,因为堆排序不需要等整个排序结束就可挑出前50个最大元素,而快速排序和基数排序都需等待整个排序结束才能知道前50个最大元素。
17 请问对一个排好序的数组进行查找,用平均时间复杂度最小的算法,时间复杂度为(B)
O(n)
O(lgn)
O(nlgn)
O(1)
二分查找的基本思想是将n个元素分成大致相等的两部分,去a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果xa[n/2],则只要在数组a的右半部搜索x.
时间复杂度无非就是while循环的次数!
总共有n个元素,
渐渐跟下去就是n,n/2,n/4,…n/2^k,其中k就是循环的次数
由于你n/2^k取整后>=1
即令n/2^k=1
可得k=log2n,(是以2为底,n的对数)
所以时间复杂度可以表示O()=O(logn)
18 便于插入和删除的容器是(ACD)
list
vector
map
set
1.list 底层数据结构为双向链表,支持快速增删
2.vector 底层数据结构为数组,支持快速随机访问
3.map 底层数据结构为红黑树,除了hashmap无序,其他实现结构有序,不重复
4.set 底层数据结构为红黑树,除了hashset无序,其他实现结构有序,不重复
19 线性表就是顺序存储的表(B)(×)
线性结构与非线性结构,主要看元素之间的关系,如果是一对一的关系则是线性表,如果不是一对一的关系则是非线性表。
线性表可以分顺序存储和链式存储。
线性结构包括顺序存储结构和链接存储结构。所以线性表有两种情况。除了线性结构还有非线性结构,如:树,图。栈和队列就是用线性结构实现的,它本身就是一种结构。可以把栈和队列归在线性结构中
线性表包括顺序存储结构(即顺序表)和链式存储结构(即链表)。但是线性表、树、图 是三种不同的数据结构,树和图不属于线性表的链式结构。
因为数据结构,从逻辑上来分的话,可分为:集合结构、 线性结构、 树形结构、 图形结构。
但是,如果从存储结构来分类,就只有:顺序存储结构和链接存储。 所以,线性结构当然也可分为这两类。
20 假设要存储一个数据集,数据维持有序,对其的操作只有插入、删除和顺序遍历,综合存储效率和运行速度,下列哪种数据结构是最适合的是?B
数组
链表
哈希表
队列
数组插入、删除需要移动数组元素,平均移动n/2
哈希表难以实现顺序遍历
队列插入删除效率低下
数组可以实现顺序遍历但是插入删除操作复杂,平均移动n/2个元素
链表因为存储的地址不连续(逻辑上连续实际上不连续),可以实现顺序遍历
哈希表是随机存储,所以是离散分布,顺序遍历实现不了
队列只可以在队尾插入队头删除,不可以实现中间插入和删除,不满足条件
综上,链表最合适
21 线性表的顺序存储结构是一种(A) 的存储结构,线性表的链式存储结构是一种顺序存取 的存储结构。
随机存取
顺序存取
索引存取
散列存取
顺序存储结构中,数据元素存放在一组地址连续的存储单元中,每个数据元素地址可通过公式LOC(ai)=LOC(a1)+(i-1)L计算得到,从而实现了随机存取。对于链式存储结构,要对某结点进行存取,都得从链的头指针指向的结点开始,这是一种顺序存取的存储结构。
一:顺序表的特点是逻辑上相邻的数据元素,物理存储位置也相邻,并且,顺序表的存储空间需要预先分配。
它的优点是:
(1)方法简单,各种高级语言中都有数组,容易实现。
(2)不用为表示节点间的逻辑关系而增加额外的存储开销。
(3)顺序表具有按元素序号随机访问的特点。
缺点:
(1)在顺序表中做插入、删除操作时,平均移动表中的一半元素,因此对n较大的顺序表效率低。
(2)需要预先分配足够大的存储空间,估计过大,可能会导致顺序表后部大量闲置;预先分配过小,又会造成溢出。
二、在链表中逻辑上相邻的数据元素,物理存储位置不一定相邻,它使用指针实现元素之间的逻辑关系。并且,链表的存储空间是动态分配的。
链表的最大特点是:
插入、删除运算方便。
缺点:
(1)要占用额外的存储空间存储元素之间的关系,存储密度降低。存储密度是指一个节点中数据元素所占的存储单元和整个节点所占的存储单元之比。
(2)链表不是一种随机存储结构,不能随机存取元素。
*22 若有说明语句“int a[10],p=a;”,对数组元素的正确引用是 D
a[p]
p[a]
p+2
*(p+2)
注意 是对数组中元素的引用 a为数组名 也代表数组首元素的地址值 p=a则p也指向数组a的第一个元素地址,则(p+2)指向数组a中第三个元素
23 数组定义为”int a[4][5];”, 引用”*(a+1)+2″表示()(从第0行开始)B
a[1][0]+2
a数组第1行第2列元素的地址
a[0][1]+2
a数组第1行第2列元素的值
a是个行指针,a+1后指向下一行,*(a+1)后变成一个列指针,再+2仍为列指针,指向a数组第一行第二列的元素,选B。题目描述的不准确,第一行也可认为是a[0]。按照给的选项只能选B
23 如果剩下的子序列有奇数个数字,就取中间那个为middle。如果有偶数个数字,取前一半的最后一个为middle。 A
12,18,14,16
12,14, 18,16
6,9,7,8
6,7,9,8
如果剩下的子序列有奇数个数字,就取中间那个为middle。如果有偶数个数字,取前一半的最后一个为middle。
第一次查找到12之后,做指针要移动到12的下一个数再继续查找
24 设循环队列中数组的下标范围是1~n,其头尾指针分别为f和r,则其元素个数为(D)
r-f
r-f+1
(r-f) mod n +1
(r-f+n) mod n
循环队列会空出一个位置,为了判断队列为满的状态,即当(rear+1)mod n==front为满,所以牺牲一个空格,所以rear-front的绝对值为队列中元素的个数(因为rear指向一个尚未填入元素的内存,所以不用加1),(rear-front+n)就是为了保证绝对值,所以为(r-f+n)mod n
举个例子,一个循环队列,队列长度N=10,下标从1-9,能够储存9个元素,index=0处为空。初始时,头指针下标为1,尾指针下标为1。当从队尾入队一个元素,尾指针下标移动,当从队首出队一个元素,头指针下标移动。头指针指向队首,尾指针指向队尾的下一位。 第一步,执行入队操作。入队9个元素,队列满,此时头指针下标为1,尾指针下标为0; 第二步,执行出队操作。头指针向后移动,比如此时出队3个元素,头指针移动到下标指向4,尾指针依然下标为0,此时队列中有6个元素。 第三步,执行入队操作。头指针不变,指向下标为4,加入两个元素,此时尾指针的下标从0指向2,此时队列中有8个元素。 结果:头指针指向4,尾指针指向2,队列中有8个元素。(2+10-4)%10=8 循环队列靠指针来执行入队出队。若用数组实现的普通队列,index=0的元素出队后,要把后面的元素全部遍历一遍做向前移动的操作;若用普通链表实现的队列,出队时要遍历到链表最后一位的前一位,再断开。
25 下列叙述中正确的是( B)
有一个以上根结点的数据结构不一定是非线性结构
只有一个根结点的数据结构不一定是线性结构
循环链表是非线性结构
双向链表是非线性结构
线性结构应满足:有且只有一个根结点与每个结点最多有一个前件,也最多有一个后件,所以 B 正确。所以有一个以上根结点的数据结构一定是非线性结构,所以 A 错误。循环链表和双向链表都是线性结构的数据结构
线性结构:直接前驱和直接后驱的数目至多为1,有且只有一个根节点 树:非线性结构,多个子节点
26 已知int a[3][4];则下列能表示a[1][2]元素值的是A
*(*(a+1)+2)
*(a+1+2)
(&a[0]+1)[2]
*(a[0]+1)
数组名是第一个数组的地址.
注意这里a不是第一个元素的地址,而是第一个维数组的地址,a[0][0]才是表示的一维数组第一个元素的地址.
地址 + 1表示向下移一层.
这是一个三行四列的数组
*(a+1)表示第二行的首地址,和a[1]一样。
*(a+1)+2第二行第三个数字的地址
*(*(a+1)+2)就是第二行第三个数字的值
A, a 是一个二级指针,不是一级指针,*(a+1)表示的第二个数组的地址
B, *(a+1+2)等于*(a+3),是一个int *, 表示的是 第4个数组a[3]的地址,而 **(a+3)表示a[3][0]的值,
*((int *)(a+3)) 也可以表示 a[3][0]的值
C. (&a[0]+1)表示的是第2个数组 a[1]的地址, (&a[0]+1)[2]其实是数组a[3]的地址,改成
((int *)(&a[0]+1))[2] 才是对的
D. *(a[0]+1) 是 a[0][1]的值
27 一个5*4的矩阵,有多少个长方形?(正方形也算是长方形) 150
长任取两个点C(6,2)*宽任取两个点C(5,2) = 15* 10 = 150
28 下面有关数据结构的说法是正确的?B
数组和链表都可以随机访问
数组的插入和删除可以 O(1)
哈希表没有办法做范围检查
以上说法都不正确
数组可以直接通过下标得到存储的值 因此支持随机,访问链表是链式存储结构时无法支持随机访问,要访问一个指定位置的元素必须从头开始做指针移动。哈希表支持直接通过关键码得到值 其实数组就是一种哈希表 下标就是关键码 通过下标直接得到值 因此哈希表肯定需要做范围检查也有办法做范围检查的
在数组的开头或结尾插入和删除 是O(1),但正常情况下为O(n)
所以说数组的插入和删除复杂度可能是O(1)
数组静态分配内存,链表动态分配内存;
数组在内存中连续,链表不连续;
数组元素在栈区,链表元素在堆区;
数组利用下标定位,时间复杂度为O(1),链表定位元素时间复杂度O(n);
数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)。
29 链表与数组的优缺点以下说明正确的是 D
数组动态分配内存,并在内存中连续,链表静态分配内存,但不连续
查询时,数组的时间复杂度为O(n),链表为O(1)
插入或删除时,数组的时间复杂度为O(1),链表为O(n)
数组元素在栈区,链表元素在堆区
解答:数组静态分配内存,链表动态分配内存; 数组在内存中连续,链表不连续; 数组元素在栈区,链表元素在堆区; 数组利用下标定位,时间复杂度为O(1),链表定位元素时间复杂度O(n); 数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)
数组插入或者删除时,一般情况下时间复杂度为O(n),但是在数组尾部进行插入或者删除时间复杂度为O(1).
30 以下错误的是(B)
(1)静态链表既有顺序存储的优点,又有动态链表的优点。所以,它存取表中第i个元素的时间与i无关。
(2)静态链表中能容纳的元素个数的最大数在表定义时就确定了,以后不能增加.
(3)静态链表与动态链表在元素的插入、删除上类似,不需做元素的移动。
(1),(2)
(1)
(1),(2),(3)
(2)
(1)错,(2)(3)对。
静态链表是用数组存储节点数据,模拟链表的实现,但是没有用到指针。每个数组节点包括两部分:data域和cursor(游标)域。data存储数据,cursor指明下个元素在数组中的下标。
(1)存取第i个元素时,需要从头遍历到i-1和元素,由第i-1个节点的cursor,才能知道第i个元素存储的位置,因此和i是相关的。
(2)使用数组对元素进行存储,在定义时大小已经确定。
(3)插入和删除操作无需移动元素,只需要修改cursor游标的值即可,就像修改动态链表中的指针一样。
31 对n个记录的线性表进行快速排序为减少算法的递归(栈)深度,以下叙述正确的是(A)
每次分区后,先处理较短的部分
每次分区后,先处理较长的部分
与算法每次分区后的处理顺序无关
以上三者都不对
解释:
现在有这么个序列:123456789
假设每次划分出短序列的长度为1
即第一次划分
短序列:1
长序列:23456789
如果优先处理短序列1
则栈中仅用保存23456789,深度为1
然后23456789出栈,划分
短序列:2
长序列:3456789
同样的先处理短序列
栈中保存3456789,深度为1
类推下去,处理完整个序列,栈的最大深度都为1
假如每次划分出的短序列长度为2呢
短序列:12
长序列:3456789
优先处理短序列12
栈中保存3456789 深度为1
12只能划分为同样长度的序列1和2
先处理左边的
栈保存2 此时栈中有3456789 和 2 深度为2
然后2 出栈 处理
接着3456789出栈
划分为短序列34
长序列 56789
处理短序列34
栈中保存56789
类推下去,处理完整个序列,栈的最大深度都为2
也就是说栈的最大深度取决于划分出来的短序列的长度 (前提是先处理短序列)
那么先处理长序列呢
短序列:1
长序列:23456789
如果优先处理长序列序列23456789 短序列入栈,长序列划分为2和3456789
2入栈,3456789划分
。。。
8入栈,9处理
此时栈中有12345678 深度为8
短序列:12
长序列:3456789
12入栈 3456789划分为34和56789
34入栈 56789划分为56和789
56入栈 789划分为78和9
9入栈 78划分为7和8
7入栈 8处理
此时栈中有12 34 56 9 7 深度为5
很明显先处理长序列 栈的深度要大于 先处理短序列栈的深度。
32 选项代码中能正确操作数组元素的是(AB)
int main(){
int a[N][N]={
{
0,0},{
0,0}};
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
//访问二维数组a的值
//选项代码
}
}
}
*(*(a+i)+j)=1
*(a[i]+j)=1
**(a+i)[j]=1
*((a+i)+j)=1
数组名当被直接使用时,是一个指向数组首地址的指针。如果数组是***数组,那么数组名是指向第一行数组的首地
址,而不是第一行第一列单个元素的地址,所以*(a+i)与a[i]是一个意思,当直接用a[i]时代表的是该一维数组的
首地址,所以*(a[i]+j)是与a[i][j]等效,所以AB选项正确
a[i] 和*(a+i)表示的是一个意思,所以对于二维数组也一定要注意区分
33 二维以上的数组其实是一种特殊的广义表(√)
广义表(Lists,又称列表)是一种非线性的 数据结构 ,是 线性表 的一种推广。即广义表中放松对表元素的原子限制,容许它们具有其自身结构
二维数组也可以看成是一维数组,只不过这个一维数组的类型为数组
广义表是线性表的一种推广。而一个线性表是n个具有相同特性的数据元素的有限序列。比如二维数组,则可以认为是数组元素为一个数组的广义表。
广义表和线性表是数据结构方面的概念,它们都被定义为一个有限的序列(a1,a2,a3,…,an)。只不过线性表中ai被限定为单个的元素,而广义表中ai可以是单个元素,也可以是一个子广义表。所以线性表可以用数组这种顺序存储结构来表示,也可以用链表来表示。而广义表一般只能用链表来表示。
34 定义语句"double * array [8]"的含义正确的是(B)
array是一个指针,它指向一个数组,数组的元素时是双精度实型
array是一个数组,数组的每一个元素是指向双精度实型数据的指针
C语言中不允许这样的定义语句
以上都不对
指针数组( * stings[] ):可以说成是”指针的数组”,首先这个变量是一个数组,其次,”指针”修饰这个数组,意思是说这个数组的所有元素都是指针类型,在32位系统中,指针占四个字节。
数组指针( (*strings)[] ):可以说成是”数组的指针”,首先这个变量是一个指针,其次,”数组”修饰这个指针,意思是说这个指针存放着一个数组的首地址,或者说这个指针指向一个数组的首地址。
35 下面的说法那个正确 C
#define NUMA 10000000
#define NUMB 1000
int a[NUMA], b[NUMB];
void pa()
{
int i, j;
for(i = 0; i < NUMB; ++i)
for(j = 0; j < NUMA; ++j)
++a[j];
}
void pb()
{
int i, j;
for(i = 0; i < NUMA; ++i)
for(j = 0; j < NUMB; ++j)
++b[j];
}
pa 和 pb 运行的一样快
pa 比 pb 快
pb 比 pa 快
无法判断
pa是执行1000次1000万连续地址的相加,pb是执行1000万次1000连续地址的相加,虽然相加次数是一样的,但是pa数组较长,跨的页较多,所以会产生较多次的缺页,导致执行速度较pb慢
在多重循环中,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨切循环层的次数
36 下列哪些不是线性表?C
队列
栈
关联数组
链表
关联数组 (英语:Associative Array),又称映射(Map)、字典( Dictionary)是一个抽象的数据结构,它包含着类似于(键,值)的有序对。
线性表具有如下的结构特点:
1.均匀性:虽然不同数据表的数据元素可以是各种各样的,但对于同一线性表的各数据元素必定具有相同的数据类型和长度。
2.有序性:各数据元素在线性表中的位置只取决于它们的序号,数据元素之前的相对位置是线性的,即存在唯一的“第一个“和“最后一个”的数据元素,除了第一个和最后一个外,其它元素前面均只有一个数据元素(直接前驱)和后面均只有一个数据元素(直接后继)。
关联数组:关联数组和数组类似,它包含着类似于(键,值)的有序对,是一种具有特殊索引方式的数组,关联数组的元素没有特定的顺序。
*37 若已定义: int a[]=[0,1,2,3,4,5,6,7,8,9],p=a,i; 其中0≤i≤9,则对a数组错误的引用是(D)
a[p-a]
*(&a[i])
p[i]
a[10]
数组名就是数组的首地址,此时p和a相等,即[p-a]就是 a[0].
*(&a[i])就是a[i]
p[i]相当于a[i]
p+i是指向数组a[i]的指针。
38 char str[]=”Hello”,sizeof(str)=(C)
4
5
6
7
实际存储为{‘H’,‘e’,‘l’,‘l’,‘o’,’\0’},所以是6个
sizeof计算长度包括字符串结束符\0
strlen不包括
#include "stdio.h"
int main() {
char str[] = "hello";
char *s = "hello";
int a[] = {
3, 5, 7};
printf("%d\n%d\n%d\n", sizeof(str), sizeof(s), sizeof(a));//输出6, 4, 12
//在32位系统中,指针占4个字节
return 0;
}
39 广义表(((a,b,c),d,e,f))的长度是4(×)
应该是1,注意有三对括号
广义表即我们通常所说的列表(lists)。它放松了对表元素的原子性限制,允许他们有自身结构。
广义表的长度:最大括号中的 逗号数+1
广义表的深度:展开后含括号的层数。
40 在定义 int a[3][4][2]; 后,第 20 个元素是( A )
a[2][1][1]
a[1][0][1]
a[2][0][1]
a[2][2][1]
三维数组可以看成是一本书!
int a[3][4][2]; 就是有3页每页4行2列
高行列
41 一个非空广义表的表尾(B)
不能是子表
只能是子表
只能是原子
是原子或子表
(1)《数据结构》对广义表的表头和表尾是这样定义的:
如果广义表LS=(a1,a2…an)非空,则 a1是LS的表头,其余元素组成的表(a2,a3,…an)是称为LS的表尾。
根据定义,非空广义表的 表头是一个元素,它 可以是原子也可以是一个子表, 而表尾则必定是子表。例如:LS=(a,b),表头为a,表尾是(b)而不是b.另外:LS=(a)的表头为a,表尾为空表().
(2)非空广义表,除表头外,其余元素构成的表称为表尾,所以非空广义表尾一定是个表
==非空广义表的表头可以是原子或子表,表尾一定是子表 ==
42 链表和数组的区别 ABC。
在有序的情况下搜索
插入和删除
随机访问
数据存储类型
ABC。BC是显而易见的答案。有序时数组可以进行折半查找,效率高;但是链表不行,所以A也是对的
43 则能将字符串 books 存放到数组 s1 的正确语句是( A)
strcpy(s1, s2);
s1 = {
"books"};
s1 = s2;
strcpy(s2, s1);
数组名代表的是数组的首地址,是一个地址常量,所以不能给数组名赋值(函数定义的形参列表传入的是指向数组的指针变量,可以变化)C错误
char *strcpy(char *dest, const char *src)
44 设有一个 10 阶的对称矩阵 A ,采用压缩存储方式,以行序为主存储, a1 , 1 为第一个元素,其存储地址为 1 ,每个元素占 1 个地址空间,则 a8 , 5 的地址为 。 (33)
对称矩阵,只需要存一半就行了, 第一行:1个 第二行:2个 第三行:3个 ………… ………… 第八行:1~5,前5个 所以:1+2+3+4+5+6+7 再加 5 总共得:33
45以下叙述正确的是( D )
char a[] = "ABCDEF";
char b[] = {
'A','B','C','D','E','F'};
a 与 b 数组完全相同
a 与 b 长度相同
a 和 b 中都存放了字符串
a 数组比 b 数组长
题目说的是长度,应该是strlen(),对a求长度为6,但是对b求长度是一个未知的大小,应该strlen()直到遇到’\0’才停止,所以a,b之间的长度不能比较,sizeof是大小,sizeof(a)=7,sizeof(b)=6,应该把题目的长度换成大小
46 关于 Array 数组对象的说法不正确的是(B)
push()向数组的末尾添加一个或更多元素,并返回新的长度
pop()删除并返回数组的第一个元素
unshift()向数组的开头添加一个或更多元素,并返回新的长度
join()把数组的所有元素放入一个字符串
一、push方法是向数组末尾添加一个或者多个元素,并返回新的长度
二、pop方法删除数组的最后一个元素,把数组的长度减1,并且返回它被删除元素的值,如果数组变为空,则该方法不改变数组,返回undefine值
三、unshift()方法是向数组的开头添加一个或多个元素,并且返回新的长度
四、shift()方法和unshift()方法恰恰相反。该方法用于把数组的第一个元素从其中删除,并返回被删除的值。如果数组是空的,shift()方法将不进行任何操作,返回undefined的值。 五,join()方法用于把数组中的所有元素放入一个字符串。元素是通过指定的分隔符进行分隔的。
47 以下关于链表和数组说法正确的是(ABC)
new出来的数组也在堆中
数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)
数组利用下标定位,时间复杂度为O(1),链表定位元素时间复杂度O(n)
对于add和remove,ArrayList要比LinkedList快
数组从栈中分配空间,链表从堆中分配空间
数组定义要给定大小,而链表大小未知,所以在堆中分配,所以数组都是在栈里面,
数组分配的空间也要分情况:静态分配在栈中,动态分配在堆中,全局数组在静态存储区
数组属于引用变量,存放在堆里面。
48 在C语言中,顺序存储长度为3的字符串,需要占用( 4 )个字节。
C语言中,字符串默认每个占用1字节,末尾还有’\0’,所以一共是4字节
char 、short 、int各占1、2、4个字节;并且字符串结尾有结尾符,所以答案为(3 + 1)
字符串末尾有’\0’
49 设数组a[]作为循环队列SQ的存储空间,数组的长度为m,f为队头指示,r为队尾指示则执行出队操作的语句为 B
f=f+1
f=(f+1)%m
r=(r+1)%m
f=(f+1)%(m+1)
循环队列的相关条件和公式:
队尾指针是rear,队头是front,其中QueueSize为循环队列的最大长度
1.队空条件:rear==front
2.队满条件:(rear+1) %QueueSIze==front
3.计算队列长度:(rear-front+QueueSize)%QueueSize
4.入队:(rear+1)%QueueSize
5.出队:(front+1)%QueueSize
注意:公式中的real是指向最后队尾元素的下一个元素的地址,并且一个长度为m的循环队列,规定最多只可存m-1个元素(队满),会有一个空的空间
50 优先级队列和有序数组的一个区别是(A)
最低优先级别的数据项不能从数组中轻易的提取出来,而在优先级队列中可以。
数组必须是有序的,而优先级队列不需要。
最高优先级的数据项可以很容易地从优先级队列中提取出来,而有序数组不行。
其他三个选项都是。
A.最大堆你可以想象成一颗二叉树,堆顶元素一定是最大值,然后它的每一棵子树也都是最大堆。优先队列的默认实现是最大堆,但是里面有个参数可以设置,设置之后就是最小堆。所以A是对的,最低优先级可以提取 B.数组和优先队列都不是有序的 C.有序数组是一种特殊的数组,里面的元素,按一定的顺序排列。有序数组可以直接提取最高优先级的元素
51 将10阶对称矩阵压缩存储到一维数组A中,则数组A的长度最少为 C
100
40
55
80
主对角线都存:10个,剩下的90个只存一半45个,共55个
52 集合与线性表的区别在于是否按关键字排序(×)
网上答案参差不齐呀
53 不能表示字符‘o’的是(A)
若定义:char s[20]="programming",*ps=s ;
ps+2
s[2]
ps[2]
*(ps+2)
A项,ps为指针,ps+2为一个地址,因此不能表示字符‘o’。
B项和C项,当ps为指针时,ps[2]等价于s[2],表示的都是数组中的第3个元素。前者表示指针名称加下标引用元素,而后者表示数组名称加下标来引用元素。因此B和C正确。
D项,*(ps+2),取到了ps[2]的值,因此为‘o’。因此D正确。
54 线性表是 A
一个有限序列,可以为空
一个有限序列,不可以为空
一个无限序列,可以为空
一个无限序列,不可以为空
线性表是有头和尾的 和线段一样
55 最坏情况下,合并两个大小为n的已排序数组所需要的比较次数___B__。
2n
2n-1
2n+1
2n-2
最坏情况为: 每比较一次,只确定一个元素的位置(最后一次比较确定两个元素的位置,即倒数第一个和倒数第2个),所以总的最坏比较次数为2n-1.
挖2n个坑,对每一个坑进行循环,比较两排带头的人,谁大谁先跳,总共比较2n-1次,最后一个不用比了,因为就剩你了。
*56 若有定义"char a [10], p=a; ”,那么下列赋值语句正确的是(D )
a [] ="abcdefg";
a=”abedefg";
*p=”abcdefg";
p=”abcdefg ";
A选项,应该是a[10]=“abcdefg”
B选项,a是数组首地址不能这样赋值
C选项,*p=a,也是指针地址变量,不能这样赋值
D正确
p表示一个指向,同样指向的是数组a的第一个位置处,那么目的是为了字符串赋值,因此我要把p所指向的内容改成"abcdefg",因此之后输出时取p相当于输出第一个a;输出p相当于输出整个abcdefg
57 一个有序数列,序列中的每一个值都能够被2或者3或者5所整除,这个序列的初始值从1开始,但是1并不在这个数列中。求第1500个值是多少?
2040
2042
2045
2050
设x个数,x/2+x/3+x/5-x/6-x/10-x/15+x/30=1500解出来就行了
翻译过来是:在x以内,能整除2的有x/2个数,整除3的有x/3个数…但这些数有重复的,需要利用容斥原理去重: A∪B∪C = A+B+C - A∩B - B∩C - C∩A + A∩B∩C; 求第1500个满足整除条件的x
在区间 [1, 30] 中,
能被2整除的数有 30 / 2 = 15 个,
能被3整除的数有 30 / 3 = 10 个,
能被5整除的数有 30 / 5 = 6 个,
能被2整除也能被3整除的数有 30 / 6 = 5 个,
能被2整除也能被5整除的数有 30 / 10 = 3 个,
能被3整除也能被5整除的数有 30 / 15 = 2 个,
能被2整除、能被3整除也能被5整除的数有 30 / 30 = 1 个,
根据集合的容斥定律可知:A∪B∪C = A + B + C - A ∩ B - B ∩ C - A ∩ C + A ∩ B ∩ C,
因此,能被2整除或能被3整除或能被5整除的数的个数(不重复)为: 15 + 10 + 6 - 5 - 3 - 2 + 1 = 22
1500 / 22 = 68 ··· 4,[ 1, 30] 中,第4个满足条件的数是 5 ,而 68 * 30 = 2040, 因此第1500个数为
2040 + 5 = 2045
58 数组可看成线性结构的一种推广,因此与线性表一样,可以对它进行插入,删除等操作(×)
怎么说呢,本人认为这道题目,没有问题。
这道题错就错在,“因此与线性表一样,可以对它进行插入,删除等操作”,注意,数组的插入、删除操作,和线性表是不一样的,虽然数组可以表示线性表,但数组终究不是线性表。
建议大家去看两个词条:
线性表和线性结构,
从根本上理解理解这两个概念。
数据结构浅析(4)-线性结构:线性表
59 下列叙述哪些是对的?CD
线性表的逻辑顺序与物理顺序总是一致的。
线性表的顺序存储表示优于链式存储表示。
线性表若采用链式存储表示时所有结点之间的存储单元地址可连续可不连续。
二维数组是每个元素都为顺序表的顺序表 .
每种数据结构都应具备三种基本运算:插入、删除和搜索。
关于E选项,栈就没有搜索操作。
A中线性表的顺序存储结构中逻辑顺序与物理顺序总是一致的,但链式存储结构却不是,
B:两种存储结构没有优劣之分,只是看在什么情况下适合哪种存储结构。对于经常插入或删除的
适合选择链式存储,经常查找的适合顺序存储。
CD正确
E中数据结构的基本运算中,搜索肯定不是必须的,比如栈中就没有搜索
D中顺序存储是指存储地址连续
60 下列关于线性表中的链表描述正确的是?ABCD
适用于数据项数量不能预知的情况。
逻辑相邻的2元素的存储空间可以是不连续的。
链表节点一般有数据元素和指针域两部分组成。
存储空间需要动态分配。
D选项有争议 有说法指出链表分两种,一种是动态链表一种是静态链表,对于静态链表来说存储空间不需要动态分配
61 如有定义:char str[20];,能将从键盘输入的字符串“How are you”保存到 str 数组的语句是(C )
scanf("%s", str);
str[] = getch();
gets(str);
str = gets();
scanf不能输入空格,而gets函数却可以。
gets(字符数组名或指针)
gets能够接受空格、制表符Tab和回车等。
gets和sacnf函数,在字符串接受结束后自动加’\0’
getch()函数从控制台读取一个字符
62 以下能对一维数组 a 进行正确初始化的语句是(ABC)
int a[10]={
0, 0, 0, 0, 0};
int a[10]={
};
int a[]={
0};
int a[10]={
10*a};
数组的初始化:
1、a[10] = {1,2,3};//随后元素补零
2、a[] = {1,2}//编译器自动计算元素个数,相当于a[2] = {1,2};
3、a[10] = {}//编译器自动将所有元素置零
63 数组元素的地址计算与数组的存储方式无关。请问这句话的说法是正确的吗? ×
二维数组存储方式可以分为行优先和列优先俩种,所以数组的地址计算和数组的存储方式有关。
64 在程序设计中,要对两个16K×16K的多精度浮点数二维数组进行矩阵求和时,行优先读取和列优先读取的区别是(B)
没区别
行优先快
列优先快
2种读取方式速度为随机值,无法判断
如果数组很大的话应该是行优先快,因为数组在内存中是按行优先存储的,在虚存环境下,如果整个数组没有在内存中的话可以比列优先减少内存换进换出的次数。就算整个数组都在内存中,列优先访问a[i][j]还得计算一次乘法,行优先只需加一就可以了,这个可以忽略
二维数组是默认的存储模式是行优先存储,也就是每行的数据都是连续的,而每列的数据是不连续的,所以按行访问更快。况且这是个长宽相等的方正
若在内存中,则数据可以”随机存取”,但内存数据被读取或写入时,所需要的时间与这段信息所在的位置无关.但是在读取和写入磁盘时,其所需要的时间与位置就会有关系.因为在BASIC,PASCAL和C/C++语言中,数组的存放是按照行优先来存放的,按行号第一行第二行…以此类推.本体关键是考察内存抖动的问题,如果按列访问则需要跳过一大串内存地址,这样可能需求的内存地址不在当前页中则需要进行页置换,这样便需要硬盘IO,减低速度.
65 当很频繁地对序列中部进行插入和删除操作时,应该选择使用的容器是(B)
vector
list
deque
stack
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。
用运算符sizeof 可以计算出数组的容量(字节数)
指针可以随时指向任意类型的内存块。
用运算符sizeof 可以计算出指针所指向内容的容量(字节数)
A.堆上创建动态数组
B.sizeof(数组名)就是数组的容量
C.const指针不可以
D. char* str = “hello”; sizeof(str)不能计算出内容的容量,只是指针的容量。
67 下列数据结构具有记忆功能的是?C
队列
循环队列
栈
顺序表
栈是限定在一端进行插入与删除的线性表,允许插入与删除的一端称为栈顶,不允许插入与删除的另一端称为栈底。栈按照“先进后出”(FILO)或“后进先出”(LIFO)组织数据,栈具有记忆作用
可以用浏览网页的情况来理解,我们在浏览第一个网页A,点网页里的一个标题,进入网页B,再在网页B里点击一个标题,进入网页C,这时连续按后退退回网页A,这说明浏览网页有记忆功能,栈的原理跟这差不多,所以说它有记忆功能,自己再想象一下
68 数组就是矩阵,矩阵就是数组,这种说法( ×)。
数组中的元素可以是字符等
矩阵中的只能是数
数组是一种顺序存储的结构,矩阵是一种逻辑结构,可以使用数组,也可以使用链表。
数组和矩阵不同,数组元素可以是字符,即字符数组,矩阵中都是数
69 下列说法正确的是(ABD)
二维以上的数组其实是一种特殊的广义表
数组一旦建立,结构的元素个数和元素间的物理存储关系就不再变化
数组是一种线性结构,因此只能用来存储线性表
数组采用顺序存储方式表示
对于选项c,因为数组也可以用来存储完全二叉树。
70 用一维数组存储二叉树时,总是以前序遍历顺序存储结点(×)
总是以层次遍历的顺序存储,并且按照完全二叉树的方式建立,所以有很多空节点,会浪费存储空间,完全二叉树可以非常方便地找到孩子兄弟和双亲
二叉树的存储结构分为顺序存储和链式存储。 顺序存储:即用一维数组存储二叉树中的结点。采用层次遍历,从上至下从左到右依次存储,根节点存储在下标为1的位置,对于任意位置i的结点,其左子树位于2i,右子树位于2i+1(画图,依次对二叉树结点标号易得),则树结点的序号可以唯一反映出结点的逻辑关系。完全二叉树和满二叉树采用顺序存储比较合适。非完全二叉树需要添加空结点使之变成完全二叉树进行顺序存储,但是这样可能造成空间的浪费。 链式存储结构:用链表表示二叉树。每个结点存储自身的数据以及两个分别指向左孩子和右孩子结点的指针。(lchild, data, rchild)
71 A为整数数组, N为A的数组长度,请问执行以下代码,最坏情况下的时间复杂度为_B___。
void fun(int A[], int n) {
for (int i = n - 1; i >= 1; i--) {
for (int j = 0; j < i; j++) {
if (A[j] > A[j+1]) {
int tmp = A[j + 1];
A[j + 1] = A[j];
A[j] = tmp;
}
}
}
}
O(N)
O(N^2)
O(Nlog(N))
O(log(N))
O(N^3)
无法确定
冒泡排序法,最坏情况为(n-1)+(n-2)+……+1=n(n-1)/2 所以复杂度是N^2
72 线性表的顺序存储结构是一种( A )的存储结构。
随机存取
顺序存取
索引存取
散列存取
所谓“随机存取”,指的是当存储器中的消息被读取或写入时,所需要的时间与这段信息所在的位置无关,所以叫随机。
线性表的顺序存储结构指的就是数组那样的结果,存储和存取不一样,随机存取指的是可以通过下标去任意的访问数据
每一个数据元素的存储位置都和线性表的起始位置相差一个和数据元素在线性表中的位序成正比的常数。由此,只要确定了存储线性表的起始位置,线性表中任一元素都可随机存取,所以线性表的顺序存储结构是一种随机存取的存储结构。
73 稀疏矩阵压缩存储后,必会失去随机存取功能(√)
稀疏矩阵在采用压缩存储后将会失去随机存储的功能。因为在这种矩阵中,非零元素的分布是没有规律的,为了压缩存储,就将每一个非零元素的值和它所在的行、列号做为一个结点存放在一起,这样的结点组成的线性表中叫三元组表,它已不是简单的向量,所以无法用下标直接存取矩阵中的元素。
特殊矩阵和稀疏矩阵哪一种压缩存储后失去随机存取的功能?为什么?
答:特殊矩阵指值相同的元素或零元素在矩阵中的分布有一定规律,因此可以对非零元素分配单元(对值相同元素只分配一个单元),将非零元素存储在向量中,元素的下标i和j和该元素在向量中的下标有一定规律,可以用简单公式表示,仍具有随机存取功能。而稀疏矩阵是指非零元素和矩阵容量相比很小(t<<m*n),且分布没有规律。用十字链表作存储结构自然失去了随机存取的功能。即使用三元组表的顺序存储结构,存取下标为i和j的元素时,要扫描三元组表,下标不同的元素,存取时间也不同,最好情况下存取时间为O(1),最差情况下是O(n),因此也失去了随机存取的功能。
74 广义表的取表尾运算,其结果通常是个表,但有时也可是个单元素值(×)
表尾是指除去表头后剩下的元素组成的表,表头可以为表或单元素值
表尾一定是广义表,但表头不一定是
表头可以为表或单元素值
表尾是指除去表头后剩下的元素组成的表(即使只剩一个元素也视为表),可以为空表
75 线性结构的是(ABC)
串
链式存储栈
顺序存储栈
顺序存储二叉树
常用的线性结构有:线性表,堆栈,队列,双队列,数组,串。
常见的非线性结构有:二维数组,***数组,广义表,树(二叉树等),图。
线性结构指的是逻辑结构,而不是物理存储结构
线性是线性,顺序是顺序,线性是逻辑结构,顺序是存储结构,两者不是一个概念,线性是指一个元素后继只有唯一的一个元素或节点,非线性是一个元素后面可以有多个后继或前继节点,顺序是指存储结构连续,例如数组是顺序的,链表不是顺序的,但他们都是线性的。当然顺序也可以是非线性的,例如顺序结构存储非线性结构的二叉树!!!
76 下列叙述中正确的是(D )
char s[ ]=”china”; char *p; p=s;
s 和 p 完全相同
数组 s 中的内容和指针变量 p 中的内容相等
s 数组长度和 p 所指向的字符串长度相等
*p 和 s[0]值相等
77 下列哪两个数据结构,同时具有较高的查找和删除性能?(CD)
有序数组
有序链表
AVL树
Hash表
由上图可见,平衡二叉树的查找,插入和删除性能都是O(logN),其中查找和删除性能较好;哈希表的查找、插入和删除性能都是O(1),都是最好的。