C语言实现顺序表的基础操作
所谓数据结构顺序表和链表的基本操作,实际上就是实现对一个顺序表(链表)的增删查改及其其他接口的实现。
顺序表线性结构存储示意图
C语言顺序表的基本操作
定义顺序表结构体
由长度和数据数组组成:
typedef int SeqDataType;//类型
typedef struct SeqList
{
SeqDataType* a;
int size; //有效数据的个数
int capacity; //容量
}SeqList,SEQ;
结构体初始化
//结构体初始化只能在定义的地方
void SeqListInit(SeqList* pq)//创
{
assert(pq);//养成好习惯,断言
pq->a = NULL;
pq->size = pq->capacity = 0;
}
接口的列举(SepList.h)
#pragma once
#include <stdio.h>
#include<assert.h>
#include<stdlib.h>
//静态的顺序表
//#define N 100
//struct SeqList
//{
// int a[N];
// int size;
//};
typedef int SeqDataType;//类型
typedef struct SeqList
{
SeqDataType* a;
int size; //有效数据的个数
int capacity; //容量
}SeqList,SEQ;
//数据结构:内存中管理数据的结构增删查改的接口
//一般都包含
void SeqListInit(SeqList* pq);//初始化
void SeqListDestory(SeqList* pq);//销毁
void SeqListPrint(SeqList* pq);//打印
//四种最常用
void SeqListPushBack(SeqList* pq, SeqDataType x);//头插
void SeqListPushFront(SeqList* pq, SeqDataType x);//尾插
void SeqListPopBack(SeqList* pq);//尾删
void SeqListPopFront(SeqList* pq);//头删
int SeqListFind(SeqList* pq, SeqDataType x);//查找
void SeqListInsert(SeqList* pq, int pos, SeqDataType x);//中间某位置插入
void SeqListErase(SeqList* pq, int pos);//删除某个位置
void SeqListModify(SeqList* pq, int pos, SeqDataType x);//修改
除了最基本的增删查改外,还增加了打印和销毁等功能。
接口的实现(SepList.c)
1、扩容接口:
void SeqCheckCapacity(SeqList* pq)//扩容接口
{
if (pq->size == pq->capacity)
{
int newcapacity = pq->capacity == 0 ? 4 : pq->capacity * 2;
SeqDataType* newA = realloc(pq->a, sizeof(SeqDataType)*newcapacity);
if (newA == NULL)
{
printf("relloc fail\n");
exit(-1);
}
pq->a = newA;
pq->capacity = newcapacity;
}
}
2、插入操作:分为头插、尾插及在中间i位置i插入,其中头插和尾插要注意扩容接口
void SeqListPushBack(SeqList* pq, SeqDataType x)//尾插
{
assert(pq);
SeqCheckCapacity(pq);
//满了,需要增容
pq->a[pq->size] = x;
pq->size++;
}
void SeqListPushFront(SeqList* pq, SeqDataType x)//头插
{
assert(pq);
SeqCheckCapacity(pq);
int end = pq->size - 1;
while (end >= 0)
{
pq->a[end + 1] = pq->a[end];
end--;
}
pq->a[0] = x;
pq->size++;
}
在数据表的第i个位置插入元素,在顺序表的第i个位置插入元素e,首先将顺序表第i个位置的元素依次向后移动一个位置,然后将元素e插入第i个位置,移动元素要从后往前移动元素,即:先移动最后一个元素,在移动倒数第二个元素,依次类推;插入元素之前要判断插入的位置是否合法,顺序表是否已满,在插入元素之后要将表长L->length++;且在i位置插入,i可以是头或尾,所以也可以用此接口代替
void SeqListInsert(SeqList* pq, int pos, SeqDataType x)//中间某位置插入
{
assert(pq);
assert(pq >= 0 && pos <= pq->size);
SeqCheckCapacity(pq);
int end = pq->size - 1;
while (end >= pos)
{
pq->a[end + 1] = pq->a[end];
end--;
}
pq->a[pos] = x;
pq->size++;
}
3、删除操作:与插入一样,删除同样分为头删尾删及某一位置的删除
头删,尾删:
void SeqListPopBack(SeqList* pq)//尾删
{
assert(pq);
assert(pq->size > 0);
--pq->size;
}
void SeqListPopFront(SeqList* pq)//头删
{
assert(pq);
assert(pq->size > 0);
int begin = 0;
while (begin < pq->size - 1)
{
pq->a[begin] = pq->a[begin + 1];
begin++;
}
pq->size--;
//SeqListErase(pq, 0);
}
在某一位置删除:同样这里的某一位置包括头和尾,所以可以代替头删和尾删。
void SeqListErase(SeqList* pq, int pos)//删除某个位置
{
assert(pq);
assert(pos >= 0 && pos < pq->size);
int begin = pos;
while (begin <= pq->size - 1)
{
pq->a[begin] = pq->a[begin + 1];
begin++;
}
pq->size--;
}
4、查找:
int SeqListFind(SeqList* pq, SeqDataType x)//查找
{
assert(pq);
for (int i = 0; i < pq->size; i++)
{
if (pq->a[i] == x)
{
return i;
}
}
return -1;
}
5、打印接口:此接口也是调试过程中不可缺少的一项
void SeqListPrint(SeqList* pq)//打印
{
assert(pq);
for (int i = 0; i < pq->size; i++)
{
printf("%d ", pq->a[i]);
}
printf("\n");
}
6、修改:
void SeqListModify(SeqList* pq, int pos, SeqDataType x)//修改
{
assert(pq);
assert(pos >= 0 && pos < pq->size);
pq->a[pos] = x;
}
7、销毁顺序表:
void SeqListDestory(SeqList* pq)//销毁
{
assert(pq);
free(pq->a);
pq->a = NULL;
pq->size = pq->capacity = 0;
}
上面便是对顺序表基础接口的实现,调试并未展出,如果有想法可以自己操作