线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表一般又可分为静态顺序表和动态顺序表。
静态顺序表
#define N 100
typedef struct SeqList
{
int a[N];
int size;
}SeqList;
静态的顺序表,它的存储数据的空间是固定的,数组中存储的数据是连续存储的,但也因此存在着相应的问题:开辟的空间,如果开小了不够用,开大了又太浪费空间,所以并不实用,我们一般都采用动态的顺序表
动态顺序表
typedef int SeqDataType;
typedef struct SeqList
{
SeqDataType* a;//存储数据空间的指针
int size;//有效数据个数
int capacity;//容量
}seqList;
动态的顺序表,它存储数据的空间是可以动态增长的,可以更好的适应现实的使用。
动态顺序表的接口实现
1.void SeqListInit(seqList* s1 )
描述:对顺序表进行初始化,为 a 指针开辟4个 int 大小的空间,置 size为0,capacity为4。
实现:
void SeqListInit(seqList* s1 )
{
assert(s1);
s1->a = (SeqDataType*) malloc(sizeof(SeqDataType)*4);
memset(s1->a,0,sizeof(SeqDataType)*4);
if(s1->a == NULL){
printf("malloc fail\n");
exit(-1);
}
s1->size = 0;
s1->capacity = 4;
}
2. void SeqListDestroy(seqList* s1 )
描述:对申请的空间进行销毁,并将a指针置为NULL,size和capacity置为0。
实现:
void SeqListDestroy(seqList* s1 )
{
assert(s1);
free(s1->a);
s1->a = NULL;
s1->size = s1->capacity = 0;
}
3. void CheckCapacity(seqList* s1)
描述:对顺序表的空间进行检查,如果当size和capacity的值相等,则证明空间已满,并对齐进行增容,每次增容都在原来的基础上扩充2倍。
实现:
void CheckCapacity(seqList* s1)
{
//检查空间,不够了需要增容
if(s1->size == s1->capacity)
{
SeqDataType* tmp = (SeqDataType* )realloc(s1->a,sizeof(SeqDataType)*s1->capacity*2);
if(tmp == NULL){
printf("malloc fail\n");
}
s1->a = tmp;
s1->capacity *= 2;
}
}
4. void SeqListPushBack(seqList* s1,SeqDataType x)
描述:在顺序表中进行尾插操作
实现:
void SeqListPushBack(seqList* s1,SeqDataType x)
{
assert(s1);
//检查空间,不够了需要增容
CheckCapacity(s1);
s1->a[s1->size] = x;
++s1->size;
}
5. void SeqListPushFront(seqList* s1,SeqDataType x)
描述:对顺序表进行头插操作
实现:
void SeqListPushFront(seqList* s1,SeqDataType x)
{
assert(s1);
CheckCapacity(s1);
int end = s1->size-1;
while(end >= 0)
{
s1->a[end+1] = s1->a[end];
--end;
}
s1->a[0] = x;
s1->size++;
}
6. void SeqListPopFront(seqList* s1)
描述:对顺序表进行头删操作
实现:
void SeqListPopFront(seqList* s1)
{
assert(s1);
assert(s1->size > 0);
//挪动数据
int begin = 1;
while(begin < s1->size)
{
s1->a[begin-1] = s1->a[begin];
++begin;
}
s1->size--;
}
7. void SeqListPopBack(seqList* s1)
描述:对顺序表进行尾删操作
实现:
void SeqListPopBack(seqList* s1)
{
assert(s1);
assert(s1->size > 0);
s1->size--;
}
8.void SeqListPrint(seqList* s1)
描述:对顺序表进行打印
实现:
void SeqListPrint(seqList* s1)
{
int i = 0;
for(; i < s1->size; ++i)
{
printf("%d ",s1->a[i]);
}
printf("\n");
}
9.int SeqListFind(seqList* s,SeqDataType x)
描述:寻找顺序表中的 x,如果找到则返回对应下标,找不到返回 -1.
实现:
int SeqListFind(seqList* s,SeqDataType x)
{
for(int i = 0;i < s->size; ++i)
{
if(s->a[i] == x)
{
return i;
}
}
return -1;
}
10.void SeqListInsert(seqList* s1,int pos,SeqDataType x)
描述:在顺序表s1的pos位置插入数据
实现:
void SeqListInsert(seqList* s1,int pos,SeqDataType x)
{
assert(s1);
assert(pos>=0 && pos <= size);
CheckCapacity(s1);
int end = s1->size - 1;
//挪动数据
while(end>=pos)
{
s1->a[end+1] = s1->a[end];
--end;
}
s1->a[pos] = x;
s1->size++;
}
11.void SeqListErase(seqList* s1,int pos)
描述:对顺序表s1的pos位置进行删除
实现:
void SeqListErase(seqList* s1,int pos)
{
assert(s1);
assert(pos >= 0 && pos <= s1->size);
//挪动覆盖要删除位置的数据
for(int i = pos + 1;i < s1->size; i++)
{
s1->a[i-1] = s1->a[i];
}
s1->size--;
}