计科八股20260606——二叉树、PCA、图深度学习、进程上下文、C语言预编译、文件读写、单精度浮点数

要高考了,我也只剩一百天了。


Q:介绍数据结构二叉树?

第一反应:二叉树就是每个节点有且只有最多两个孩子的节点,分别记作左孩子和有孩子,所以这个node可以定义为指向父节点的指针、指向左、右节点的指针,还有自己的value值。然后完全二叉树的性质相对较多,比如树的节点个数向下取整log2+1就是深度,这些都可以用数学简单证明出来。

AI表示面试官希望听到二叉树的优势:"二叉树的每个节点度数 ≤ 2,这个结构决定了它可以用数组连续存储(完全二叉树),也可以用链式存储(指针)。更重要的是,任何多叉树都可以用'左孩子右兄弟'表示法转换成一棵二叉树,所以二叉树是树结构里通用性最强、实现最方便的一种形式。"

Q:二叉树的最大深度你知道吧(老师还解释了一下),你怎么求?

我的第一反应:链式存储的就用DFS,数组存储的可以直接找到最大的下标,然后取log2+1。

"求二叉树的最大深度,可以根据存储结构用不同的方法。

如果是链式存储的通用二叉树,我会用深度优先搜索(DFS)递归地去算。核心逻辑就是:树的深度 = max(左子树的深度, 右子树的深度) + 1。这个解法的时间复杂度是O(n)。

如果明确知道树是用数组存储的完全二叉树,并且节点是从下标1开始连续存放的,那就可以直接用公式计算:最大深度 = floor(log2(节点数)) + 1。这是一种利用完全二叉树性质的数学解法,可以直接算出来,不需要遍历。"

Q:你了解深度学习吧?有没有用过降维的什么算法?

这里帖主写的PCA,我也跟着复习一遍PCA。

PCA 是一种线性降维算法。核心是找到能让数据方差最大的投影方向,把数据投影到这些方向上去。

具体做法是:

  1. 对数据中心化
  2. 计算协方差矩阵
  3. 对协方差矩阵做特征分解,得到特征值和特征向量
  4. 按特征值从大到小排序,取前 k 个特征向量作为新坐标轴
  5. 把原始数据投影到这些轴上,得到降维结果

优点是算法简单、线性计算快,缺点是不擅长处理非线性数据。

Q:映射回去是怎么做的?

映射矩阵的转置

Q:说一下图神经网络层与层之间是如何相连的?

"图神经网络的层与层之间通过消息传递机制相连。每一层,每个节点根据邻接矩阵找到它的邻居(包括自己),把邻居的特征进行聚合(如求平均、加权和或注意力加权),然后通过一层线性变换和非线性激活,得到该层新的节点表示。多层堆叠后,节点就能逐步融合更大邻域的信息。"

Q:C语言预编译是什么?

一、预编译做什么?(4件事)

预处理指令 作用 例子
#include 文件包含:把头文件内容原封不动地插入到当前位置 #include <stdio.h>
#define 宏定义:把代码中的宏名替换成对应的值或表达式 #define PI 3.14159
#if / #ifdef / #endif 条件编译:根据条件决定保留还是删除某段代码 #ifdef DEBUG ... #endif
#pragma 编译器特殊指令 #pragma once
  1. 宏定义和函数的区别?

宏是文本替换,在预编译阶段完成,没有函数调用开销;但宏不检查类型,且参数会重复计算(如 SQUARE(x++) 有问题)。函数在编译阶段处理,有类型检查。

  1. #include <stdio.h> 和 #include "myheader.h" 的区别?

<> 只在系统默认路径里找(如 /usr/include)。"" 先在当前目录找,找不到再去系统路径找。

  1. #ifndef HEADER_H 这种写法是干什么用的?

防止头文件被重复包含。第一次包含时 HEADER_H 未定义,进入 #define;第二次包含时已经定义,跳过整个文件内容。

六、面试回答模板

"C语言的预编译是编译的第一个阶段,处理所有以 # 开头的预处理指令,包括文件包含(#include)、宏替换(#define)、条件编译(#if)等。这一步是纯文本层面的处理,不涉及任何C语言的语法检查。预编译完成后,输出一个没有预处理指令的 .i 文件,再交给编译器进行真正的编译。"

Q:好,那问你操作系统,你知道进程上下文是什么么?

A:"进程上下文是操作系统为了支持多任务、实现进程切换而保存的一组'状态快照'。

它主要包含三个部分:一是寄存器的值,特别是程序计数器;二是内存管理信息,主要是页表地址;三是内核中与该进程相关的数据结构。

当操作系统决定切换到另一个进程时,它做的就是'保存当前进程的上下文' -> '恢复下一个进程的上下文'这个动作。这个'上下文切换'的过程是理解操作系统调度和性能开销的关键。"

Q:文件读写r和w的区别

模式 全称 文件必须存在 原有内容 读写位置
r read(读) ✅ 必须存在 保留 文件开头
w write(写) ❌ 不存在则创建 清空 文件开头

关键区别

  • r 是只读,不能写;w 是只写,不能读

  • w清空文件原有内容 (如果文件存在),r 不会

常见组合

  • r+:读写,文件必须存在,不清空

  • w+:读写,文件不存在则创建,存在则清空

  • a:追加写,文件不存在则创建,不清空,写入位置在末尾

Q:fopen返回什么

返回 FILE*类型的指针(文件指针),指向一个 FILE 结构体。

这个结构体里包含了:

  • 文件描述符
  • 当前读写位置
  • 缓冲区指针
  • 错误标志、文件结束标志等

返回值判断

  • ✅ 成功:返回有效的 FILE* 指针
  • ❌ 失败:返回 NULL(例如用 r 打开一个不存在的文件)

典型用法

cpp 复制代码
FILE *fp = fopen("test.txt", "r");
if (fp == NULL) {
    perror("打开文件失败");
    return -1;
}

Q:既然有了整数和双精度浮点数,为什么还要存在单精度浮点数?

一句话回答用更少的内存和更快的速度,换取较低的精度------在不需要高精度的场景下更高效。

三种浮点数对比

类型 字节数 有效十进制位数 取值范围
float(单精度) 4 字节 6-7 位 ±1.18e-38 ~ ±3.4e38
double(双精度) 8 字节 15-16 位 ±2.23e-308 ~ ±1.80e308
long double 16 字节 18-21 位 更大

为什么需要 float?

原因 解释
节省内存 4GB 内存存 1 亿个 double 要 800MB,float 只要 400MB
内存带宽 读 4 字节比 8 字节快,数据密集型任务(如图像处理)吞吐量翻倍
SIMD 向量化 AVX 指令集一次可处理 8 个 float 但只能处理 4 个 double
GPU 友好 GPU 对 float 的计算单元远超 double(如游戏显卡双精度只有单精度的 1/32)
深度学习 模型参数量大,用 float16 或 bfloat16 甚至 int8 来加速(NVIDIA Tensor Core)

"单精度浮点数存在的主要原因是:用一半的内存和更高的速度换取足够用的精度。

在图像处理、3D 图形、深度学习等大规模并行计算的场景下,内存带宽和计算速度往往是瓶颈。使用 float 可以让数据传输量减半、向量化指令一次处理更多数据,GPU 上 float 的计算单元也远多于 double。

double 适用于需要高精度的科学计算,但对于绝大多数视觉和 AI 任务,float 的 6-7 位有效数字已经足够。"

相关推荐
To_OC13 小时前
LC 128 最长连续序列:别上来就排序,O (n) 解法才是这题的灵魂
javascript·算法·leetcode
刘马想放假1 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
05Kevin1 天前
lk每日冒险题--数据结构6.27
算法
To_OC2 天前
从一次栈溢出报错说起,我把递归彻底扒明白了
javascript·算法·程序员
千纸鹤安安2 天前
千问Qwen-AgentWorld来了:一个语言模型搞定七大Agent场景,GPT-5.4都输了
算法
七牛开发者2 天前
MCP 到底是什么?为什么 Agent 都想接上它
算法·aigc·agent
北域码匠2 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法