面试题答案
一键面试设计思路
- 内存碎片化问题:
- 尽量减少内存分配和释放的次数。当增加元素时,如果当前数组的剩余空间足够,就直接在原数组上添加元素,避免频繁调用
realloc
导致内存碎片化。 - 当减少元素时,不急于释放内存,而是将释放的空间标记为可用,下次增加元素时优先使用这些标记的空间,从而减少内存碎片。
- 尽量减少内存分配和释放的次数。当增加元素时,如果当前数组的剩余空间足够,就直接在原数组上添加元素,避免频繁调用
- 优化内存使用效率:
- 采用合理的内存增长策略。例如,每次增加元素时,如果原数组已满,按照一定的增长率(如翻倍)来分配新的内存,而不是只增加一个元素的空间,这样可以减少
realloc
的调用次数。 - 减少不必要的内存拷贝。在
realloc
时,如果新分配的内存地址与原地址相同,就不需要进行数据拷贝,直接使用原数据。
- 采用合理的内存增长策略。例如,每次增加元素时,如果原数组已满,按照一定的增长率(如翻倍)来分配新的内存,而不是只增加一个元素的空间,这样可以减少
函数实现
#include <stdio.h>
#include <stdlib.h>
// 自定义结构体
struct Node {
int data;
struct Node *next;
};
// 动态数组管理函数
struct Node* adjustArray(struct Node* arr, int* size, int capacity, int newSize, int growthRate) {
if (newSize < 0) {
printf("Invalid new size.\n");
return arr;
}
if (newSize <= capacity) {
// 减少元素时不释放内存,只更新size
if (newSize < *size) {
*size = newSize;
}
return arr;
}
// 增加元素且原空间不足
int newCapacity = capacity;
while (newSize > newCapacity) {
newCapacity *= growthRate;
}
struct Node* newArr = (struct Node*)realloc(arr, newCapacity * sizeof(struct Node));
if (!newArr) {
printf("Memory allocation failed.\n");
return arr;
}
// 更新size和capacity
*size = newSize;
return newArr;
}
不同情况下的具体实现步骤
- 增加元素:
- 首先检查新的元素个数
newSize
是否超过当前数组的容量capacity
。 - 如果未超过,直接在原数组的
size
位置添加新元素,并更新size
。 - 如果超过,按照设定的增长率(如
growthRate
为2)计算新的容量newCapacity
,直到newCapacity
大于等于newSize
。 - 调用
realloc
分配新的内存空间,并将原数组的数据拷贝到新数组(如果realloc
返回的地址与原地址不同)。 - 更新数组指针
arr
、数组大小size
和数组容量capacity
。
- 首先检查新的元素个数
- 减少元素:
- 检查新的元素个数
newSize
是否小于当前数组的大小size
。 - 如果是,只更新
size
,不释放内存,标记释放的空间为可用,供下次增加元素时使用。 - 如果
newSize
大于等于size
,则不做任何处理,返回原数组。
- 检查新的元素个数
示例使用
int main() {
struct Node* arr = NULL;
int size = 0;
int capacity = 0;
int growthRate = 2;
// 增加元素
arr = adjustArray(arr, &size, capacity, 5, growthRate);
capacity = 5;
// 减少元素
arr = adjustArray(arr, &size, capacity, 3, growthRate);
free(arr);
return 0;
}
这样设计可以在一定程度上解决内存碎片化问题并优化内存使用效率。