面试题答案
一键面试#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构体
struct node {
int data;
struct node *next;
};
// 创建新节点
struct node* createNode(int value) {
struct node* newNode = (struct node*)malloc(sizeof(struct node));
if (newNode == NULL) {
fprintf(stderr, "内存分配失败\n");
exit(EXIT_FAILURE);
}
newNode->data = value;
newNode->next = NULL;
return newNode;
}
// 构建链表
struct node* buildList(int n) {
struct node *head = NULL, *tail = NULL;
for (int i = 0; i < n; i++) {
int value;
printf("请输入第 %d 个节点的值: ", i + 1);
scanf("%d", &value);
struct node* newNode = createNode(value);
if (head == NULL) {
head = newNode;
tail = newNode;
} else {
tail->next = newNode;
tail = newNode;
}
}
return head;
}
// 逆序链表
struct node* reverseList(struct node* head) {
struct node *prev = NULL, *current = head, *next = NULL;
while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
return prev;
}
// 打印链表
void printList(struct node* head) {
struct node* current = head;
while (current != NULL) {
printf("%d -> ", current->data);
current = current->next;
}
printf("NULL\n");
}
// 释放链表内存
void freeList(struct node* head) {
struct node* current = head;
struct node* next;
while (current != NULL) {
next = current->next;
free(current);
current = next;
}
}
int main() {
int n;
printf("请输入链表节点的数量: ");
scanf("%d", &n);
struct node* head = buildList(n);
printf("原始链表: ");
printList(head);
head = reverseList(head);
printf("逆序后的链表: ");
printList(head);
freeList(head);
return 0;
}
内存分配与释放性能问题及优化方案
-
性能问题:
- 频繁内存分配:在构建链表过程中,每次使用
malloc
分配内存可能会带来一定的开销,特别是当链表节点数量较多时,这种频繁的系统调用可能会影响性能。 - 内存碎片:频繁的内存分配和释放可能导致内存碎片,使得后续的内存分配请求更难满足,降低内存利用率。
- 频繁内存分配:在构建链表过程中,每次使用
-
优化方案:
- 内存池:可以使用内存池技术,预先分配一块较大的内存空间,然后从这个内存池中分配小块内存给链表节点使用。这样可以减少
malloc
的调用次数,提高性能。 - 批量分配:一次性分配多个节点所需的内存,然后再逐个构建链表节点,这样可以减少内存分配的次数。例如,每次分配10个节点的内存,然后依次使用这些内存构建节点,当用完这10个节点的内存后,再分配下一批。
- 优化释放策略:在释放链表内存时,可以考虑延迟释放或者批量释放,以减少内存碎片的产生。例如,可以将链表节点的内存先标记为可重用,而不是立即释放,当需要新的节点时,优先从这些可重用的节点中获取。
- 内存池:可以使用内存池技术,预先分配一块较大的内存空间,然后从这个内存池中分配小块内存给链表节点使用。这样可以减少