数据结构习题记录-牛客网

下列哪两个数据结构,同时具有较高的查找和删除性能?()  AVL树 Hash表
以下操作中,数组比线性表速度更快的是____    返回中间节点 选择随机节点
当很频繁地对序列中部进行插入和删除操作时,应该选择使用的容器是()  list
stl提供了三个最基本的容器:vector,list,deque。
vector和built-in数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随即存取,即[]操作符,但由于它的内存空间是连续的,所以在中间进行插入和删除会造成内存块的拷贝,另外,当该数组后的内存空间不够时,需要重新申请一块足够大的内存并进行内存的拷贝。这些都大大影响了vector的效率。
list就是数据结构中的双向链表(根据sgi stl源代码),因此它的内存空间可以是不连续的,通过指针来进行数据的访问,这个特点使得它的随即存取变的非常没有效率,因此它没有提供[]操作符的重载。但由于链表的特点,它可以以很好的效率支持任意地方的删除和插入。
deque是一个double-ended queue,它的具体实现不太清楚,但知道它具有以下两个特点:
它支持[]操作符,也就是支持随即存取,并且和vector的效率相差无几,它支持在两端的操作:push_back,push_front,pop_back,pop_front等,并且在两端操作上与list的效率也差不多。

因此在实际使用时,如何选择这三个容器中哪一个,应根据你的需要而定,一般应遵循下面
的原则:
  1、如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector
  2、如果你需要大量的插入和删除,而不关心随即存取,则应使用list
  3、如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque。

vector为存储的对象分配一块连续的地址空间,因此对vector中的元素随机访问效率很高。在vecotor中插入或者删除某个元素,需要将现有元素进行复制,移动。如果vector中存储的对象很大,或者构造函数复杂,则在对现有元素进行拷贝时开销较大,因为拷贝对象要调用拷贝构造函数。对于简单的小对象,vector的效率优于list。vector在每次扩张容量的时候,将容量扩展2倍,这样对于小对象来说,效率是很高的。
list中的对象是离散存储的,随机访问某个元素需要遍历list。在list中插入元素,尤其是在首尾插入元素,效率很高,只需要改变元素的指针。

综上所述:
vector适用:对象数量变化少,简单对象,随机访问元素频繁
list适用:对象数量变化大,对象复杂,插入和删除频】
来源:
A,B两个整数集合,设计一个算法求他们的交集,尽可能的高效。 如果是有序的用二路归并求交集 如果是无序的可以用map或hash
链表和数组的区别。  在有序的情况下搜索 、插入和删除、随机访问
以下数据结构属于非线性数据结构的是  二叉树
数据的逻辑结构分为线性结构和非线性结构。
常用的线性结构有:线性表,栈,队列,双队列,数组,串。
常见的非线性结构有:二维数组,多维数组,广义表,树(二叉树等),图。
稀疏矩阵一般的压缩存储方法有两种,即()   三元组和十字链表
数组是一种线性结构,因此只能用来存储线性表()  错,比如可以存储完全二叉树,完全二叉树按层序遍历,从上到下,从左到右的编号
有两个从小到大排好序的数组,长度分别为N和M,将这两个数组合并成一个有序数组的最小比较次数是? Min(N, M)
10  用向量和单链表示的有序表均可使用折半查找方法来提高查找速度()。错, 折半查找只针对顺序存储结构
11  对n个记录的线性表进行快速排序为减少算法的递归深度,以下叙述正确的是()  每次分区后,先处理较短的部分
12  编程实现删除数组中的重复元素。
public static void main(String[] args) {
      int j=0;
      String a[]={"1","2","2","3"};
      Set c=  new HashSet();
      for(int i=0;i


13  和顺序栈相比,链栈有一个比较明显的优势是()  通常不会出现栈满的情况
14  ArrayLists和LinkedList的区别,下述说法正确的有? 
  1. ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 
  2. 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 
  3. 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
  4. ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间。
15  递归式的先序遍历一个n节点,深度为d的二叉树,需要栈空间的大小为______。  O(d)
16  若用一个大小为6的数组来实现循环队列,且当前rear和front的值分别为0和3,当从队列中删除一个元素,再加入两个元素后,rear和front的值分别为多少?()
循环队列是解决假溢出的问题,通常把一维数组看成首尾相接。在循环意义下的加1运算通常用求模运算来实现。所以入队和出队时的操作分别为:rear=(rear+1)%m,front=(front+1)%m。
删除操作:front=(3+1)%6=4;
两次增加操作:rear1=(0+1)%6=1; rear=(rear1+1)%6=(1+1)%6=2

17  栈和队的共同点是()  
只允许在端点处插入和删除元素
18  现有一个循环队列,其队头指针为 front,队尾指针为 rear,循环队列的总长度为 N,问怎么判断循环队列满了?
  1. 当队列不为空时,front指向队列的第一个元素,rear指向队列最后一个元素的下一个位置。
  2. 当队列为空时,front=rear
  3. 队列满时:(rear+1)%maxsiz=front,少用一个存储空间,也就是数组的最后一个存数空间不用

19  有一个用数组C[1..m]表示的环形队列,m为数组的长度。假设f为队头元素在数组中的位置,r为队尾元素的后一位置(按顺时针方向)。若队列非空,则计算队列中元素个数的公式应为?
(m+r-f)mod m
20  需要借助于一个队列来实现DFS算法()?
错,DFS是深度优先搜索,是后进先出,所以需要借助于一个栈来实现。而BFS,也就是广度优先搜索才是借助一个队列来实现
21  已知一棵二叉树,如果先序遍历的节点顺序是:ADCEFGHB,中序遍历是:CDFEGHAB,则后序遍历结果为:()

解析:由先序遍历序列和中序遍历序列可以唯一确定树的结构

步骤: 由先序序列确定根节点;按根节点把中序序列分为两端,前面的是左子树,后面的是右子树;对左右子树重复前面的步骤

还原树形结构:

根节点:   A

            D          B

     C        E

F      G

H

后续遍历序列:CFHGEDBA

22  什么是平衡二叉树?
平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。构造与调整方法 平衡二叉树的常用算法有红黑树、AVL、Treap等。 最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。

23  写一个函数,输入一个二叉树,树中每个节点存放了一个整数值,函数返回这棵二叉树中相差最大的两个节点间的差值绝对值。请注意程序效率。
int find(BinaryTreeNode *pRoot) 
{ 
    static int min = MIN;//定义一个足够大的数 
    static int max = MAX;//定义一个足够小的数 
    if(min>pRoot->val) 
        min = pRoot->val; 
    if(maxval) 
        max = pRoot->val; 
    if(pRoot->lChild!=NULL) 
        find(pRoot->lChild); 
    if(pRoot->rChild!=NULL) 
        find(pRoot->rChild); 
    return max-min; 
} 
24  执行()操作时,需要使用队列做辅助存储空间 
广度优先搜索网
25  简要介绍树的广度优先搜索算法?
宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。 Prim 最小生成树算法采用了和宽度优先搜索类似的思想。其别名又叫 BFS ,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位址,彻底地搜索整张图,直到找到结果为止。
26  一个二叉树有N个度为2的节点,求叶节点的数目为多少? 
N+1
27  设一棵二叉树中有3个叶子结点,有8个度为1的结点,则该二叉树中总的结点数为多少个?
要用到数据结构里面的一个定理
设T是由n个结点构成的二叉树,其中,叶子结点个数为n0,次数为2的结点个数为n2,则有:
                n0=n2+1
所以结点个数:叶子结点(3)+次数为1的结点(8)+次数为2的结点(2) =13 ,选B
28  一棵完全二叉树上有1001个结点,其中叶结点的个数是() 
501
29  若度为m的哈夫曼树中,其叶结点个数为n,则非叶结点的个数为() 
[(n-1)/(m-1)]
30  有n个元素的完全二叉树的深度是 
D(n)=1+log2(n)
31  利用二叉链表存储树,则根结点的右指针是()     
KONG
32  邻接矩阵一定为对称矩阵的图是?  邻接矩阵一定为对称矩阵的图是?
33  有ABCDEF 六个城市,每一个城市都和其他所有城市直接相连,问从A——B有多少种连接方式,路径不允许在两个城市之间往返
A-B:1
A-?-B:4
A-?-?-B:4*3
A-?-?-?-B:4*3*2
A-?-?-?-?-B:4*3*2*1

34  图中有关路径的定义是() 
由顶点和相邻顶点序偶构成的边所形成的序列
35  设无向图的顶点个数为n,则该图最多有()条边
n(n-1)/2
36  图的BFS生成树的树高比DFS生成树的树高()
小或相等
37  无向图G=(V,E),其中:V={a,b,c,d,e,f},E={(a,b),(a,e),(a,c),(b,e),(c,f),(f,d),(e,d)},对该图进行深度优先遍历,得到的顶点序列正确的是()
假设给定图G的初态是所有顶点均未曾访问过。在G中任选一顶点v为初始出发点(源点),则深度优先遍历可定义如下:
首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止。若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。
图的深度优先遍历类似于树的前序遍历。采用的搜索方法的特点是尽可能先对纵深方向进行搜索。这种搜索方法称为深度优先搜索(Depth-First Search)。相应地,用此方法遍历图就很自然地称之为图的深度优先遍历。
深度优先遍历的顺序有a,b,e,d,f,c、、、、a,e,d,f,c,b、、、、、a,e,b,d,f,c、、、、、a,c,f,d,e,b.
38  假定有k个关键字互为同义词,若用线性探测法把这k个关键字存入哈希表中,至少要进行多少次探测?() 
k(k+1)/2次
至少需要 1 + 2 + ... + k-1+k = k(k+1)/2 次探测
这些同义词散列到一个hash点, 按线性探测法, 第一次之前没有点, 探测1次, 第二次, 前面有一个点, 要探测两次, 以此类推, 得到上述答案
39  下列哪两个数据结构,同时具有较高的查找和删除性能?()  
AVL树 Hash表
40  散列文件使用散列函数将记录的关键字值计算转化为记录的存放地址。由于散列函数不是一对一的关系,所以选择好的( )方法是散列文件的关键。 
散列函数和冲突处理
41  执行()操作时,需要使用队列做辅助存储空间 
广度优先搜索网
深度优先搜索和谦虚二叉遍历都类似图的深度遍历,都借助栈的数据结构;
广度优先相关的借助了队列的数据结构,类似图的层序遍历。
42  HASHMAP,HASHTABLE区别。
1.Hashtable是Dictionary的子类,HashMap是Map接口的一个实现类;
2.Hashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。
3.在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。

43  设有n个关键字具有相同的Hash函数值,则用线性探测法把这n个关键字映射到Hash表中需要做几次线性探测? 
n*(n-1)/2
44  基于哈希的索引和基于树的索引有什么区别?
  1. hash索引仅满足“=”、“IN”和“<=>”查询,不能使用范围查询
  2. hash索引无法被用来进行数据的排序操作
  3. 对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用
  4. Hash 索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高
45  由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况, 通常有两类方法处理冲突:开放定址(Open Addressing)法和拉链(Chaining)法。 在用拉链法构造的散列表中,删除结点的操作易于实现,链法的缺点是:指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间
46  下列哪些方法可以用作Hash函数的构造方法?
  1. 平方取中法:先通过求关键字的平方值扩大相近数的差别,然后根据表长度取中间的几位数作为散列函数值。
  2. 除余法:它是以表长m来除关键字,取其余数作为散列地址,即 h(key)=key%m
  3. 相乘取整法:首先用关键字key乘上某个常数A(0
  4. 随机数法:选择一个随机函数,取关键字的随机函数值为它的散列地址
47  下面属于构造散列函数的方法是() 
直接定址法 数字分析法 乘余取整法 平方取中法
48  10,100,32,45,58,126,3,29,200,400,0利用除商留余法构造存于长度为13的数据的HASH
static int additiveHash(String key, int prime)  
{  
  int hash, i;  
  for (hash = key.length(), i = 0; i < key.length(); i++)  
   hash += key.charAt(i);  
  return (hash % prime);  
} 

49  哈希函数有一个共同的性质,即函数值应当以()取其值域的每个值。 
同等概率
50  哈希法的平均查找长度不随表中结点数目的增加而增加,而是随负载因子的增大而增大()
51  若装填因子a为1,则向哈希表中散列元素时一定会产生冲突() 
装填因子定义为:α= 填入表中的元素个数 / 散列表的长度
α是散列装满程度的标志因子。由于表长是定值,α与“填入表中的元素个数”成正比,所以,α越大,填入表中的元素较多,产生冲突的可能性就越大;α越小,填入表中的元素较少,产生冲突的可能性就越小。装填因子是1说明填入元素与表长相等,题中说的是向哈希表中散列元素,可能每个元素都不冲突,每各元素各占一个位置,并不是表满了再插入一个元素
52  稀疏矩阵压缩的存储方法是:() 
三元组
53  hash冲突时候的解决方法?
  1. 开放地址法
  2. 再哈希法
  3. 链地址法
  4. 建立一个公共溢出区
54  【0、2、1、4、3、9、5、8、6、7】是以数组形式存储的最小堆,删除堆顶元素0后的结果是()
首先,题目有问题,[0,2,1,4,3,9,5, 8 ,6,7], 原数组是这样才对得上号。
第二,堆是一种经过排序的完全二叉树,最小堆:根结点的键值是所有堆结点键值中最小者。根据这个不难写出原来堆依次为 顶层0   第二层 2 1   第三层 4 3   9 5   第四层 8 6 7      
第三,最小堆删除堆顶后,用最后一个元素暂代堆顶,然后变成顶层7   第二层  2 1   第三层 4 3   9 5   第四层 8 6 ,7>2>1,故1和7对调,对调后顶层1   第二层  2 7   第三层 4 3   9 5   第四层 8 6;因为9>7>5,5和7对调 ,对调后 顶层1   第二层  2 5   第三层 4 3   9 7   第四层 8 6;形成新的最小堆
故答案为:D 

来源: >
 
55  最坏情况下 insert sort, stack sort, quick sort ,merge sort 的复杂度分别是多少 ? 

冒泡排序:o(n*n)

选择排序:o(n*n)

插入排序:o(n*n)

快速排序:O(nlogn)

堆排序:O(nlogn)

归并排序:O(nlogn)

56  堆的形状是一颗()。  完全二叉树
57  使用初始化列表有两个原因

1.必须这样做:

        三种情况下需要使用初始化成员列表         1)对象成员(只有一个带参数的构造函数,而没有默认构造函数);  2)const修饰的成员;  3)引用成员数据;

2.效率要求这样做:

    类对象的构造顺序显示,进入构造函数体后,进行的是计算,是对他们的赋值操作,显然,赋值和初始化是不同的,这样就体现出了效率差异,如果不用成员初始化列表,那么类对自己的类成员分别进行的是一次隐式的默认构造函数的调用,和一次复制操作符的调用,如果是类对象,这样做效率就得不到保障。

58  满二叉树 与完全二叉树的区别
(1)完全二叉树——只有最下面的两层结点度小于2,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树;
(2)满二叉树——除了叶结点外每一个结点都有左右子女且叶结点都处在最底层的二叉树。

60  堆排序的时间复杂度是(),堆排序中建堆过程的时间复杂度是()。
O(n log n),O(n)
61  下面数据结构能够支持随机的插入和删除操作、并具有较好的性能的是____  链表和哈希表
62  就分类算法所用的辅助空间而言,堆分类、快速分类和归并分类的关系是()  堆分类<快速分类<归并分类
63  在用堆排序算法排序时,如果要进行增序排序,则需要采用"大根堆"() 
因为大根堆每次可以选择最大的那个元素,将它放在最后面,因此是递增的序列。最小堆排序后是递减数组,要得到递增数组,可以使用最大堆。

你可能感兴趣的:(数据结构和算法)