选择问答题汇总

head()和tail()

  • head() 返回列表的第一个元素;
  • tail() 返回列表的删去第一个元素之后的剩余列表;
  • K=(m,n,(p,(q,s)),(h,f)),
    head[tail[head[tail[tail(K)]]]]
    tail(K)-------(n,(p,(q,s)),(h,f))
    tail[tail[K]]--------((p,(q,s)),(h,f))
    head()-----((p,(q,s))
    tail()-----(q,s)
    head()-------q

声明和定义

  • 1.若在main()函数中包含.h文件,则编译器无法知道模板的确切定义,所以要在main()中包含.cpp文件,.cpp文件中又会包含.h文件,这样一来通过在main函数中包含.cpp文件就会将类的定义和声明都包含进来,编译器自然能找到模板的确切定义
  • 2.模板声明和定义放在一个文件里
  • 3.使用export实现声明和定义的分离

析构函数

#include <iostream>
using namespace std;
class D{
int d;
public: 
	D(int x=1):d(x){}
	~D(){cout<<"D";}
}; 
int main()
{ 
	D d[]={_____________};
	D* p=new D[2];
	delete[]p;
	return 0; 
}

程序运行的结果是DDDDD,请为横线处选择合适的程序( )
A. 3,3,3
B. D(3),D(3),D(3)
C. 3,3,3,3
D. D(3,3),D(3,3)

答案:AB
delete调用了两次析构,再调用三次
A:隐式转化

派生类对象和基类对象

#include <iostream>
using namespace std;
class shape 
{
public: 
	virtual int area()=0;
}; 
class rectangle:public shape 
{
public: 
	int a, b; 
	void setLength (int x, int y) {a=x;b=y;} 
	int area() {return a*b;} 
};

若有语句定义rectangle r; r.setLength(3,5); 则编译时无语法错误的语句是( )
A. shape *s1=&r;
B. shape &s2=r;
C. shape s3=r;
D. shape s4[3];

答案:AB
选项一:父类指针指向子类对象。
选项二:父类引用指向子类对象。
选项三四:纯虚函数不能实例化对象

在bash编程中,算术比较大于、大于等于的运算符是 gt,ge;

某系统中有4个并发进程,多需要同类资源5个,试问该系统无论怎样都不会发生死锁的最少资源数是: 4*(5-1)+ 1 =17

二叉搜索树,二叉平衡树,B树,B+树,红黑树

(一) 二叉搜索树

  • 特点:
  1. 所有非叶子结点至多拥有两个儿子(Left和Right)
  2. 所有结点存储一个关键字
  3. 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树
  • 其中序遍历是 排序好的序列
  • B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中;否则,如果查询关键字比结点关键字小,就进入左儿子;如果比结点关键字大,就进右儿子;如果左儿子或右儿子的指针为空,则报告找不到相应的关键字
  • 如果B树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树的搜索性能逼近二分查找;但它比连续内存空间的二分查找的优点是,改变B树结构(插入与删除结点)不需要移动大段的内存数据,甚至通常是常数开销
  • 查找效率最好O(logn),最坏O(n)
  • 删除效率最好O(logn)+O(1)->只有左子树或者右子树;最差O(logn)+O(logn)->左子树和右子树同时存在

(二) 二叉平衡树 (来源于二叉查找树与平衡二叉树

  • 平衡二叉搜索树,又被称为AVL树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树
    在这里插入图片描述
  • 为将一个非AVL树变成AVL树,使用左旋和右旋操作
  • 左旋:
    在这里插入图片描述
  • 右旋:
  • 左旋就是将节点的右支往左拉,右子节点变成父节点,并把晋升之后多余的左子节点出让给降级节点的右子节点;
    而右旋就是反过来,将节点的左支往右拉,左子节点变成了父节点,并把晋升之后多余的右子节点出让给降级节点的左子节点。即左旋就是往左变换,右旋就是往右变换。不管是左旋还是右旋,旋转的目的都是将节点多的一支出让节点给另一个节点少的一支
  • 插入节点:当有新节点插入时,都会判断插入后时候平衡,这说明了插入新节点前,都是平衡的,也即高度差绝对值不会超过1。当新节点插入后**,有可能会有导致树不平衡**,这时候就需要进行调整,而可能出现的情况就有4种,分别称作左左,左右,右左,右右 ——左左或右右只需要一次旋转就能实现平衡,而其余两种方式需要两次旋转;
  • 删除节点:①删除的是什么类型的节点?②删除了节点之后是否导致失衡?
    1) 节点的类型有三种:1.叶子节点;2.只有左子树或只有右子树;3.既有左子树又有右子树。
    2) 当删除的节点是叶子节点,则将节点删除,然后从父节点开始,判断是否失衡,如果没有失衡,则再判断父节点的父节点是否失衡,直到根节点,此时到根节点还发现没有失衡,则说此时树是平衡的;如果中间过程发现失衡,则判断属于哪种类型的失衡(左左,左右,右左,右右),然后进行调整
    3) 删除的节点只有左子树或只有右子树,这种情况其实就比删除叶子节点的步骤多一步,就是将节点删除,然后把仅有一支的左子树或右子树替代原有结点的位置,后面的步骤就一样了,从父节点开始,判断是否失衡,如果没有失衡,则再判断父节点的父节点是否失衡,直到根节点,如果中间过程发现失衡,则根据失衡的类型进行调整
    4)删除的节点既有左子树又有右子树,这种情况又比上面这种多一步,就是中序遍历,找到待删除节点的前驱或者后驱都行,然后与待删除节点互换位置,然后把待删除的节点删掉,后面的步骤也是一样,判断是否失衡,然后根据失衡类型进行调整

(三) B树

  • 是平衡的多路查找树
  • 多路查找树(muitl-way search tree),其每一个结点的孩子数可以多于两个,且每个结点出可以存储多个元素。由于它是查找树,所有元素之间存在某种特定的排序关系
  • B树就是一种平衡的多路查找树
  • B-树中所有结点中孩子结点个数的最大值成为B-树的阶,通常用m表示,从查找效率考虑,一般要求m>=3。一棵m阶B-树或者是一棵空树,或者是满足以下条件的m叉树:
  1. 每个结点最多有m个分支(子树);而最少分支数要看是否为根结点,如果是根结点且不是叶子结点,则至少要有两个分支,非根非叶结点至少有ceil(m/2)个分支,这里ceil代表向上取整
  2. 如果一个结点有n-1个关键字,那么该结点有n个分支。这n-1个关键字按照递增顺序排列
  3. 每个节点的结构为:
    节点个数:n;
    关键字数组: k[n],这n个关键字按照递增顺序排列
    孩子指针数组:p[n + 1], p0<=k1, 之后所有 ki < pi <= ki+1;
  • 查找操作:
    1)先让key与根结点中的关键字比较,如果key等于k[i](k[]为结点内的关键字数组),则查找成功
    2)若key<k[1],则到p[0]所指示的子树中进行继续查找(p[]为结点内的指针数组),这里要注意B-树中每个结点的内部结构。
    3)若key>k[n],则道p[n]所指示的子树中继续查找。
    4)若k[i]<key<k[i+1],则沿着指针p[I]所指示的子树继续查找。
    5)如果最后遇到空指针,则证明查找不成功。

  • 插入操作:
    1)要确定一下每个结点中关键字个数的范围,如果B-树的阶数为m,则结点中关键字个数的范围为ceil(m/2)-1 ~ m-1个;
    2)对于关键字的插入,需要找到插入位置。在B-树的查找过程中,当遇到空指针时,则证明查找不成功,同时也找到了插入位置,即根据空指针可以确定在最底层非叶结点中的插入位置
    3)为了方便,我们称最底层的非叶结点为终端结点,由此可见,B-树结点的插入总是落在终端结点上
    4)在插入过程中有可能破坏B-树的特征,如新关键字的插入使得结点中关键字的个数超过规定个数,中间结点为m/2向上取整的位置,这是要进行按中间结点的拆分,将中间结点放到父节点,如果父节点也不满足要求,就一直到网上分裂

例子:

按照关键字序列来,{1,2,6,7,11,4,8,13,10,5,17,9,16,20,3,12,14,18,19,15}

创建5阶b数,每个节点的关键字范围2-4((5/2-1) ~(5-1))

①根节点最多容纳4个关键字,插入1,2,6,7,的b树如图所示
在这里插入图片描述
②插入11时,超过4,此时需要分裂5/2向上取整(取整的时候要把当前添加的数加入进去),中间结点上移(并入上一层);
在这里插入图片描述
如: 添加10时:7 8 10 11 13 5/2 =3 ,第三位为10,将10上移;上层为6 10
最后:
在这里插入图片描述

  • 删除操作:
    对于B-树关键字的删除,需要找到待删除的关键字,在结点中删除关键字的过程也有可能破坏B-树的特性,如旧关键字的删除可能使得结点中关键字的个数少于规定个数,这是可能需要向其兄弟结点借关键字或者和其孩子结点进行关键字的交换,也可能需要进行结点的合并

例子:
①删除8,16,删除终端节点只需要判断删除后关键字的个数有没有小于最小值即2,没有直接删除,删除16的话,由于不是中端结点,取孩子来交换,只能找小于16的最大的或者大于16最小的,这里如果取15,会导致15所在结点的个数小于2,更麻烦,因此取17替换。

在这里插入图片描述
②删除4
在这里插入图片描述
将其与根节点合并,高度-1
在这里插入图片描述
(四) B+树

  • 在B+树中,具有n个关键字的结点有n个分支,而在B-树中,具有n个关键字的结点含有n+1个分支
  • 在B+树中,每个结点(除根结点外)中的关键字个数n的取值为ceil(m/2) <= n <=m,根结点的取值范围为1<=n<=m,b树他们的取值范围分别是ceil(m/2) -1<= n <=m-1和1<=n<=m-1
  • 在B+树中叶子结点包含信息,并且包含了全部关键字,叶子结点引出的指针指向记录。
  • 在B+树中的所有非叶子结点仅起到一个索引的作用,即结点中的每个索引项只含有对应子树的最大关键字和指向该子树的指针
    在这里插入图片描述
    每个父节点都出现在子节点中,是子节点的最大或最小元素。例如根节点的元素8,是子节点2,5,8的最大元素,也是叶子节点6,8的最大元素。根节点15是整个b+数的最大元素,无论插入删除多少元素,始终要保持最大在根节点中;父亲元素都会包含在叶子节点中,所有叶子节点包含了全部元素信息,并且每个叶子节点都带有指向下一个节点的指针,形成链表这里其实是双向链表,图中没表现出来
  • 对比B树:
    在这里插入图片描述
    B树中无论是中间结点还是叶子节点,都有卫星数据,而b+树中,只有叶子节点带有卫星数据,其余中间结点仅仅是索引。

b+树的优势在于;

1.单一节点存储更多的元素,使得查询的IO次数更少。

2.所有查询都要查找到叶子节点,查询性能稳定。

3.所有叶子节点形成有序链表,便于范围查询。

静态局部变量

(1)该变量在全局数据区分配内存;

(2)静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;

(3)静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为 0;

(4)它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。

静态全局变量

(1)静态变量都在全局数据区分配内存,包括后面将要提到的静态局部变量;

(2)未经初始化的静态全局变量会被程序自动初始化为0(在函数体内声明的自动变量的值是随机的,除非它被显式初始化,而在函数体外被声明的自动变量也会被初始化为 0);

(3)静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的。

若一序列进栈顺序为a1,a2,a3,a4,问存在多少种可能的出栈序列? —— C(2n,n)/(n+1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值