一.顺序表
顺序表(Sequential List)是一种线性表,其元素在内存中连续存放,可通过索引直接访问。线性表在逻辑结构上是线性结构,也就是说是连续的一条直线,但是在物理结构上并不一定是连续的。线性表在物理结构上存储时,通常是以数组和链式结构的形式存储的。
顺序表是一种基础的数据结构,主要有以下几种类型:
-
静态顺序表:
- 使用静态数组实现,即数组的大小在编译时就已经确定,不可更改。
- 优点是实现简单,元素访问速度快。
- 缺点是空间固定,不易扩展。
-
动态顺序表:
- 使用动态数组实现,即通过指针和动态内存分配(如C语言中的malloc和realloc)来管理数组。
- 优点是可根据需要动态调整数组的大小,具有较好的灵活性。
- 缺点是当数组扩容时,可能需要进行数据的复制,有一定的性能开销。
以下是这两种顺序表在C语言中的简单定义:
静态顺序表:
#define MAX_SIZE 100 // 定义最大容量
typedef struct
{
int data[MAX_SIZE]; // 静态数组
int length; // 顺序表当前长度
} StaticSeqList;
动态顺序表:
typedef struct
{
int *data; // 动态数组指针
int length; // 顺序表当前长度
int capacity; // 顺序表当前容量
} DynamicSeqList;
除了这两种基本的顺序表外,还有一些其他的顺序表, 比如说单顺序表、多重顺序表、稀疏顺序表以及压缩顺序表,感兴趣的可以去了解一下。
顺序表具有以下特点:
存储空间连续:顺序表的元素存储在一块连续的内存空间中。
随机访问:顺序表支持通过索引随机访问元素,访问时间为常数级别。
动态扩容:顺序表在元素数量达到容量上限时,可以进行动态扩容。
二.顺序表的实现
在C语言中,顺序表通常通过结构体和数组来实现。以下是一个简单的顺序表实现:
SeqList.h
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* a;
int size;
int capacity;
}SeqList;
// 对数据的管理:增删查改
//顺序表初始化
void SeqListInit(SeqList* ps);
//顺序表的销毁
void SeqListDestroy(SeqList* ps);
//顺序表的打印
void SeqListPrint(SeqList* ps);
//尾插
void SeqListPushBack(SeqList* ps, SLDataType x);
//头插
void SeqListPushFront(SeqList* ps, SLDataType x);
//尾删
void SeqListPopFront(SeqList* ps);
//头删
void SeqListPopBack(SeqList* ps);
// 顺序表查找
int SeqListFind(SeqList* ps, SLDataType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);
SeqList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
//初始化
void SeqListInit(SeqList* ps)
{
ps->a = NULL;
ps->size = ps->capacity = 0;
}
//销毁
void SeqListDestroy(SeqList* ps)
{
if (ps->a)//不为NULL先释放,然后置为NULL
{
free(ps->a);
}
ps->a = NULL;
ps->size = ps->capacity = 0;
}
顺序表的打印
void SeqListPrint(SeqList* ps)
{
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
//检查空间是否充足
void SLcheckcapacity(SeqList* ps)
{
if (ps->size == ps->capacity)
{
int newcapacity = ps->capacity = 0 ? 4:2*ps->capacity;
SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
if (tmp == NULL)
{
perror("realloc fail!");//扩容失败
exit(1);
}
ps->a = tmp;
ps->capacity = newcapacity;
}
}
//尾插
void SeqListPushBack(SeqList* ps, SLDataType x)
{
assert(ps);//是否为NULL
SLcheckcapacity(ps);
ps->a[ps->size] = x;
ps->size++;
}
//头插
void SeqListPushFront(SeqList* ps, SLDataType x)
{
assert(ps);//是否为NULL
SLcheckcapacity(ps);
for (int i = ps->size; i > 0; i--)
{
ps->a[i] = ps->a[i - 1];
}
ps->a[0] = x;
ps->size++;//size要+1
}
//尾删
void SeqListPopFront(SeqList* ps)
{
assert(ps);//是否为NULL
assert(ps->size);
ps->size--;
}
//头删
void SeqListPopBack(SeqList* ps)
{
assert(ps->a);
assert(ps->size);
for (int i = 0; i < ps->size-1; i++)//ps->size-1!!!
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}
// 顺序表查找
int SeqListFind(SeqList* ps, SLDataType x)
{
for (int i = 0; i < ps->size; i++)
{
if (ps->a[i] == x)
return i;
}
return -1;//循坏结束后没有找到返回-1
}
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDataType x)
{
assert(ps->a);
assert(pos >= 0 && pos <= ps->size);
SLcheckcapacity(ps);
for (int i = ps->size; i > pos; i--)
{
ps->a[i] = ps->a[i - 1];
}
ps->a[pos] = x;
ps->size++;
}
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
for (int i = pos; i < ps->size-1; i++)
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include "SeqList.h"
int main()
{
SeqList s;
SeqListInit(&s);
s.a = (int*)malloc(sizeof(int)*5);
s.size = 5;
s.capacity = 5;
//填充顺序表!!!
int data[] = { 1,2,3,4,5 };
for (int i = 0; i < s.size; i++)
{
s.a[i] = data[i];
}
SeqListPrint(&s);
//尾插
//SeqListPushBack(&s, 11);
//SeqListPrint(&s);
//头插
//SeqListPushFront(&s, 11);
//SeqListPrint(&s);
//尾删
//SeqListPopFront(&s);
//SeqListPrint(&s);
// 头删
//SeqListPopBack(&s);
//SeqListPrint(&s);
//查找
//int ret=SeqListFind(&s, 5);
//if (ret == -1)
// printf("没有找到\n");
//else
// printf("找到了,下标为%d\n", ret);
//顺序表在pos位置插入x
//SeqListInsert(&s, 3, 11);
//SeqListPrint(&s);
//顺序表删除pos位置的值
SeqListErase(&s, 3);
SeqListPrint(&s);
//销毁
SeqListDestroy(&s);
return 0;
}
三、顺序表问题
1.中间/头部的插入和删除,时间复杂度是O(N)。
2.增容需要申请新的空间,拷贝数据,释放旧空间,会产生不小的消耗。
3.增容一般是呈2倍增长,肯定会有一定的空间浪费。例如当前容量是100,满了以后增容到200,继续插入10个数据,后面90个数据空间就浪费了。
宝子们,点赞收藏+关注,进阶大佬不迷路~
标签:ps,顺序,路过,SeqList,错过,int,void,震惊,size From: https://blog.csdn.net/2401_83948390/article/details/140353633