方法1:标记删除(逻辑删除)
不真正删除元素,而是用特殊标记(如id = -1)表示该元素已删除,后续操作跳过这些标记。
示例代码
#include <stdio.h>
typedef struct {
int id;
char name[20];
} Student;
void printStudents(Student students[], int size) {
for (int i = 0; i < size; i++) {
if (students[i].id != -1) { // 跳过已删除的元素
printf("ID: %d, Name: %s\n", students[i].id, students[i].name);
}
}
}
int main() {
Student students[5] = {
{1, "Alice"},
{2, "Bob"},
{3, "Charlie"},
{4, "David"},
{5, "Eve"}
};
// 删除ID为3的学生(逻辑删除)
for (int i = 0; i < 5; i++) {
if (students[i].id == 3) {
students[i].id = -1; // 标记为已删除
break;
}
}
printf("After deletion:\n");
printStudents(students, 5);
return 0;
}
输出:
After deletion:
ID: 1, Name: Alice
ID: 2, Name: Bob
ID: 4, Name: David
ID: 5, Name: Eve
方法2:物理删除(移动元素覆盖)
将待删除元素后的所有元素向前移动一位,并更新有效数组长度。
示例代码
#include <stdio.h>
typedef struct {
int id;
char name[20];
} Student;
void printStudents(Student students[], int size) {
for (int i = 0; i < size; i++) {
printf("ID: %d, Name: %s\n", students[i].id, students[i].name);
}
}
int main() {
Student students[5] = {
{1, "Alice"},
{2, "Bob"},
{3, "Charlie"},
{4, "David"},
{5, "Eve"}
};
int size = 5;
// 删除ID为3的学生(物理删除)
for (int i = 0; i < size; i++) {
if (students[i].id == 3) {
// 将后面的元素前移
for (int j = i; j < size - 1; j++) {
students[j] = students[j + 1];
}
size--; // 更新有效长度
break;
}
}
printf("After deletion:\n");
printStudents(students, size);
return 0;
}
输出:
After deletion:
ID: 1, Name: Alice
ID: 2, Name: Bob
ID: 4, Name: David
ID: 5, Name: Eve
关键点总结
- 逻辑删除:简单高效,但会浪费内存,适合删除操作较少的场景。
- 物理删除:节省内存,但需要移动元素,效率较低(时间复杂度O(n))。
- 动态数组:如果频繁增删,建议使用动态数组(如
malloc+realloc)或链表结构。
进阶:动态数组 + 结构体
如果需要频繁增删,可以结合动态内存管理实现更灵活的数组操作。
示例代码
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int id;
char name[20];
} Student;
int main() {
int capacity = 5;
int size = 5;
Student *students = malloc(capacity * sizeof(Student));
// 初始化数据...
students[0] = (Student){1, "Alice"};
students[1] = (Student){2, "Bob"};
students[2] = (Student){3, "Charlie"};
students[3] = (Student){4, "David"};
students[4] = (Student){5, "Eve"};
// 删除ID为3的学生
for (int i = 0; i < size; i++) {
if (students[i].id == 3) {
for (int j = i; j < size - 1; j++) {
students[j] = students[j + 1];
}
size--;
break;
}
}
// 打印结果
for (int i = 0; i < size; i++) {
printf("ID: %d, Name: %s\n", students[i].id, students[i].name);
}
free(students);
return 0;
}
选择建议
- 静态数组:数据量固定,删除操作少时用逻辑删除。
- 动态数组:数据量变化频繁时,用物理删除 +
realloc调整大小。 - 链表:频繁增删时更高效(但C语言需手动实现)。
