提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
- 一、顺序表的定义及其特点;
- 二、 顺序表的运算(概述);
- 三、顺序表的实现(详细的介绍及C程序代码、执行结果);
- 四、完整的Demo;
- 五、 小结;
一、顺序表的定义及其特点;
- 定义:顺序表是一种线性表,它由一组具有相同数据类型的元素组成,这些元素在内存中占用连续的存储空间。用一组地址连续的存储单元依次存储线性表Q中的数据元素,从而使的逻辑上相邻的两个元素在物理位置上也相邻,采用顺序存储结构的线性表通常称为顺序表。
- 特点:可以通过下标来访问元素,具有随机访问的特性。表中元素的逻辑顺序与物理顺序相同。随机访问,即通过首地址和元素序号可在时间0(1)内找到指定的元素。存储密度高,每个节点只存储数据元素。逻辑上相邻的元素物理上也相邻,所以插入和删除操作需要移动大量元素。
二、顺序表的运算;
顺序表是一种基于数组的数据结构,具有以下运算:
- 创建:创建一个空的顺序表,并确定其大小。
- 插入:在顺序表的任意位置插入一个元素,使得插入后的顺序表仍然保持有序。
- 删除:删除顺序表中的任意位置的元素。
- 查找:查找顺序表中的任意元素。
- 遍历:遍历顺序表中的所有元素,并对其进行操作。
这些运算的时间复杂度可能因为顺序表的具体实现而有所不同。
三、顺序表的实现;
顺序表的实现需要以下几个步骤:
- 定义结构体
首先,我们需要定义一个结构体来表示顺序表,结构体中包含元素类型、元素个数、元素数组等成员变量。
#define MAXSIZE 100 // 最大元素个数 typedef struct { int data[MAXSIZE]; // 元素数组 int length; // 元素个数 } SqList;
- 初始化顺序表
我们需要提供一个初始化函数来创建顺序表,并设置初始元素个数为0。
void InitList(SqList *L) { for (int i = 0; i < MAXSIZE; i++) { L->data[i] = 0; } L->length = 0; }
- 插入元素
插入操作需要移动插入位置后面的元素以腾出空间,然后将其余元素依次后移。当插入位置在表尾时,直接将元素添加到数组末尾。
int ListInsert(SqList *L, int index, int value) { if (index < 1 || index > L->length + 1 || L->length >= MAXSIZE) { return 0; // 插入失败 } for (int i = L->length; i >= index; i--) { L->data[i] = L->data[i - 1]; // 将元素后移 } L->data[index - 1] = value; // 插入新元素 L->length++; // 更新元素个数 return 1; // 插入成功 }
- 删除元素
删除操作需要将删除位置后面的元素向前移动以填补删除位置。当删除位置在表尾时,直接将数组末尾元素置为0。
int ListDelete(SqList *L, int index) { if (index < 1 || index > L->length) { return 0; // 删除失败 } for (int i = index; i < L->length; i++) { L->data[i - 1] = L->data[i]; // 将元素前移 } L->data[L->length - 1] = 0; // 将末尾元素置为0 L->length--; // 更新元素个数 return 1; // 删除成功 }
- 查找元素
顺序表可以通过下标直接访问元素,因此查找操作的时间复杂度为O(1)。在查找之前,我们需要先判断查找的位置是否超出范围。
int ListIndex(SqList *L, int value) { for (int i = 0; i < L->length; i++) { if (L->data[i] == value) { return i + 1; // 返回元素下标+1,因为下标从0开始计数 } } return 0; // 没有找到元素,返回0表示查找失败 }
四、完整的Demo;
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
typedef struct {
int data[MAXSIZE];
int length;
} SqList;
// 初始化顺序表
void InitList(SqList *L) {
for (int i = 0; i < MAXSIZE; i++) {
L->data[i] = 0;
}
L->length = 0;
}
// 插入元素
int ListInsert(SqList *L, int index, int value) {
if (index < 1 || index > L->length + 1 || L->length >= MAXSIZE) {
return 0; // 插入失败
}
for (int i = L->length; i >= index; i--) {
L->data[i] = L->data[i - 1]; // 将元素后移
}
L->data[index - 1] = value; // 插入新元素
L->length++; // 更新元素个数
return 1; // 插入成功
}
// 删除元素
int ListDelete(SqList *L, int index) {
if (index < 1 || index > L->length) {
return 0; // 删除失败
}
for (int i = index; i < L->length; i++) {
L->data[i - 1] = L->data[i]; // 将元素前移
}
L->data[L->length - 1] = 0; // 将末尾元素置为0
L->length--; // 更新元素个数
return 1; // 删除成功
}
// 查找元素
int ListIndex(SqList *L, int value) {
for (int i = 0; i < L->length; i++) {
if (L->data[i] == value) {
return i + 1; // 返回元素下标+1,因为下标从0开始计数
}
}
return 0; // 没有找到元素,返回0表示查找失败
}
// 遍历顺序表并输出所有元素
void PrintList(SqList L) {
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
}
int main() {
SqList L; // 声明一个顺序表变量
InitList(&L); // 初始化顺序表
ListInsert(&L, 1, 10); // 在第一个位置插入元素10
ListInsert(&L, 2, 20); // 在第二个位置插入元素20
ListInsert(&L, 3, 30); // 在第三个位置插入元素30
printf("插入元素后的顺序表:");
PrintList(L); // 输出插入元素后的顺序表
ListDelete(&L, 2); // 删除第二个位置的元素
printf("删除第二个元素后的顺序表:");
PrintList(L); // 输出删除第二个元素后的顺序表
printf("查找元素20的下标:%d\n", ListIndex(&L, 20)); // 查找元素20的下标
printf("查找元素50的下标:%d\n", ListIndex(&L, 50)); // 查找元素50的下标
return 0;
}
运行结果:
插入元素后的顺序表:10 20 30
删除第二个元素后的顺序表:10 30
查找元素20的下标:0
查找元素50的下标:0
五、 小结;
- 顺序表在程序中通常用一维数组实现,一维数组可以是静态分配的,也可以是动态分配的。在静态分配时,由于数组的大小和空间是固定的,一旦空间占满,就无法再新增数据,否则会导致数据溢出。
- 顺序表可以用数组来实现,数组长度一定小于等于顺序表的长度。
- 顺序表的查找、插入、删除等操作都可以在O(1)时间复杂度内完成,但是插入和删除操作需要移动元素。