计网/数据库面试题(更新中ing~~)

本文涵盖了计算机网络的OSI七层模型、TCP/IP协议对比、HTTP与HTTPS的区别,以及数据库的连接类型、锁机制和优化。深入讨论了HTTP请求过程、URL与URI的区别,并对比了HTTP1和HTTP2。此外,还介绍了编程语言的基础知识,如内存分配、类的特性,以及数据结构如树和堆。最后涉及了分布式数据库、死锁概念和避免策略,以及数据库事务的隔离级别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

计网/数据库面试题(更新中ing~~)

《计算机网络》

在这里插入图片描述

OSI 模型全称为开放式通信系统互连参考模型,是国际标准化组织提出的一个网络的标准框架。 OSI 将计算机网络体系结构划分为七层,每一层实现各自的功能和协议,并完成与相邻层的接口通信。

1. OSI七层模型、设备

① 应用层: 应用程序间的交流。
不同的应用层“协议”为不同的网络应用提供服务。例如域名系统 DNS,支持万维网应用的 HTTP 协议,电子邮件系统采用的 SMTP 协议等。在应用层交互的数据单元:报文。
② 表示层:数据压缩,格式转换。
使通信的应用程序能够解释交换数据的含义,其向上为应用层提供服务,向下接收来自会话层的服务。
③ 会话层:建立、管理和终止 表示层实体 之间的通信会话。
该层提供了数据交换的定界和同步功能,包括了建立检查点和恢复方案的方法。
④ 传输层:两台主机进程之间的通信,提供服务。
应用程序利用该服务传送应用层报文。该服务并不针对某一特定的应用,多种应用可以使用同一个传输层服务。由于一台主机可同时运行多个线程,因此传输层有复用和分用的功能。
⑤ 网络层:封装数据报。
选择合适的“网间路由”和交换节点,确保数据按时成功传送。
在发送数据时,网络层把传输层产生的报文或用户数据报封装成,分组和包,向下传输到数据链路层。在网络层使用的协议是无连接的网际协议(Internet Protocol)和许多路由协议,因此我们通常把该层简单地称为 IP 层
⑥ 数据链路层:传帧。
相邻节点之间,传送数据时,本层将网络层的 IP 数据报->帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息。控制信息可以知道信息的起始位置,也能判断是否出错然后删掉它。
⑦ 物理层: 传比特流。
实现计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异。使其上面的数据链路层不必考虑网络的具体传输介质是什么。

网络层: 路由器
数据链路层: 网卡,网桥
物理层: 网线,中继器、集线器

(传输层)协议的多路分用和复用

如果某层的一个协议对应直接上层的多个协议或者实体,则与要多路复用和多路分用
复用:多个应用层进程可同时使用下面传输层的服务
分用:传输层把收到的信息分别交付上面应用层中的相应进程。

2. TCP/IP四层模型==五层模型

TCP/IP是指能够在多个不同网络间实现信息传输的协议簇。

TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。

tcp是传输层协议

TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,而IP层不提供这样的机制,而是提供不可靠的包交换。

IP是网络层的协议

IP协议规定了数据传输时的基本单元和格式。如果比作货物运输,IP协议规定了货物打包时的包装箱尺寸和包装的程序。 除了这些以外,IP协议还定义了数据包的递交办法和路由选择。同样用货物运输做比喻,IP协议规定了货物的运输方法和运输路线。

① 应用层:会话层、表示层和应用层。
通过不同的应用层协议为不同的应用提供服务。例如:FTP、Telnet、DNS、SMTP 等。
② 传输层:传输层。
为上层实体提供源端到对端主机的通信功能。传输层定义了两个主要协议:传输控制协议(TCP)和用户数据报协议(UDP)。
③ 网络层
网际互联层对应 OSI 参考模型的网络层,主要负责相同或不同网络中计算机之间的通信。在网际互联层, IP 协议提供的是一个不可靠、无连接的数据报传递服务。该协议实现两个基本功能:寻址和分段。根据数据报报头中的目的地址将数据传送到目的地址,在这个过程中 IP 负责选择传送路线。除了 IP 协议外,该层另外两个主要协议是互联网组管理协议(IGMP)和互联网控制报文协议(ICMP)。
④ 网络接入层
网络接入层的功能对应于 OSI 参考模型中的物理层和数据链路层,它负责监视数据在主机和网络之间的交换。事实上,TCP/IP 并未真正描述这一层的实现,而由参与互连的各网络使用自己的物理层和数据链路层协议,然后与 TCP/IP 的网络接入层进行连接,因此具体的实现方法将随着网络类型的不同而有所差异。

五层协议的体系结构只是为介绍网络原理而设计的,实际应用还是 TCP/IP 四层体系结构。

(传输层)TCP和UDP协议对比

传输控制协议(TCP)和用户数据报协议(UDP)。其中面向连接的 TCP 协议保证了数据的传输可靠性,面向无连接的 UDP 协议能够实现数据包简单、快速地传输。
在这里插入图片描述

(传输层)TCP协议的三次握手和四次挥手

因为是全双工协议,所以是两条信道要分别关闭

三次握手
发送方-> SYN(握手信号) -> 接收方
发送方<- SYN(握手信号)/ACK(确认字符) <- 接收方
发送方-> ACK(确认字符) -> 接收方
为什么是三次,两边都需要确认自己的收发以及对方的收发
在这里插入图片描述
四次挥手

发送方-> FIN(结束信号) -> 接收方
发送方<- ACK(确认字符) <- 接收方
发送方<- FIN(结束信号) <- 接收方
发送方-> ACK(确认字符) -> 接收方
为什么是四次,就是,互相更新对方那自己是否已知。我知道了,你知不知道我知道了?
在这里插入图片描述

(应用层)HTTP的长连接、短连接(实质是传输层tcp的)

HTTP的长连接和短连接本质上是TCP长连接和短连接。HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。

短连接的操作步骤是:

建立连接——数据传输——关闭连接.………建立连接——数据传输——关闭连接

长连接的操作步骤是:

建立连接——数据传输.………(保持连接).………数据传输——关闭连接

什么时候用长连接,短连接?
长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况,。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。

3. URL和URI的区别

URL是全球资源定位符,家庭地址
IE浏览器中输入的那个地址就是URL。例如 http://www.163.com就是一个URL。
URI是资源的通用标志符,身份证
HTML文档、图像、视频片段、程序,由一个通过通用资源标志符(Universal Resource Identifier, 简称"URI")进行定位。

URL是URI的一种,是URI命名机制的一个子集,能够说URI是抽象的,而详细要使用URL来定位资源。
URI是一个相对来说更广泛的概念。URI定位Web上的每一种资源如:图片、文档、视频等。这里所谓的定位指的是web上的资源相对于主机server来说,存放在server上的详细路径。
URL是internet上用来描写叙述信息资源文件的字符串。用在客户程序和server上,定位客户端连接server所须要的信息,它不仅定位了这个信息资源,并且定义了怎样找到这个资源。

URL的组成组成解释
协议该URL的协议部分为“http:”, 在"HTTP"后面的“//”为分隔符
域名该URL的域名部分为“www.aspxfans.com”。一个URL中,也可以使用IP地址作为域名使用
端口跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符。非必须可省略,可用默认端口
虚拟目录从域名后的第一个“/”开始到最后一个“/”为止,是虚拟目录部分。本例中的虚拟目录是“/news/”。非必须。
文件名从域名后的最后一个“/”开始到“?”为止,是文件名部分。非必须可省略,可用默认文件名
从“#”开始到最后,都是锚部分。本例中的锚部分是“name”。非必须可省略。
参数从“?”开始到“#”为止,又称搜索部分、查询部分。本例中的参数部分为“boardID=5&ID=24618&page=1”。

4. 打开一个网址的过程

1、浏览器发起DNS请求,将网址www.baidu.com 解析为IP地址
2、浏览器向IP地址发起请求
3、服务器收到请求并开始进行数据处理
4、服务器返回时数据
5、浏览器解析返回的数据并进行渲染,实现可视化展示

什么是DNS解析?
当用户输入一个网址并按下回车键的时候,浏览器得到了一个域名。而在实际通信过程中,我们需要的是一个IP地址。因此我们需要先把域名转换成相应的IP地址,这个过程称作DNS解析。
1、浏览器首先搜索浏览器自身缓存的DNS记录。
2、如果浏览器缓存中没有找到需要的记录或记录已经过期,则搜索hosts文件和操作系统缓存。
3、如果在hosts文件和操作系统缓存中没有找到需要的记录或记录已经过期,则向域名解析服务器发送解析请求。
4、如果域名解析服务器也没有该域名的记录,则开始递归+迭代解析。

这里我们举个例子,如果我们要解析的是mail.google.com。
1、首先我们的域名解析服务器会向根域服务器(全球只有13台)发出请求。显然,仅凭13台服务器不可能把全球所有IP都记录下来。所以根域服务器记录的是com域服务器的IP、cn域服务器的IP、org域服务器的IP……

2、根域服务器告诉我们com域服务器的IP。
3、接着我们的域名解析服务器会向com域服务器发出请求。根域服务器并没有mail.google.com的IP,但是却有google.com域服务器的IP。
4、接着我们的域名解析服务器会向google.com域服务器发出请求。
5、如此重复,直到获得mail.google.com的IP地址。

为什么是递归:问题由一开始的本机要解析mail.google.com变成域名解析服务器要解析mail.google.com,这是递归。
为什么是迭代:问题由向根域服务器发出请求变成向com域服务器发出请求再变成向google.com域发出请求,这是迭代。

5. HTTP和HTTPS的区别

HTTP:超文本传输协议,它可以使浏览器更加高效,使网络传输减少。

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,就对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。

HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。SSL(Secure Sockets Layer 安全套接字协议)

6. HTTP1和HTTP2的区别

与HTTP 1.1相比,主要区别包括
HTTP/2采用二进制格式而非文本格式
HTTP/2是完全多路复用的,而非有序并阻塞的——只需一个连接即可实现并行
使用报头压缩,HTTP/2降低了开销
HTTP/2让服务器可以将响应主动“推送”到客户端缓存中

HTTP/2为什么是二进制?
比起像HTTP/1.x这样的文本协议,二进制协议解析起来更高效、“线上”更紧凑,更重要的是错误更少

7. 常见错误码/状态码

一.信息 1XX
二.成功 2XX
三.重定向 3XX,为完成请求客户需进一步细化请求
四.客户端错误 4XX
五.服务端错误 5XX

200 OK
指示客服端的请求已经成功收到,解析,接受。

403 Forbidden
服务器接受请求,但是被拒绝处理。

404 Not Found
找不到服务器,服务器找不到任何匹配Request-URI的资源。

503 Service Unavailable
因为临时文件超载导致服务器不能处理当前请求。

(总结)HTTP常见错误返回代码

《数据库》

1. 内连接、外连接、左连接、右连接、自然连接、 笛卡尔积

内连接(inner join):交集
外连接(outer join):并集
左连接(Left Join):产生表A的完全集,而B表中匹配的则有值(没有匹配的则以null值取代)
右连接(Right Join):产生表B的完全集,而A表中匹配的则有值(没有匹配的则以null值取代)
自然连接(natural join):自然连接得到的结果表中,两表中名称相同的列只出现一次。
select * from employee natural join department;

笛卡尔积原本是代数的概念,他的意思是对于两个不同的集合A,B。对于A中的每一个元素,都有对于在B中的所有元素做连接运算 。可以见得对于两个元组分别为m,n的表。笛卡尔积后得到的元组个数为m x n个元组。而对于mysql来说,默认的连接就是笛卡尔积连接。

2.锁的类型, 共享S、排它X、更新U or 乐观、悲观

为什么需要锁?

防止同时访问
在并发环境下,如果多个客户端访问同一条数据,此时就会产生数据不一致的问题,如何解决,通过加锁的机制,常见的有两种锁,乐观锁和悲观锁,可以在一定程度上解决并发访问。

共享(S)锁:
读。多个事务可封锁一个共享页;任何事务都不能修改该页; 通常是该页被读取完毕,S锁立即被释放。
排它(X)锁:
写。仅允许一个事务封锁此页;其他任何事务必须等到X锁被释放才能对该页进行访问;X锁一直到事务结束才能被释放。
更新(U)锁:
预定写。用来预定要对此页施加X锁,它允许其他事务读,但不允许再施加U锁或X锁;当被读取的页将要被更新时,则升级为X锁;U锁一直到事务结束时才能被释放。

一、悲观锁
顾名思义,就是对于数据的处理持悲观态度,总认为会发生并发冲突,获取和修改数据时,别人会修改数据。所以在整个数据处理过程中,需要将数据锁定。
二、乐观锁
顾名思义,就是对数据的处理持乐观态度,乐观的认为数据一般情况下不会发生冲突,只有提交数据更新时,才会对数据是否冲突进行检测。如果发现冲突了,则返回错误信息给用户,让用户自已决定如何操作。
乐观锁的实现不依靠数据库提供的锁机制,需要我们自已实现,实现方式一般是记录数据版本,一种是通过版本号,一种是通过时间戳。

3.聚集索引和非聚集索引

clustered index
nonclustered index
一本字典,聚集索引就是拼音顺序,A-Z,A打头的都在一起
非聚集就是部首顺序,偏旁部首分散在各个字母

4.数据库查询怎么优化?

1.使用索引

2.优化SQL语句

3.优化数据库对象

3.1 优化表的数据类型:列的数据类型提出优化建议。能短就用短。尽可能使用能正确的表示和储存数据的最短类型。这样可以减少对磁盘空间,内存,cpu缓存的使用。
3.2 对表进行拆分:垂直拆或者水平拆,筛去不常用的
3.3 使用中间表来提高查询速度: 创建中间表,表结构和原表结构完全相同,转移要统计的数据到中间表,然后在中间表上进行统计,得出想要的结果。

详细展开说:
https://www.cnblogs.com/arxive/p/10597002.html

5.主键、外键

==主键:==表中经常有一个列或多个列的组合,其值能唯一的标识表中的每一行。
==外键:==用来表示表与表之间联系,是表中的一个列。

主键和外键都是用于维护数据库完整性的一种机制。
区别:
1、主键是唯一标识一条记录,不能重复,不允许为空;而外键可以重复,可以是空值;
2、主键是用来保持数据完整性,外键是用来建立与其他表联系用的;
3、主键只有一个,外键可以有多个。

6.什么是关系型数据库?

数据库:数据仓库,数据库分成一个个库,分成一个个表,分成一条条记录

关系型数据库:依据关系模型来创建的数据库。所谓关系模型就是“一对一、一对多、多对多”等关系模型,关系模型就是指二维表格模型,因而一个关系型数据库就是由二维表及其之间的联系组成的一个数据组织。

非关系型型数据库:列模型、键值对模型。
列模型:存储的数据是一列列的。关系型数据库以一行作为一个记录,列模型数据库以一列为一个记录。(这种模型,数据即索引,IO很快,主要是一些分布式数据库)
键值对模型:存储的数据是一个个“键值对
什么是数据库?什么是关系数据库?什么是非关系型数据库?

7.分布式数据库是什么?

分布式数据库系统:一个粗略的定义是“分布式数据库由一组数据组成,这些数据物理上分布在计算机网络的不同节点上(亦称场地)上,逻辑上是属于同一个系统。” 这里强调两点:

(1)分布性:数据库中的数据不是存储在同一场地,更确切的说,不存储在同一计算机的存储设备上,这就可以和集中式数据库相互区别。

(2)逻辑整体性:这些数据逻辑上是互相联系的,是一个整体(逻辑上如同集中数据库)。

8.死锁? 如何避免死锁?对资源的分配要给予合理的规划

死锁产生的四个必要条件:

1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

如何避免死锁?对资源的分配要给予合理的规划

a. 按同一顺序访问对象:第一个事务提交或回滚后,第二个事务继续进行,这样不会发生死锁。

b. 避免编写包含用户交互的事务:因为运行没有用户交互的批处理的速度要远远快于用户手动响应查询的速度,例如答复应用程序请求参数的提示。减少等待用户等待占用的资源,这样其他事务不会被阻塞。

c. 保持事务简短并在一个批处理中:事务运行时间越长,其持有排它锁或更新锁的时间也就越长,从而堵塞了其它活动并可能导致死锁。 保持事务在一个批处理中,可以最小化事务的网络通信往返量,减少完成事务可能的延迟并释放锁。

d. 使用低隔离级别:确定事务是否能在更低的隔离级别上运行,执行提交读取允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。

数据库引起的死锁及死锁的定义

多线程死锁?

c++线程中的锁主要有五类:互斥锁、条件锁、自旋锁、读写锁、递归锁。

互斥锁用于控制多个线程对它们之间共享资源互斥访问的一个信号量。在某一时刻只有一个线程可以获得互斥锁,在释放互斥锁之前其它线程都不能获得互斥锁,以阻塞的状态在一个等待队列中等待。

条件锁就是所谓的条件变量,当某一个线程因为某个条件未满足时可以使用条件变量使该程序处于阻塞状态,一旦条件满足则以“信号量”的方式唤醒一个因为该条件而被阻塞的线程。

自旋锁是一种busy-waiting的锁。也就是说,如果T1正在使用Public,而T2也想使用Public,此时T2肯定是得不到这个自旋锁的。与互斥锁相反,此时运行T2的处理器core2会一直不断地循环检查Public使用可用(自旋锁请求),直到获得到这个自旋锁为止。

读写锁我们可以借助于“读者-写者”问题进行理解。接下来我们简单说下“读者-写者”问题。

计算机中某些数据被多个进程共享,对数据库的操作有两种:一种是读操作,就是从数据库中读取数据不会修改数据库中内容;另一种就是写操作,写操作会修改数据库中存放的数据。因此可以得到我们允许在数据库上同时执行多个“读”操作,但是某一时刻只能在数据库上有一个“写”操作来更新数据。这就是简单的读者-写者模型。

9.什么是批处理?

一次性执行多条sql语句,允许多条语句一次性提交给数据库批量处理,比单独提交处理效率搞。
事务vs批处理

10.数据库事务的隔离级别?四种

最低到最高

Read uncommitted(最低级别,任何情况都无法保证。)
读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。

Read committed(可避免脏读的发生。)
读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。

Repeatable read(可避免脏读、不可重复读的发生。)
重复读,就是在开始读取数据(事务开启)时,不再允许修改操作

Serializable(可避免脏读、不可重复读、幻读的发生。)
序列化 Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

11.脏写、脏读、不可重复读、幻读

脏写:自己明明更新了,结果值却没了。因为两个事务同时进行,其中一个回滚了,另一个白写。
脏读:读一条别人还没提交的数据,读不到。两个事务同时,一个没提交,另一个就找那个,肯定找不到。
不可重复读: 连续读两遍同一条数据,两遍之间有读写操作,导致数据不一致
幻读:连续读n遍n条数据,n遍之间有插入操作,导致数据不一致

不可重复读是: 因为在读的时候没有禁止写操作,两次读取同一条数据的时候结果不一致,主要针对的是update或delete
幻读是: 因为在读取多条数据时。虽然此时读操作禁止了写操作,所以update和delete都是不行的,但是由于未知行的不存在,无法加锁,所以insert语句还是可以在读事务中间执行,所以可能出现幻读

MyISAM与InnoDB 的区别

1.InnoDB支持事务,MyISAM不支持。
对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;

2.InnoDB支持外键,而MyISAM不支持。
对一个包含外键的InnoDB表转为MYISAM会失败;

3.InnoDB是聚集索引,MyISAM是非聚集索引。

InnoDB是聚集索引使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。

MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
也就是说:InnoDB的B+树主键索引的叶子节点就是数据文件,辅助索引的叶子节点是主键的值;而MyISAM的B+树主键索引和辅助索引的叶子节点是数据文件的地址指针。

《基础知识》

1. 编程语言的对比

面向过程:关注事情发展的顺序,类似于编年体,以时间顺序,历史发生的先后顺序记录。
面向对象:关注对象的属性和行为,类似于纪传体(史记),以人物对象的行为属性记录。

C:面向过程,开发效率低,适合系统linux开发,移植性差。
C++: 面向对象,开发效率高,很多的库,具有较好的封装性和移植性(代码),但是更新很快,需要不断学习。
JAVA: 面向对象,开发效率高,很多的封装类,具有较好的封装性和移植性(代码),但是占用内存,因为java虚拟机。
Python:面向对象,脚本语言,开发效率高,很多的封装类,具有较好的封装性和移植性(代码),但是语法规则严格,用缩进区分语句关系

2. 常见排序算法

常见排序算法及其对应的时间复杂度和空间复杂度

选择排序是:选一个最大的和第一个交换,选一个第二大的和第二个交换
冒泡排序是:两个两个交换,每次一圈都是第n大的值放在第n位置
插入排序是:维护已经排好序的数组
快速排序是:选一个点,然后一分为二,小的放左,大的放右
在这里插入图片描述

3. 类的特性?封装、继承、多态

封装就是,创建一个类,“打包”定义到一个模块中,供我们需要时调用它们。这个打包的行为,我们也称“类的封装”。public,privite,公有私有。

继承就是,子类承接父类的全部
公有成员:类内和类外都可访问。
私有成员:类内可访问,类外不可访问。友元可访问。什么是友元,下面会介绍。
保护成员:不涉及继承,和私有成员没什么区别,涉及继承,就是私有继承会把保护变成私有。

实现多态,有二种方式,覆盖,重载。覆盖:是指子类重新定义父类的虚函数的做法。重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

4. 内存分配?栈、堆、全局、文字常量、程序代码

1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其 操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由系统回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的 全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另 一块区域。 - 程序结束后由系统释放。
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。

5. 函数重载 VS 虚函数

为什么要有虚函数?

虚函数:在某基类中声明为 virtual 并在一个或多个派生类中被重新定义。为了子类能够重定义。

1.函数重载可以用于非成员函数和类的成员函数,而虚函数只能用于类的成员函数

2.函数重载可用于构造函数,而虚函数不能用于构造函数

3.如果对成员函数进行重载,重载的函数与原函数应该是用一个类中的成员函数,不能分属于两个不同继承层次的类,函数重载处理的是横向的重载。

虚函数是对同一类族中的基类和派生类的同名函数的处理,即允许在派生类中对基类的成员函数重新定义。虚函数处理的是纵向的同名函数。

4.重载的函数必须具有相同的函数名,函数类型可以相同也可以不同,但函数的参数个数和参数类型二者中至少有一个不同,否则在编译时无法区分。

而虚函数则要求同一类族中的所有虚函数的函数名,函数类型,函数的参数个数和参数类型都全部相同,否则就不是重定义了,也就不是虚函数了

5.函数重载是在程序编译阶段确定操作的对象的,属于静态关联。虚函数是在程序运行阶段确定操作对象的,属于动态关联。

6. 虚析构函数,没有虚构造

.虚析构函数作用总结:

(a) 普通析构函数
当基类中的析构函数没有声明为虚析构函数时,派生类开始从基类继承,基类的指针指向派生类的对象时,delete基类的指针时,只会调用基类的析构函数,不会调用派生类的析构函数。

(b) 虚析构函数(基类的析构函数加virtual关键字)
当基类中的析构函数声明为虚析构函数时,派生类开始从基类继承,基类的指针指向派生类的对象时,delete基类的指针时,先调用派生类的析构函数,再调用基类中的析构函数。

7. 父类指针指向子类对象

父类指针指向子类实例对象(多态与普通函数区别)
父类指针指向子类实例对象,调用普通重写方法时,会调用父类中的方法。而调用被子类重写虚函数时,会调用子类中的方法。
这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。

虚函数 是在基类中使用关键字 virtual 声明的函数,可以实现。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。 virtual int area() ;
我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定.

子类中被重写的虚函数的运行方式是动态绑定的,与当前指向类实例的父类指针类型无关,仅和类实例对象本身有关。

如果子类覆盖的父类的虚函数
则父类的指针或引用实际指向子类的对象
那通过该指针或引用调用虚函数时,则将调用子类的(虚)函数
如果不是虚函数,则将调用父类的函数
虚函数的优势在于当用指针调用虚函数的时候,即使是基类类型的指针,也会调用到派生类型的函数。

8. 静态成员函数&&静态成员变量

为什么有静态成员函数
引入前,C++里如果需要调一个在类里,但跟类的实例无关的函数,就需要((T*)NULL)->Func();
很恐怖有没有。所以干脆就引入了static mem func。

引入后,与类实例无关。
1、可以把类名当成namespace用。
2、控制该函数的访问权限。
3、控制类内的static变量。

静态成员函数与非静态成员函数的根本区别是:非静态成员函数有 this 指针,而静态成员函数没有 this 指针。由此决定了静态成员函数不能访问本类中的非静态成员。

为什么有静态成员变量
可以使用全局变量来达到共享数据的目的。例如在一个程序文件中有多个函数,每一个函数都可以改变全局变量的值,全局变量的值为各函数共享。但是用全局变量的安全性得不到保证,由于在各处都可以自由地修改全局变量的值,很有可能偶然失误,全局变量的值就被修改,导致程序的失败。因此在实际开发中很少使用全局变量。

如果想在同类的多个对象之间实现数据共享,也不要用全局变量,那么可以使用静态成员变量。

  1. 一个类中可以有一个或多个静态成员变量,所有的对象都共享这些静态成员变量,都可以引用它。
  2. static 成员变量和普通 static 变量一样,编译时在静态数据区分配内存,到程序结束时才释放。这就意味着,static 成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。而普通成员变量在对象创建时分配内存,在对象销毁时释放内存。
  3. 静态成员变量必须初始化,而且只能在类体外进行。例如:
    int Student::num = 10;
    初始化时可以赋初值,也可以不赋值。如果不赋值,那么会被默认初始化,一般是 0。静态数据区的变量都有默认的初始值,而动态数据区(堆区、栈区)的变量默认是垃圾值。
  4. 静态成员变量既可以通过对象名访问,也可以通过类名访问,但要遵循 private、protected 和 public 关键字的访问权限限制。当通过对象名访问时,对于不同的对象,访问的是同一份内存。

9. 浮点数存储float和double

实际上0.5 是2的-1次方,二进制表示就是0.1
十进制小数---->二进制小数----->二进制的科学计数法
1.xxxx 乘以 2的E次方
xx只能是0或者1
然后省略小数点和前面的1,一定是1,因为科学计数法必然是1
然后指数位本来表示的是0-255,为了表示-126-127,所以指数部分+127
在这里插入图片描述
从上图可知,“float精度是2^23 ,能保证6位。double精度是2^52 ,能保证15位。但是默认float和double都只能显示6位,再多需要#include ,然后在输出语句之前插入cout << setprecision(20);强制输出小数位。

浮点数的范围计算,实际是近似值在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

https://zhuanlan.zhihu.com/p/46464005

10. char 类型和 unsigned char 类型

只对于符号位是否计算有区别

char(-128-127)
unsigned char(0-255)

比如说128=0x80(16进制128)
最高位是否会被当成符号位的区别
如果char保存,强制类型转换为unsigned int ,输出结果是4294967168
如果char保存,强制类型转换为int ,输出结果是 -128
如果unsigned char保存,强制类型转换为unsigned int ,输出结果是128
如果unsigned char保存,强制类型转换为int ,输出结果是128

之所以有“char没有负数”这样的错觉是因为常用char类型记录一个ASCII字符,而ASCII的范围是0~+127。

c语言中 char* 和 unsigned char* 的区别浅析

11.树

(1)B树:二叉搜索树

左<中<右,二叉

增加,删除,修改

怎么把无序树变成二叉搜索树?五种情况

//1, 根结点与左子树上的某个节点互换
//2, 根结点与右子树上的某个节点互换
//3, 左子树上的某个节点与右子树上的某个节点互换
//4, 左子树上的两个节点互换
//5, 右子树的两个节点互换

求左子树中val最大+右子树中val最小,然后判断并执行情况345

力扣 99. 恢复二叉搜索树

怎么删除二叉搜索树的某个节点?三种情况

    TreeNode* deleteNode(TreeNode* root, int key) 
    {
        if (root == nullptr)    return nullptr;
        if (key > root->val)    root->right = deleteNode(root->right, key);     // 去右子树删除
        else if (key < root->val)    root->left = deleteNode(root->left, key);  // 去左子树删除
        else    // 当前节点就是要删除的节点
        {
            if (root->left == nullptr)   return root->right; // 情况1,没有左子树返回右子树
            if (root->right == nullptr)  return root->left;  // 情况2,没有右子树返回左子树
            TreeNode* bigger = root->right;           // 情况3,要删除节点左右子都有 
            while (bigger->left)          // 寻找要删节点的右子树的最左节点,比当前要删的大一位的
                bigger = bigger->left;
            bigger->left = root->left;    // 大一位的连接到小一位的,就等于删除了
            root = root->right;         // 右节点进位
        }
        return root;    
    }

(2)B-树/B+树:多叉搜索树

B-:B减树: 无论哪一层都有数据索引指向的数据记录
在这里插入图片描述
B+:B加树:只有最后一层有数据索引指向的数据记录
数据库的聚集索引(Clustered Index)中,叶子节点直接包含数据记录。
在非聚集索引(NonClustered Index)中,叶子节点带有指向数据记录的指针。
在这里插入图片描述

对比来讲,查询效率上,B+树会更高,除了叶子层,其余层都是索引,能够加速查找,提高查找的稳定性。
因为B-数的查找是从根节点向下找,中序遍历,B+数直接在最下面一行,当做链表横向查找即可。
B-树与B+树 两者的区别

(3) RB-Tree红黑树(自平衡二叉搜索树)

红黑树使用红黑二色进行“着色”,目的是利用颜色值作为二叉树的平衡对称性的检查,只要插入的节点“着色”满足红黑二色的规定,最短路径与最长路径不会相差的太远,红黑树的节点分布就能大体上达至均衡。
从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。
最短是全黑色。最长是黑红相间。
左旋:把当前的左节点提上来,左节点的原来右变成当前的左,左节点的新右变成当前
右旋:把当前的右节点提上来,右节点的原来左变成当前的右,右节点的新左变成当前

插入:首先是根据一般二叉查找树的插入步骤, 把新结点 插入到某个叶结点的位置上,然后将 z 着 为红色。 为了保证红黑树的性质能继续保 持,再对有关结点重点着色并旋转。

删除:与红黑树的的插入算法一样,对一个结点的删除算法要花 O(log n)时间,只是删 除算法略微复杂些,删除算法如下

红黑树原理及插入、删除

(4) 二叉平衡树

  1. 将二叉搜索树变平衡

实际就是先保存一个序列,再生成一颗树,如果是上面那个题就是生成一颗搜索树

(5) 最大堆(非排序的完全二叉树)

完全树:上面是满的只有最后一层是从左到右排列的
插入节点:插入到最后一层的最右边空的情况,然后节点 上浮,把这个分支上所有有孩子的父节点都判断一遍
删除节点:把叶子节点的最后一个替代这个要删除的节点,然后,节点 下沉,从当前开始所有有孩子的父节点都判断一遍

12. 解决散列冲突问题

开放寻址:如果相同key值,就把数据存到后面的空位置
链表:相同key值,存为链表横向排列
在这里插入图片描述

13. c++11特性

  1. nullptr
    nullptr 出现的目的是为了替代 NULL, 专门用来区分空指针、0。
  2. 引入了 auto 和 decltype 这两个关键字实现了类型推导,让编译器来操心变量的类型。
    decltype 关键字是为了计算某个表达式的类型.

C++11常用新特性快速一览

14.c++ STL

STL内容介绍
STL中六大组件:

1.容器(Container),是一种数据结构,如list,vector,和deques ,以模板类的方法提供。为了访问容器中的数据,可以使用由容器类输出的迭代器;
2. 迭代器(Iterator),提供了访问容器中对象的方法。例如,可以使用一对迭代器指定list或vector中的一定范围的对象。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器也可以是那些定义了operator*()以及其他类似于指针的操作符地方法的类对象;
3. 算法(Algorithm),是用来操作容器中的数据的模板函数。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象,函数本身与他们操作的数据的结构和类型无关,因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用;
4. 仿函数(Functor)
5. 适配器(Adaptor)
6. 分配器(allocator)

(1)序列式容器(Sequence containers),每个元素都有固定位置--取决于插入时机和地点,和元素值无关,vector、deque、list;

Vector:将元素置于一个动态数组中加以管理,可以随机存取元素(用索引直接存取),数组尾部添加或移除元素非常快速。但是在中部或头部安插元素比较费时;

Deque:是“double-ended queue”的缩写,可以随机存取元素(用索引直接存取),数组头部和尾部添加或移除元素都非常快速。但是在中部或头部安插元素比较费时;

List:双向链表,不提供随机存取(按顺序走到需存取的元素,O(n)),在任何位置上执行插入或删除动作都非常迅速,内部只需调整一下指针;

《大数据相关》

大数据平台最常用的30款开源工具

1. Hadoop分布式存储与计算

Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,MapReduce则为海量的数据提供了计算,因此,需要重点掌握。

怎么使用Hadoop
3.1、Hadoop集群的搭建无论是在windows上装几台虚拟机玩Hadoop,还是真实的服务器来玩,说简单点就是
把Hadoop的安装包放在每一台服务器上,改改配置,启动就完成了Hadoop集群的搭建。
3.2、上传文件到Hadoop集群Hadoop集群搭建好以后,可以通过web页面查看集群的情况,还可以通过Hadoop命令来上传文件到hdfs集群,通过Hadoop命令在hdfs集群上建立目录,通过Hadoop命令删除集群上的文件等等。
3.3、编写map/reduce程序通过集成开发工具(例如eclipse)导入Hadoop相关的jar包,编写map/reduce程序,将程序打成jar包扔在集群上执行,运行后出计算结果。

2. ZooKeeper开源的分布式协调服务

ZooKeeper是一个开源的分布式协调服务,是Hadoop和HBase的重要组件,是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组件服务等。在大数据开发中要掌握ZooKeeper的常用命令及功能的实现方法。

3. Spark计算引擎

Spark是专为大规模数据处理而设计的快速通用的计算引擎,其提供了一个全面、统一的框架用于管理各种不同性质的数据集和数据源的大数据处理的需求,大数据开发需掌握Spark基础、SparkJob、Spark RDD部署与资源分配、Spark Shuffle、Spark内存管理、Spark广播变量、Spark SQL、Spark Streaming以及Spark ML等相关知识。

《研究生相关》

1. 数据挖掘

数据挖掘(Data Mining)就是从大量的数据中,提取隐藏在其中的,事先不知道的、但潜在有用的信息的过程。数据挖掘的目标是建立一个决策模型,根据过去的行动数据来预测未来的行为。

常用的数据挖掘方法:
聚类分析(cluster analysis)旨在发现紧密相关的观测值组群,使得与属于不同簇的观测值相比, 属于同一簇的观测值相互之间尽可能类似。聚类可用来对相关的顾客分组、找出显著影响 地球气候的海洋区域以及压缩数据等。

什么是数据挖掘?

2. 深度学习

深度学习(deep learning,以下简称DL),换种说法,可以说是基于人工神经网络的机器学习。区别于传统的机器学习,DL需要更多样本,换来更少的人工标注和更高的准确率。

神经网络一般指三层的全连接神经网络,而大于三层就成了DNN(深度神经网络)

通过对图片的学习,生成一些相似图片,该怎么做呢?GAN(生成式对抗网络)因此诞生。
这个网络的想法是,用一个网络模型来生成目标,叫做生成器;然后用另一个或多个网络模型来实现判别,叫做判别器。判别器提升自己的判别能力,将生成的假目标与真实的目标区分开;而生成器提升自己的生成能力,将生成的假目标做得真实,试图骗过判别器。

3. 机器学习

最常见的机器学习算法是学习映射 Y = f(X) 来预测新 X 的 Y。这叫做预测建模或预测分析,我们的目标是尽可能作出最准确的预测。

我们可以根据输入变量 X 的新样本对 Y 进行预测。我们不知道函数 f 的样子或形式。如果我们知道的话,我们将会直接使用它,不需要用机器学习算法从数据中学习。

机器学习像是,我给你分类,你去分类别的数据
深度学习是,我给你数据,你给我几种分类的方法

以下是一些 MySQL 常见面试题: 1. 什么是 MySQL? MySQL 是一种开源的关系型数据库管理系统(RDBMS),用于存储、管理检索数据。它是一种客户端/服务器模型数据库,可以同时支持多个连接。 2. MySQL 的优点是什么? MySQL 的优点包括: - 开源:MySQL 是免费开源的,可以用于商业非商业用途。 - 可扩展性:MySQL 可以处理大量数据高并发请求。 - 跨平台:MySQL 可以在多个操作系统上运行,如 Windows、Linux、Mac 等。 - 安全性:MySQL 提供了许多安全功能,如 SSL 加密、访问控制数据加密。 3. MySQL 中的主键唯一键有什么区别? 主键是一列或一组列,用于唯一标识表中的每一行数据。主键必须是唯一的,且不能为 NULL。 唯一键是一列或一组列,用于确保表中的数据唯一。唯一键可以包含 NULL 值,但每个值只能出现一次。 4. 如何在 MySQL 中创建一个新表? 可以使用以下命令在 MySQL 中创建一个新表: ``` CREATE TABLE table_name ( column1 datatype, column2 datatype, column3 datatype, ... ); ``` 其中,`table_name` 是要创建的表的名称,`column1`、`column2`、`column3` 等是表中的列名,`datatype` 是每列的数据类型。 5. 如何在 MySQL 中插入新数据? 可以使用以下命令在 MySQL 中插入新数据: ``` INSERT INTO table_name (column1, column2, column3, ...) VALUES (value1, value2, value3, ...); ``` 其中,`table_name` 是要插入数据的表的名称,`column1`、`column2`、`column3` 等是表中的列名,`value1`、`value2`、`value3` 等是要插入的值。 6. 如何在 MySQL 中更新数据? 可以使用以下命令在 MySQL 中更新数据: ``` UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition; ``` 其中,`table_name` 是要更新数据的表的名称,`column1`、`column2` 等是要更新的列名,`value1`、`value2` 等是要更新的值,`condition` 是更新数据的条件。 7. 如何在 MySQL 中删除数据? 可以使用以下命令在 MySQL 中删除数据: ``` DELETE FROM table_name WHERE condition; ``` 其中,`table_name` 是要删除数据的表的名称,`condition` 是删除数据的条件。 8. 如何在 MySQL 中查询数据? 可以使用以下命令在 MySQL 中查询数据: ``` SELECT column1, column2, ... FROM table_name WHERE condition; ``` 其中,`column1`、`column2` 等是要查询的列名,`table_name` 是要查询的表的名称,`condition` 是查询数据的条件。 9. 如何在 MySQL 中创建索引? 可以使用以下命令在 MySQL 中创建索引: ``` CREATE INDEX index_name ON table_name (column1, column2, ...); ``` 其中,`index_name` 是要创建的索引的名称,`table_name` 是要创建索引的表的名称,`column1`、`column2` 等是要创建索引的列名。 10. 如何在 MySQL 中优化查询? 可以使用以下方法优化 MySQL 查询: - 创建索引:可以提高查询速度。 - 避免使用 SELECT *:只查询需要的列,可以减少查询时间。 - 避免在 WHERE 子句中使用函数:可以减少查询时间。 - 避免使用子查询:可以减少查询时间。 - 分页查询时使用 LIMIT:可以减少查询时间减轻服务器负担。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值