前言
线性表的顺序存储结构,即顺序表,是指利用一块连续的地址空间依次存放线性表中的元素。这种数据结构被称作顺序映像,简称顺序表。其显著特征在于逻辑上相邻的元素,在物理存储上也是连续的。基于这个特性,顺序表允许通过起始地址加上偏移量的方式,即索引,实现对任意元素的随机访问,这使得顺序表成为一种随机访问存储结构。
顺序表的类型
typedef struct Seqlist
{
int arr[];
int size;//数据个数
int capacity;//空间容量
}sl;
1.这就是顺序表的第一种类型:静态顺序表。它是使用定长数组的顺序表,对于定长数组来说,数组给大了浪费内存,数组给小了空间不够用,所以一般来说不使用静态顺序表。
typedef struct seqlist
{
int* a;
int size;//数据个数
int capacity;//容量
}sl;
2.顺序表的第二种类型:动态顺序表。它是使用动态增容的顺序表,它的内存会随着数据的增加而增加,所以不会像静态顺序表那样出现内存问题。
顺序表的主要操作
那么我们对顺序表的实现需完成以下操作 ,才能完成顺序表的实现:
1.顺序表的初始化。
2.顺序表的销毁。
3.顺序表的数据插入。
4.顺序表的查找。
5.顺序表的删除。
顺序表的初始化:
void initialize(sl* pa)//初始化
{
pa->a = NULL;
pa->capacity = pa->size = 0;
}
顺序表的初始化就是构造一个空的顺序表,方便之后使用。
内存判断
这里我们写的是动态顺序表那么我们就要对顺序表进行分配空间,如下:
void MJ(sq* pa)//内存判断
{
if (pa->capacity == pa->size)//如果数据个数=内存容量,证明空间不够
{
int variable = pa->capacity == 0 ? 4 : 2 * pa->capacity;
int* tmp = (int*)realloc(pa->a, variable * sizeof(lala));
if (tmp == NULL)
{
printf("错了");
exit(1);
}
pa->a = tmp;
pa->capacity = variable;
}
}
这里我们运用三元操作符来判断内存容量是否为0,因为顺序表刚初始化完内存容量为0,随后创建一个临时变量并给予其内存空间(此内存空间用realloc创建,使其位于顺序表指针之后),创建临时变量是为了避免realloc操作失败返回NULL,如果创建成功,使pa->tmp更新顺序表结构体中的数组指针,让它指向新的内存地址。
顺序表的插入及删除
尾插法和尾删法,头插法和头删法
void SLPushBack(sl* pa, int x)//尾插法
{
assert(pa);
MJ(pa);
pa->a[pa->size++] = x;
}
void SLPopBack(sl* pa)//尾插法删除
{
assert(pa);
assert(pa->size);
--pa->size;
}
void SLPushFront(sl* pa, int x)//头插法
{
assert(pa);
MJ(pa);
int i;
for (i = pa->size; i > 0; i--)
{
pa->a[i] = pa->a[i - 1];
}
pa->a[0] = x;
pa->size++;
}
void SLPopFront(sl* pa)//头插法删除
{
assert(pa);
assert(pa->size);
for (int i = 0; i < pa->size - 1; i++)
{
pa->a[i] = pa->a[i + 1];
}
pa->size--;
}
尾插法和尾删法都是从尾部进行插入和删除,头插法和头删法相反,在进行尾插法和头插法是都要进行断言指针是否为空,且要进行内存判断,避免内存不够用的情况。在进行尾删法和头删法是需断言指针和数据个数,避免对错误内容进行操作。
顺序表的查找
int find(sq* pa, int x)//查找
{
assert(pa);
for (int i = 0; i < pa->size; i++)
{
if (pa->a[i] == x)
{
return i;
}
}
return -1;
}
x为查找的内容,如果查找成功,则会返回第几个a找到的x,如果找不到返回-1。
顺序表在指定位置的查找和删除
void yyy(sl* pa, int pos, int x)//在指定位置插入数据
{
assert(pa);
assert(pos >= 0 && pos <= pa->size);
MJ(pa);
for (int i = pa->size; i >= pos; i--)
{
pa->a[i] = pa->a[i - 1];
}
pa->size++;
pa->a[pos] = x;
}
void aaa(sl* pa, int pos)//删除指定位置数据
{
assert(pa);
assert(pos >= 0 && pos < pa->size);
MJ(pa);
for (int i = pos; i < pa->size-1; i++)
{
pa->a[i] = pa->a[i + 1];
}
pa->size--;
}
顺序表在指定位置的插入和删除必须判断查找或删除(pos)位置是否合法,随后在进行查找和删除。
顺序表的销毁
void destory(sl* pa)//顺序表的销毁
{
if (pa->a)
{
free(pa->a);
}
pa->a = NULL;
pa->capacity = pa->size = 0;
}
在操作完成后需要销毁顺序表,将顺序表的内存还给系统。
完整代码如下
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int lala;
typedef struct seqlist
{
lala* a;
int size;//数据个数
int capacity;//容量
}sq;
void initialize(sq* pa)//初始化
{
pa->a = NULL;
pa->capacity = pa->size = 0;
}
void destory(sq* pa)//顺序表的销毁
{
if (pa->a)
{
free(pa->a);
}
pa->a = NULL;
pa->capacity = pa->size = 0;
}
void MJ(sq* pa)//内存判断
{
if (pa->capacity == pa->size)
{
int variable = pa->capacity == 0 ? 4 : 2 * pa->capacity;
lala* tmp = (lala*)realloc(pa->a, variable * sizeof(lala));
if (tmp == NULL)
{
printf("错了");
exit(1);
}
pa->a = tmp;
pa->capacity = variable;
}
}
void SLPushBack(sq* pa, lala x)//尾插法
{
assert(pa);
MJ(pa);
pa->a[pa->size++] = x;
}
void SLPushFront(sq* pa, lala x)//头插法
{
assert(pa);
MJ(pa);
int i;
for (i = pa->size; i > 0; i--)
{
pa->a[i] = pa->a[i - 1];
}
pa->a[0] = x;
pa->size++;
}
void SLPrint(sq s)//打印内容
{
for (int i = 0; i < s.size; i++)
{
printf("%d ", s.a[i]);
}
printf("\n");
}
void SLPopBack(sq* pa)//尾插法删除
{
assert(pa);
assert(pa->size);
--pa->size;
}
void SLPopFront(sq* pa)//头插法删除
{
assert(pa);
assert(pa->size);
for (int i = 0; i < pa->size - 1; i++)
{
pa->a[i] = pa->a[i + 1]; //arr[size-2] = arr[size-1]
}
pa->size--;
}
void yyy(sq* pa, int pos, lala x)//在指定位置插入数据
{
assert(pa);
assert(pos >= 0 && pos <= pa->size);
MJ(pa);
for (int i = pa->size; i >= pos; i--)
{
pa->a[i] = pa->a[i - 1];
}
pa->size++;
pa->a[pos] = x;
}
void aaa(sq* pa, int pos)//删除指定位置数据
{
assert(pa);
assert(pos >= 0 && pos < pa->size);
MJ(pa);
for (int i = pos; i < pa->size-1; i++)
{
pa->a[i] = pa->a[i + 1];
}
pa->size--;
}
int find(sq* pa, lala x)//查找
{
assert(pa);
for (int i = 0; i < pa->size; i++)
{
if (pa->a[i] == x)
{
return i;
}
}
return -1;
}
请注意,以上代码仅供学习和参考之用。对顺序表相关操作的理解和实现细节,有助于深入掌握数据结构的基本概念。如有任何疑问或建议,欢迎交流。