在计算机科学中,数据结构是处理和组织数据的方法和技术。顺序表是一种常见的线性表数据结构,它基于数组实现,提供了快速的随机访问能力。本文将详细介绍顺序表的定义、特点以及常见操作。
1. 顺序表的定义与特点
顺序表是一种线性表的实现方式,它使用一块连续的内存空间存储元素,并通过下标来访问和操作元素。顺序表具有以下特点:
- 连续存储:顺序表使用数组来存储元素,数组中的元素在内存中是连续存储的。
- 随机访问:由于元素在内存中连续存储,可以通过下标直接访问任意位置的元素,具有快速的随机访问能力。
- 插入和删除的复杂度较高:在顺序表中插入和删除元素时,需要移动其他元素以保持顺序,因此插入和删除的时间复杂度较高。
- 固定长度:顺序表的长度是固定的,需要预先分配足够的内存空间来存储元素。
2. 顺序表的操作
2.1 构造顺序表
顺序表在C语言中无法用现有的类型来定义,故需要使用构造类型进行构造出顺序表。
当构造顺序表时,您需要先定义一个结构体来表示顺序表,并分配足够的内存空间来存储元素。
示例代码如下:
#define MAX_SIZE 100 // 宏替换
struct SequentialList {
int data[MAX_SIZE];//MAX_SIZE是一个常量,表示数组空间的大小
int num; // 当前顺序表中的元素个数
int size;//当前所申请数组空间的大小
};
在上面的示例中,我们首先定义了一个结构体 SequentialList
,其中包含一个数组 data
用于存储元素,以及一个整型变量 num 表示当前顺序表中的元素个数和size表示数组所能存储的大小。
2.2 创建顺序表
当构造出顺序表结构后,就要创建顺序表,顺序表的创建 即顺序表初始化,示例代码如下:
struct SequentialList * create()
{
//调用malloc函数申请空间
struct SequentialList *p = malloc(sizeof(struct SequentialList));
p->num = 0;//新创建的顺序表元素为0
p->size = MAX_SIZE;//构造中数组的大小
return p;
}
在上述示例中,函数 create()
使用 malloc()
函数为顺序表分配了足够的内存空间,并将其地址赋给指针 p
。然后,通过 p->num
将顺序表的元素个数初始化为 0,p->size记录了顺序表中能存储的最大元素个数,并返回指针 p
。
2.2 判断顺序表是否为空
判断顺序表是否为空可以通过判断顺序表的个数是否为 0 来实现。示例代码如下:
// 判断顺序表是否为空
int isEmpty(struct SequentialList* p) {
return p->num == 0;
}
2.3 判断顺序表是否已满
判断顺序表是否已满可以通过判断个数是否达到最大个数来实现。示例代码如下:
// 判断顺序表是否已满
int isFull(struct SequentialList* p) {
return p->num == p->size;
}
2.4 获取顺序表的长度
获取顺序表的长度即为获取当前顺序表中元素的个数。示例代码如下:
// 获取顺序表的长度
int getLength(struct SequentialList* p) {
return p->num;
}
2.5 在指定位置插入元素
顺序表在进行插入和删除时,复杂度较高,故理解顺序表的插入和删除过程是非常有必要的,在顺序表的指定位置插入元素时,防止因插入而破坏顺序表逻辑结构(线性结构,唯一前驱,唯一后继)需要将插入位置之后的元素依次后移,并将新元素插入到指定位置。故如何移动,是我们要特别注意的,从插入元素的位置开始依次往后移动,那么这样移动就会造成前面所移动的值覆盖后面的值(在未插入前,顺序表是一个接一个的,当插入元素时就会破坏这种结构,要插入位置的空间是已经被占用的,且顺序表空间是连续的,当这个位置向后移动时就会覆盖原来空间的值,从而破坏顺序表结构),这种移动方式是行不通的,那我们要怎么去移动才能保证不会破坏顺序表结构,我们这样找到往后移的位置是没有值(后移位置的空间存在且没有值),通过这样分析我们可以得到顺序表最后一个元素(顺序表数组空间允许下)往后移是不会覆盖顺序表的值,故当顺序表未满时进行插入就需要从顺序表尾开始依次往后移,直到移动到要插入元素位置时进行插入。
顺序表满不进行插入。
示例代码如下:
// 在指定位置插入元素
void insert(struct SequentialList* p, int position, int element) {
if (isFull(p)) {
printf("顺序表已满,无法插入元素。\n");
return;
}
if (position < 0 || position > list->size) {
printf("插入位置不合法。\n");
return;
}
// 将插入位置之后的元素后移
for (int i = p->num - 1; i >= position; i--) {
list->data[i + 1] = list->data[i];
}
// 插入新元素
p->data[position] = element;
p->num++;
}
2.6 删除指定位置的元素
删除过程相对于插入过程就要简单一些,删除过程就是将要删除的元素进行覆盖进行,即只要将删除元素的后一个元素前移就可以进行将删除元素覆盖,保证顺序表结构,后面元素也要依次前移。当然顺序表为空不进行删除。即删除顺序表的指定位置元素需要将删除位置之后的元素依次前移,并更新顺序表的长度。
示例代码如下:
// 删除指定位置的元素
void delete(struct SequentialList* p, int position) {
if (isEmpty(p)) {
printf("顺序表为空,无法删除元素。\n");
return;
}
if (position < 0 || position >= p->num) {
printf("删除位置不合法。\n");
return;
}
// 将删除位置之后的元素前移
for (int i = position; i < p->num - 1; i++) {
p->data[i] = p->data[i + 1];
}
p->num--;
}
2.7 获取指定位置的元素
获取顺序表的指定位置元素即为通过下标访问对应位置的元素。示例代码如下:
// 获取指定位置的元素
int getElement(struct SequentialList* p, int position) {
if (position < 0 || position >= p->num) {
printf("访问位置不合法。\n");
return -1; // 返回一个特殊值表示出错
}
return p->data[position];
}
2.8遍历顺序表元素
通过循环输出顺序表元素,示例代码如下:
void show(struct SequentialList *p)
{
for(int i = 0;i < p->num;i++)
{
printf("%d ",p->data[i]);
}
printf("\n");
}
总体代码
#define MAX_SIZE 100 // 宏替换
//构造顺序表
struct SequentialList {
int data[MAX_SIZE];//MAX_SIZE是一个常量,表示数组空间的大小
int num; // 当前顺序表中的元素个数
int size;//当前所申请数组空间的大小
};
//创建顺序表
struct SequentialList * create()
{
//调用malloc函数申请空间
struct SequentialList *p = malloc(sizeof(struct SequentialList));
p->num = 0;//新创建的顺序表元素为0
p->size = MAX_SIZE;//构造中数组的大小
return p;
}
// 判断顺序表是否为空
int isEmpty(struct SequentialList* p) {
return p->num == 0;
}
// 判断顺序表是否已满
int isFull(struct SequentialList* p) {
return p->num == p->size;
}
// 获取顺序表的长度
int getLength(struct SequentialList* p) {
return p->num;
}
// 在指定位置插入元素
void insert(struct SequentialList* p, int position, int element) {
if (isFull(p)) {
printf("顺序表已满,无法插入元素。\n");
return;
}
if (position < 0 || position > list->size) {
printf("插入位置不合法。\n");
return;
}
// 将插入位置之后的元素后移
for (int i = p->num - 1; i >= position; i--) {
list->data[i + 1] = list->data[i];
}
// 插入新元素
p->data[position] = element;
p->num++;
}
// 删除指定位置的元素
void delete(struct SequentialList* p, int position) {
if (isEmpty(p)) {
printf("顺序表为空,无法删除元素。\n");
return;
}
if (position < 0 || position >= p->num) {
printf("删除位置不合法。\n");
return;
}
// 将删除位置之后的元素前移
for (int i = position; i < p->num - 1; i++) {
p->data[i] = p->data[i + 1];
}
p->num--;
}
// 获取指定位置的元素
int getElement(struct SequentialList* p, int position) {
if (position < 0 || position >= p->num) {
printf("访问位置不合法。\n");
return -1; // 返回一个特殊值表示出错
}
return p->data[position];
}
//遍历
void show(struct SequentialList *p)
{
for(int i = 0;i < p->num;i++)
{
printf("%d ",p->data[i]);
}
printf("\n");
}
int main() {
struct SequentialList* p = create(); // 创建顺序表并获取指针
// 此时,顺序表已经创建完成,并可以进行操作
// 例如,可以通过 p->data 访问数组,通过 p->length 访问元素个数
for(int i = 1;i < 11;i++)
{
insert(p,i,i);//插入元素(循环插入1-10)
}
show(p);//遍历
delete(p,5);//删除下标为5的元素
show(p);
return 0;
}
3. 总结
顺序表是一种基于数组实现的线性表数据结构,具有快速的随机访问能力。它适用于需要频繁随机访问元素的场景,但插入和删除操作的效率相对较低。通过本文的介绍,您应该对顺序表的定义、特点以及常见操作有了更深入的了解。
希望本文对您理解顺序表有所帮助,感谢您的阅读!