引言
读前须知:阅读需要一定的C语言基础,顺序表的概念篇可参考我的上上期博客。
顺序表(Sequential List)是一种常见的线性数据结构,通过连续的内存空间来存储数据。本文将介绍如何使用C语言实现顺序表,包括其定义、初始化、插入、删除、查找等操作。
一、顺序表的定义
首先,我们通过定义一个结构体来表示顺序表。在这个结构体中,结构体的元素可以是任意类型,我们使用一个整数指针来存储顺序表的元素,并且用两个size_t
类型的变量来表示顺序表的当前大小和容量。
二、顺序表的初始化
我们使用一个函数来初始化顺序表。该函数接受一个顺序表指针和一个容量参数,然后为顺序表分配内存,并初始化其大小和容量。
(1)初始化顺序表的函数,接受一个SequentialList类型的指针和一个整型为参数;
(2)在函数内部,通过malloc函数为数组分配容量,并赋值给list->elements成员变量用来存储顺序表的元素;
(3)初始化顺序表为零,即此时顺序表里面没有元素;
(4)list->capacity将传递进来的容量初始化,即初始化顺序表的容量;
三、顺序表的销毁
为了避免内存泄漏,我们需要一个函数来销毁顺序表,释放其占用的内存。
(1)销毁顺序表的函数,接受一个SequentialList类型的指针;
(2)检查内存是否已分配,
if (list->elements != NULL),
只有在顺序表的内存已经分配的情况下才进行释放;
(3)释放内存,free(list->elements),
释放顺序表的内存;
(4)避免悬挂指针,list->elements = NULL,
将指针设置为NULL,避免使用已释放的内存
四、获取顺序表的元素个数
我们可以通过一个函数来获取顺序表的当前大小。
返回顺序表的大小;
五、顺序表的元素插入
我们可以在指定位置插入元素。需要注意的是,当顺序表的容量不足时,我们需要重新分配内存以扩展容量。
(1)检查索引有效性:
if (index < 0 || index > list->size)
检查插入位置是否有效。(2)检查容量:
if (list->size == list->capacity)
检查当前顺序表是否已满。(3)重新分配内存:
int* newElements = (int*)realloc(list->elements, sizeof(int) * list->capacity * 2);
if (newElements == NULL)
{
printf("Failed to allocate memory\n");
return;
}
(4)扩容:list->elements = newElements,将顺序表的首地址指向新的数组;
list->capacity *= 2,一般进行倍数扩容;
(5)移动元素:
for (size_t i = list->size; i > index; i--)
{
list->elements[i] = list->elements[i - 1];
}
从插入位置开始,将所有元素向后移动一位。
(6)插入元素:
list->elements[index] = element;
在指定位置插入新元素。(7)更新大小:
list->size++;
更新顺序表的大小。
六、顺序表的元素删除
我们可以删除指定位置的元素,并将后面的元素向前移动。
(1)检查删除位置的有效性;
(2)将删除位置后面的元素向前移动一位;
(3)更新顺序表的大小;
七、顺序表的元素查找
我们可以查找指定元素在顺序表中的位置。
(1)遍历顺序表所有元素;
(2)找到元素,返回其索引;
(3)未找到返回-1;
八、顺序表的元素获取
我们可以通过索引来获取顺序表中的元素。
(1)检查索引的有效性,错误值返回-1;
(2)返回指定索引处的元素;
九、顺序表的元素修改
我们可以修改顺序表中指定位置的元素。
(1)检查索引的有效性;
(2)修改指定索引处的元素;
完整代码
以下是完整的顺序表实现代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>//顺序表的C代码实现
//顺序表定义
//顺序表的元素可以是任意类型,以整数为例,利用结构体进行定义
typedef struct {
int* elements;//一个指向整数数组的指针
size_t size;//size表示当前顺序表的大小,即元素的个数
size_t capacity;//capacity表示顺序表的容量
}SequentialList;
//顺序表的初始化
void SeqentialListInit(SequentialList* list, int capacity)//(1)
{
list->elements = (int*)malloc(sizeof(int) * capacity);//(2)
list->size = 0;//(3)
list->capacity = capacity;//(4)
}
//顺序表的销毁
void SeqentlListDestroy(SequentialList* list)//(1)
{
if (list->elements != NULL)
{
free(list->elements);//(2)
list->elements = NULL;
}
}
//顺序表的元素个数
size_t SequentialListSize(const SequentialList * list)
{
return list->size;
//返回顺序表的大小
}
//顺序表的元素插入
void SequentlListInsert(SequentialList* list, int index, int element)
{
if (index<0 || index >list -> size)
{
printf("Invalid index\n");//(1)
return;
}
if (list->size == list->capacity)//(2)
{
int* newElements = (int*)realloc(list->elements, sizeof(int) * list->capacity * 2);//(3)
if (newElements == NULL)
{
printf("Failed to allocate memory\n");
return;
}
list->elements = newElements;//(4)
list->capacity *= 2;
for (size_t i = list->size;i > index;i--)
{
list->elements[i] = list->elements[i - 1];
}
list->elements[index] = element;//(6)
list->size++;//(7)
}
}//顺序表的元素删除
void SequentialListDelete(SequentialList* list, int index)
{
if (index<0 || index >list->size)
{
printf("Invalid index\n");//(1)
return ;
}
for (size_t i = index;i < list->size;i++)
{
list->elements[i] = list->elements[i + 1];//(2)
}list->size--;//(3)
}//顺序表的元素查找
int SequentialListFind(SequentialList* list, int element)
{
for (size_t i = 0;i < list->size;i++)//(1)
{
if (element == list->elements[i])//(2)
return i;
return -1;//(3)
}
}//顺序表的元素索引
int SequentialListFind(SequentialList* list,int index, int element)
{
if (index<0 || index >list->size)
{
printf("Invalid index\n");//(1)
return -1;
}return list->elements[index];//(2)
}
//顺序表的元素修改
void SequentialListFind(SequentialList* list, int index, int element)
{
if (index<0 || index >list->size)
{
printf("Invalid index\n");//(1)
return ;
}list->elements[index]=element;//(2)
}
通过以上代码,我们实现了顺序表的基本操作。希望这篇博客能帮助你理解顺序表的实现原理,并能在实际项目中灵活应用。