概念
顺序表是由一组元素组成的线性集合,这些元素按照一定的顺序排列,每个元素都有一个确定的位置。在顺序表中,元素之间的关系是一对一的关系,即除了第一个和最后一个元素外,每个元素都有唯一的前驱和后继。
数据存储
顺序表通常采用数组来实现。这意味着所有元素都存储在连续的内存地址中。数组的索引或下标用于访问顺序表中的元素。例如,一个包含5个元素的顺序表可以表示为 array[0...4]
。
特性
- 顺序性:顺序表中的元素是按照一定的顺序存储的,可以是递增或递减,也可以是其他特定的顺序。
- 随机访问:由于元素在内存中连续存储,可以通过索引直接访问任何一个元素,访问时间复杂度为O(1)。
- 固定容量:对于静态顺序表,其容量在创建时确定,之后不可更改。动态顺序表则可以在需要时扩展容量。
基本操作
以下是一些顺序表的基本操作:
初始化:创建一个空的顺序表,并为其分配初始容量
#include <stdio.h>
#include<stdlib.h>
#include"head.h"
// 创建一个空的顺序表
seqlist_p CreatEpSeqlist()
{
seqlist_p p = (seqlist_p)malloc(sizeof(seqlist_t));
if (NULL == p)
{
perror("malloc lost"); // perror打印上一个函数报的错误
return NULL; // 错误情况让函数返回空指针
}
// 对结构体初始化
p->last = -1;//当数组为空时下标为-1
return p;
}
插入:在顺序表的指定位置插入一个新元素
#include <stdio.h>
#include<stdlib.h>
#include"head.h"
// 向顺序表的指定位置插入一个元素
int InsertSeqlist(seqlist_p p, int post, int data)
{
// 容错判断:判断数组空间是否足够,对post判断
if (IsFullSeqlist(p) || post < 0 || post > p->last + 2)
{
printf("error\n");
return -1; // 错误返回
}
else
{
int i = p->last;
while (i >= post-1)
{
p->data[i + 1] = p->data[i];
i--;
}
p->data[post-1] = data;
p->last++;
}
return 0;
}
删除:删除顺序表中指定位置的元素
#include <stdio.h>
#include<stdlib.h>
#include"head.h"
// 删除顺序表指定位置的元素
int DeleteSeqlist(seqlist_p p, int post)
{
// 容错判断:判断数组空间是否,对post判断
if (IsEpSeqlist(p)||post < 0 || post >= p->last + 2)
{
printf("error\n");
return -1; // 错误返回
}
else
{
int i = post - 1;
while (i < p->last)
{
p->data[i] = p->data[i + 1];
i++;
}
p->last--;
}
return 0;
}
查找:在顺序表中查找特定的元素,并返回其位置
#include <stdio.h>
#include<stdlib.h>
#include"head.h"
//查找指定数据出现的位置,返回下标,未找到返回-1
int SerchSqelist(seqlist_p p, int data)
{
for(int i=0;i<=p->last;i++)
{
if(p->data[i]==data)
return i;
}
return -1;
}
修改:修改顺序表中指定位置的元素值
#include <stdio.h>
#include <stdlib.h>
#include "head.h"
// 修改顺序表指定位置的元素
int ChangeSeqlist(seqlist_p p, int post, int data)
{
// 容错判断:判断数组空间是否为空,对post判断
if (IsEpSeqlist(p) || post < 0 || post >= p->last + 2)
{
perror("error");
return -1; // 错误返回
}
else
{
p->data[post - 1] = data;
}
return 0;
}
遍历:循环遍历顺序表
#include <stdio.h>
#include<stdlib.h>
#include"head.h"
// 循环遍历顺序表
void show(seqlist_p p)
{
for (int i = 0; i <= p->last; i++)
{
printf("%d ", p->data[i]);
}
printf("\n");
}
优缺点
优点:
- 随机访问能力强,访问任何一个元素的时间复杂度都是O(1)。
- 存储密度高,不需要额外空间存储节点间关系。
缺点:
- 插入和删除操作需要移动大量元素,时间复杂度为O(n)。
- 静态顺序表长度固定,可能导致空间浪费或不足。
- 动态顺序表在扩容时可能需要复制整个数组,效率较低。
代码示例:
头文件
#define N 10
typedef struct seqlist // 封装顺序表结构体类型
{
int data[N]; // 存储数据的数组
int last; // 数组中最后一个有效元素的下标
} seqlist_t, *seqlist_p;
seqlist_p CreatEpSeqlist() ;
int IsFullSeqlist(seqlist_p p);
int IsEpSeqlist(seqlist_p p);
int InsertSeqlist(seqlist_p p, int post, int data) ;
int DeleteSeqlist(seqlist_p p, int post) ;
int SerchSqelist(seqlist_p p, int data);
int ChangeSeqlist(seqlist_p p, int post,int data) ;
void show(seqlist_p p) ;
容错判断
#include <stdio.h>
#include<stdlib.h>
#include"head.h"
// 判断顺序表是否为满,满返回1,未满返回0
int IsFullSeqlist(seqlist_p p)
{
return p->last + 1 == N;//return 1
}
// 判断顺序表是否为空,空返回1,非空返回0
int IsEpSeqlist(seqlist_p p)
{
return p->last == -1;//return 1
}
创建空顺序表
#include <stdio.h>
#include<stdlib.h>
#include"head.h"
// 创建一个空的顺序表
seqlist_p CreatEpSeqlist()
{
seqlist_p p = (seqlist_p)malloc(sizeof(seqlist_t));
if (NULL == p)
{
perror("malloc lost"); // perror打印上一个函数报的错误
return NULL; // 错误情况让函数返回空指针
}
// 对结构体初始化
p->last = -1;//当数组为空时下标为-1
return p;
}
在指定位置插入元素
#include <stdio.h>
#include<stdlib.h>
#include"head.h"
// 向顺序表的指定位置插入一个元素
int InsertSeqlist(seqlist_p p, int post, int data)
{
// 容错判断:判断数组空间是否足够,对post判断
if (IsFullSeqlist(p) || post < 0 || post > p->last + 2)
{
printf("error\n");
return -1; // 错误返回
}
else
{
int i = p->last;
while (i >= post-1)
{
p->data[i + 1] = p->data[i];
i--;
}
p->data[post-1] = data;
p->last++;
}
return 0;
}
删除指定位置的元素
#include <stdio.h>
#include<stdlib.h>
#include"head.h"
// 删除顺序表指定位置的元素
int DeleteSeqlist(seqlist_p p, int post)
{
// 容错判断:判断数组空间是否,对post判断
if (IsEpSeqlist(p)||post < 0 || post >= p->last + 2)
{
printf("error\n");
return -1; // 错误返回
}
else
{
int i = post - 1;
while (i < p->last)
{
p->data[i] = p->data[i + 1];
i++;
}
p->last--;
}
return 0;
}
修改指定位置的元素
#include <stdio.h>
#include <stdlib.h>
#include "head.h"
// 修改顺序表指定位置的元素
int ChangeSeqlist(seqlist_p p, int post, int data)
{
// 容错判断:判断数组空间是否为空,对post判断
if (IsEpSeqlist(p) || post < 0 || post >= p->last + 2)
{
perror("error");
return -1; // 错误返回
}
else
{
p->data[post - 1] = data;
}
return 0;
}
查找指定数据出现的位置
#include <stdio.h>
#include<stdlib.h>
#include"head.h"
//查找指定数据出现的位置,返回下标,未找到返回-1
int SerchSqelist(seqlist_p p, int data)
{
for(int i=0;i<=p->last;i++)
{
if(p->data[i]==data)
return i;
}
return -1;
}
循环遍历顺序表
#include <stdio.h>
#include<stdlib.h>
#include"head.h"
// 循环遍历顺序表
void show(seqlist_p p)
{
for (int i = 0; i <= p->last; i++)
{
printf("%d ", p->data[i]);
}
printf("\n");
}
主函数文件
#include <stdio.h>
#include<stdlib.h>
#include"head.h"
int main(int argc, char const *argv[])
{
seqlist_p p = CreatEpSeqlist(); // 定义一个结构体类型的指针接收函数的返回值
InsertSeqlist(p, 1, 1);
InsertSeqlist(p, 2, 2);
InsertSeqlist(p, 3, 3);
show(p);
DeleteSeqlist(p,2);
show(p);
ChangeSeqlist(p,1,0);
show(p);
printf("%d\n",SerchSqelist(p,3));
return 0;
}
程序运行结果
1 2 3
1 3
0 3
1