线性表可以用顺序存储结构和链式存储结构。用顺序存储结构实现的线性表称作顺序表,用链式存储结构实现的线性表称作链表。链表主要有单链表,循环单链表和双向循环链表。
顺序表的存储结构
实现顺序存储结构的方法是使用数组。数组满足顺序表的特点:逻辑上相邻的元素在物理存储上也相邻。
//结构体定义
typedef struct {
Datatype list[Maxsize];//Datatype表示存储的元素的数据类型,数组用来存储数据
int size;//元素个数
}Sequlist;
其中数组可以动态申请
Datatype* list;//数组的首地址
int maxlength;//最大分配的存储容量
int size;//元素个数
顺序表操作的实现(数组是静态数组)
初始化顺序表:void Listintiate(Sequlist*L)
void Listintiate(Sequlist*L) {
L->size = 0;//元素个数初始化为0
}
求当前元素个数:int Listlength(Sequlist* L)
int Listlength(Sequlist* L) {
return L->size;//返回元素个数
}
插入元素:int Listinsert(Sequlist* L, int i, Datatype x)
i表示插入的位置,x表示要插入的元素
1.先判断参数i是否合法和顺序表是否已满
2.如果均没有,将数组中的元素从最后的位置开始向后移动,直到空出指定的位置
3.插入元素,更新元素个数
int Listinsert(Sequlist* L, int i, Datatype x) {
if (L->size >= Maxsize) {
printf("顺序表已满\n");
return 0;
}
else if (i<0 || i>L->size) {
printf("参数i不合适\n");
return 0;
}
else {
for (int j = L->size;j > i;j--) {
L->list[j] = L->list[j - 1];
}
L->list[i] = x;
L->size++;
printf("存入数据成功\n");
return 1;
}
}
删除元素:int Listdelete(Sequlist* L, int i, Datatype* x)
返回数据类型:1——删除成功,0——删除失败
i需要删除的位置的下标,x存储被删除的元素
1.判断顺序表是否为空,参数i是否合法
2.找到需要删除的元素,存储在x中
3.将位置i后面的元素向前移动,更新顺序表元素个数
int Listdelete(Sequlist* L, int i, Datatype* x) {
if (L->size <= 0) {
printf("顺序表为空\n");
return 0;
}
else if (i<0 || i>L->size) {
printf("参数i不合适\n");
return 0;
}
else {//如果i要表示第几个,i改为i-1
*x = L->list[i];
for (int j = i;j < L->size;j++) {
L->list[j] = L->list[j + 1];
}
L->size--;
printf("删除数据成功\n");
return 1;
}
}
取元素:int Listget(Sequlist* L, int i, Datatype* x)
返回类型:1——获取成功,0——获取失败
i表示想要获取的元素的下标,x存储获取到的元素
int Listget(Sequlist* L, int i, Datatype* x) {
if (i<0 || i>=L->size) {
printf("参数i不合适\n");
return 0;
}
else if (L->size == 0) {
printf("顺序表为空\n");
return 0;
}
else {
*x = L->list[i];
return 1;
}
}
顺序表操作的效率分析
顺序表中的插入与删除操作时顺序表中时间复杂度最高的操作。
插入操作:若i=size,在最后位置插入,根本无需移动(特别快);若i=0,在最前面插入,表中元素全部要后移(特别慢);考虑在各种位置插入(共n+1种可能)的平均移动次数:设Pi是在第i个存储位置插入一个数据元素的概率,顺序表中的数据元素个数为n,当在顺序表的任何位置上插入数据元素的概率相等时,有Pi=1/(n+1),则 插入时的平均移动次数为:(1/n+1)(1+2+3+4+……+n)=n/2
同理可得,顺序表删除元素的平均移动次数为:(1/n)(1+2+3+4+……+n-1)=(n-1)/2
顺序表的优点:算法简单,内存单元利用率较高,缺点:需要预先去欸的那个元素的 最大个数
完整的代码:
#include <stdio.h>
#include <stdlib.h>
//顺序表
#define Maxsize 80
typedef int Datatype;
typedef struct {
Datatype list[Maxsize];
int size;
}Sequlist;
//初始化顺序表
void Listintiate(Sequlist*L) {
L->size = 0;
}
//元素个数
int Listlength(Sequlist* L) {
return L->size;
}
//插入数据
int Listinsert(Sequlist* L, int i, Datatype x) {
if (L->size >= Maxsize) {
printf("顺序表已满\n");
return 0;
}
else if (i<0 || i>L->size) {
printf("参数i不合适\n");
return 0;
}
else {
int j;
for (j = L->size;j > i;j--) {
L->list[j] = L->list[j - 1];
}
L->list[i] = x;
L->size++;
printf("存入数据成功\n");
return 1;
}
}
//删除数据
int Listdelete(Sequlist* L, int i, Datatype* x) {
if (L->size <= 0) {
printf("顺序表为空\n");
return 0;
}
else if (i<0 || i>L->size) {
printf("参数i不合适\n");
return 0;
}
else {
int j;
*x = L->list[i];
for (j = i;j < L->size;j++) {
L->list[j] = L->list[j + 1];
}
L->size--;
printf("删除数据成功\n");
return 1;
}
}
//取数据
int Listget(Sequlist* L, int i, Datatype* x) {
if (i<0 || i>=L->size) {
printf("参数i不合适\n");
return 0;
}
else if (L->size == 0) {
printf("顺序表为空\n");
return 0;
}
else {
*x = L->list[i];
return 1;
}
}
//输出顺序表
void Listoutput(Sequlist* L) {
int i;
for (i = 0;i < L->size;i++) {
printf("%-6d", L->list[i]);
}
}
int main() {
Sequlist List;
Listintiate(&List);
int n;
printf("请输入要出入的元素个数n:");
scanf("%d", &n);
//插入数据
int i;
for (i = 0;i < n;i++) {
//要输入的数据
Datatype x;
scanf("%d", &x);
Listinsert(&List, i, x);
}
printf("顺序中元素的个数为%d\n",Listlength(&List));
//数据输出
Listoutput(&List);
//数据删除
int postion;
printf("\n输入要删除的位置:");
scanf("%d", &postion);
getchar();
//用来接收删掉的数据
Datatype a;
Listdelete(&List, postion, &a);
printf("删除的元素为%d\n", a);
//取数据
printf("要获取的位置的下标:");
scanf("%d",&postion);
int flag=Listget(&List, postion, &a);
if(flag==1){
printf("下标为%d的元素为:%d",postion,a);
}
return 0;
}