本文为学习数据结构过程中的笔记,内容较为浅显,有问题的评论区见~~
一、基本概念
顺序表是一种有序的数据结构,用于存储一组具有相同数据类型的元素。顺序表中的元素在内存中是连续存放的,因此可以通过下标直接访问元素。
优点:
访问速度快:可以通过下标直接访问元素,时间复杂度为O(1)。
占用空间少:连续存储减少了空间开销。
缺点:
插入和删除操作效率低:需要移动大量元素,时间复杂度为O(n)。
顺序表有两种实现方式:
第一种是分配一块固定的的内存(数组),缺点是我们通常无法事先确定需要存储多少数据,从而难以选择合适的数组长度。若长度过小,则很可能无法满足使用需求;若长度过大,则会造成内存空间浪费。
第二种方式是使用动态数组实现,它继承了数组的各项优点,并且可以在程序运行过程中进行动态扩容。本文主要讨论第二种方式。
二、结构定义
数据类型为int类,capacity用来保存顺序表的容量
// 定义顺序表结构
typedef struct {
int* data;
int capacity;
} DynamicArray;
// 初始化顺序表
void initArray(DynamicArray* array);
// 动态调整顺序表容量
void resizeArray(DynamicArray* array, int newCapacity);
// 插入元素
void insertElement(DynamicArray* array, int element, int position);
// 删除元素
void deleteElement(DynamicArray* array, int position);
// 查找元素
int findElement(DynamicArray* array, int element);
// 修改元素
void updateElement(DynamicArray* array, int position, int newElement);
// 打印
void printArray(DynamicArray* array);
// 释放内存
void freeArray(DynamicArray* array);
三、内容实现
1.初始化顺序表
初始化数据为空,容量为0
void initArray(DynamicArray *array) {
array->data = NULL;
array->capacity = 0;
}
2.动态调整顺序表容量
使用realloc函数先判断当前的指针是否有足够的连续空间,如果有,扩大data指向的地址,并且将data返回,如果空间不够,先按照newCapacity指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来data所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。
void resizeArray(DynamicArray* array, int newCapacity) {
int* newData = (int*)realloc(array->data, newCapacity * sizeof(int));
if (newData) {
array->data = newData;
array->capacity = newCapacity;
}
else {
printf("内存分配失败!\n");
}
}
3.插入元素
先判断插入位置是否合法,然后将顺序表的容量+1,如果插入位置为表的尾部则直接插入,否则需要先移动元素位置再插入,过程如下图:
插入元素5到位置1
void insertElement(DynamicArray* array, int element, int position) {
if (position < 0 || position > array->capacity) {
printf("插入位置无效!\n");
return;
}
//元素容量+1
resizeArray(array, array->capacity + 1);
//尾插则直接插入
if (position == array->capacity - 1) {
array->data[position] = element;
}
else {//否则移动后面元素并插入到指定位置
for (int i = array->capacity - 1; i > position; i--) {
array->data[i] = array->data[i - 1];
}
array->data[position] = element;
}
}
4.删除元素
先判断删除元素的位置是否合法(也可以修改为遍历表来找到对应元素),如果位置位于表尾则直接删除,否则移动元素位置覆盖需要删除的元素,再更新表的容量,过程如下图:
删除位置1的元素2
void deleteElement(DynamicArray* array, int position) {
if (position < 0 || position >= array->capacity) {
printf("删除位置无效!\n");
return;
}
if (position == array->capacity - 1) {
// 对于表尾元素,直接删除
resizeArray(array, array->capacity - 1);
}
else {
// 否则移动表内元素位置
for (int i = position; i < array->capacity - 1; i++) {
array->data[i] = array->data[i + 1];
}
resizeArray(array, array->capacity - 1);
}
}
5.查找元素
通过元素内容来遍历表查找,如果知道元素位置可以直接获取元素内容
int findElement(DynamicArray* array, int element) {
for (int i = 0; i < array->capacity; i++) {
if (array->data[i] == element) {
return i;
}
}
printf("没有该元素\n");
return -1;
}
6.修改元素
先判断修改位置是否合法,将新元素赋值到该位置
void updateElement(DynamicArray* array, int position, int newElement) {
if (position < 0 || position >= array->capacity) {
printf("修改位置无效!\n");
return;
}
array->data[position] = newElement;
}
7.打印表中内容
遍历表并打印
void printArray(DynamicArray* array) {
for (int i = 0; i < array->capacity; i++) {
printf("%d ", array->data[i]);
}
printf("\n");
}
8.释放内存
void freeArray(DynamicArray* array) {
free(array->data);
array->capacity = 0;
}
9.主函数与部分测试用例
int main() {
DynamicArray array;
initArray(&array); // 测试插入元素
printf("测试插入元素:\n");
insertElement(&array, 10, 0);
insertElement(&array, 20, 1);
insertElement(&array, 30, 2);
printf("顺序表内容: ");
printArray(&array); // 测试删除元素
printf("\n测试删除元素:\n");
deleteElement(&array, 1);
printf("删除元素后顺序表内容: ");
printArray(&array); // 测试查找元素
printf("\n测试查找元素:\n");
int position = findElement(&array, 30);
if (position != -1) {
printf("元素30的位置: %d\n", position);
} else {
printf("元素30未找到\n");
}
// 测试修改元素
printf("\n测试修改元素:\n");
updateElement(&array, 0, 15);
printf("修改元素后顺序表内容: ");
printArray(&array); // 测试边界情况
printf("\n测试边界情况:\n");
insertElement(&array, 25, array.capacity); // 插入到最后
deleteElement(&array, 0); // 删除第一个元素
printf("边界情况测试后顺序表内容: ");
printArray(&array); // 释放顺序表内存
freeArray(&array);
return 0;
}
全文完,赏个点赞收藏吧~~