面试题答案
一键面试数据结构设计
- 环形缓冲区(Circular Buffer):
- 定义:环形缓冲区是一种适合在数据接收场景下使用的数据结构,它可以高效地处理数据的读写操作,避免频繁的内存分配和释放。
- 结构:
typedef struct {
char *buffer;
size_t size;
size_t read_index;
size_t write_index;
} CircularBuffer;
- 解释:
buffer
是一个字符指针,指向实际存储数据的内存区域。size
表示缓冲区的总大小。read_index
记录当前读取数据的位置。write_index
记录当前写入数据的位置。
操作流程
- 初始化缓冲区:
CircularBuffer *initCircularBuffer(size_t size) {
CircularBuffer *cb = (CircularBuffer *)malloc(sizeof(CircularBuffer));
if (cb == NULL) {
return NULL;
}
cb->buffer = (char *)malloc(size);
if (cb->buffer == NULL) {
free(cb);
return NULL;
}
cb->size = size;
cb->read_index = 0;
cb->write_index = 0;
return cb;
}
- 写入数据(处理接收数据):
int writeToCircularBuffer(CircularBuffer *cb, const char *data, size_t len) {
size_t available = (cb->size - cb->write_index + cb->read_index) % cb->size;
if (len > available) {
// 缓冲区空间不足,根据策略处理,这里简单返回错误
return -1;
}
size_t part1 = cb->size - cb->write_index;
if (len <= part1) {
memcpy(cb->buffer + cb->write_index, data, len);
cb->write_index += len;
} else {
memcpy(cb->buffer + cb->write_index, data, part1);
memcpy(cb->buffer, data + part1, len - part1);
cb->write_index = len - part1;
}
return 0;
}
- 读取数据(处理发送数据或其他业务逻辑):
int readFromCircularBuffer(CircularBuffer *cb, char *data, size_t len) {
size_t available = (cb->write_index - cb->read_index + cb->size) % cb->size;
if (len > available) {
len = available;
}
size_t part1 = cb->size - cb->read_index;
if (len <= part1) {
memcpy(data, cb->buffer + cb->read_index, len);
cb->read_index += len;
} else {
memcpy(data, cb->buffer + cb->read_index, part1);
memcpy(data + part1, cb->buffer, len - part1);
cb->read_index = len - part1;
}
return len;
}
-
带宽控制与缓冲区协调:
- 带宽控制可以通过设置定时器或者使用令牌桶算法等方式实现。例如,使用令牌桶算法,在每次从网络接收数据前,先检查令牌桶中是否有足够的令牌。如果有,则可以接收数据并写入缓冲区;如果没有,则等待令牌桶补充令牌后再接收。
- 在写入缓冲区时,要实时检查缓冲区的可用空间,避免溢出。如上述
writeToCircularBuffer
函数中,先计算可用空间,若数据长度超过可用空间,则根据具体策略处理(这里简单返回错误,实际中可丢弃部分数据等)。 - 在读取缓冲区数据时,要根据带宽控制的速率,合理安排读取速度,避免数据丢失。如上述
readFromCircularBuffer
函数中,根据缓冲区中已有的数据量调整实际读取的长度。
-
释放缓冲区:
void freeCircularBuffer(CircularBuffer *cb) {
free(cb->buffer);
free(cb);
}