MST

星途 面试题库

面试题:C语言指针在复杂数据结构内存管理中的应用

假设有一个链表结构,每个节点包含一个整数数据和一个指向下一个节点的指针。请编写函数实现链表节点的动态内存分配、插入新节点、删除指定节点以及释放整个链表内存的操作。说明在这些操作中,指针是怎样对内存进行有效管理,避免内存泄漏的。
39.6万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
#include <stdio.h>
#include <stdlib.h>

// 定义链表节点结构
typedef struct Node {
    int data;
    struct Node* next;
} Node;

// 动态分配新节点内存
Node* createNode(int value) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    if (newNode == NULL) {
        fprintf(stderr, "内存分配失败\n");
        return NULL;
    }
    newNode->data = value;
    newNode->next = NULL;
    return newNode;
}

// 在链表头部插入新节点
void insertAtHead(Node** head, int value) {
    Node* newNode = createNode(value);
    if (newNode != NULL) {
        newNode->next = *head;
        *head = newNode;
    }
}

// 删除指定节点
void deleteNode(Node** head, int value) {
    Node* current = *head;
    Node* prev = NULL;

    // 找到要删除的节点
    while (current != NULL && current->data != value) {
        prev = current;
        current = current->next;
    }

    if (current == NULL) {
        printf("未找到值为 %d 的节点\n", value);
        return;
    }

    // 如果要删除的是头节点
    if (prev == NULL) {
        *head = current->next;
    } else {
        prev->next = current->next;
    }
    free(current);
}

// 释放整个链表内存
void freeList(Node** head) {
    Node* current = *head;
    Node* nextNode;

    while (current != NULL) {
        nextNode = current->next;
        free(current);
        current = nextNode;
    }
    *head = NULL;
}

// 打印链表
void printList(Node* head) {
    Node* current = head;
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

int main() {
    Node* head = NULL;
    insertAtHead(&head, 1);
    insertAtHead(&head, 2);
    insertAtHead(&head, 3);

    printf("链表: ");
    printList(head);

    deleteNode(&head, 2);
    printf("删除节点 2 后链表: ");
    printList(head);

    freeList(&head);
    printf("释放链表后,链表已为空\n");

    return 0;
}

指针内存管理说明

  1. 动态内存分配
    • 使用 malloc 函数为新节点分配内存。如果分配成功,返回指向新分配内存的指针;如果失败,返回 NULL。例如在 createNode 函数中:Node* newNode = (Node*)malloc(sizeof(Node));
  2. 插入新节点
    • insertAtHead 函数中,先创建新节点,然后调整指针。newNode->next = *head; 将新节点的 next 指针指向当前头节点,*head = newNode; 再将头指针更新为新节点,从而完成新节点的插入,确保内存的正确连接。
  3. 删除指定节点
    • deleteNode 函数中,通过遍历链表找到要删除的节点。在删除节点时,调整前一个节点的 next 指针跳过要删除的节点(prev->next = current->next;),然后使用 free 函数释放要删除节点的内存(free(current);),避免内存泄漏。如果要删除的是头节点,直接更新头指针(*head = current->next;)。
  4. 释放整个链表内存
    • freeList 函数中,使用一个临时指针 nextNode 保存当前节点的下一个节点位置,然后释放当前节点的内存(free(current);),再将当前节点移动到下一个节点(current = nextNode;),如此循环直到链表末尾,确保链表中的所有节点内存都被释放,避免内存泄漏。最后将头指针置为 NULL*head = NULL;)。