顺序表的实现
这里主要以动态分配内存为案例来实现一个顺序表。
1、结构体定义
typedef int SLDataType;
typedef struct SeqList
{
SLDataType * a; // 指针
int size; // 顺序里面元素个数
int capacity; // 顺序表容量
}SeqList;
2、具体实现
初始化
void SeqListInit(SeqList* pq)
{
assert(pq);
pq->a = NULL;//初始化指针,该指针是malloc开辟连续内存的首地址
pq->size = pq->capacity = 0;
}
销毁
void SeqListDestroy(SeqList* pq)
{
assert(pq);
free(pq->a);
pq->a = NULL;
pq->capacity = pq->size = 0;
}
顺序表的打印
void SeqListPrint(SeqList* pq)
{
assert(pq);
for (int i = 0; i < pq->size; i++)
{
printf("%d ", pq->a[i]);
}
printf("\n");
}
动态数组扩容
void CapacityCheck(SeqList* pq)
{
assert(pq);
// 判断是否存满
if (pq->size == pq->capacity)
{
// 还需要判断一下是否是空的,因为后面是要在capacity的基础上扩容(capacity的2倍,如果capacity=0,那么会出问题)
int newcapacity = pq->capacity = 0 ? 4 : pq->capacity * 2;
SLDataType* tmp = (SLDataType*)realloc(pq->a, sizeof(SLDataType) * newcapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
else
{
// 有可能当前内存不够扩容,因此在另一块内存上开辟,所以起始地址会变换
pq->a = tmp;
pq->capacity = newcapacity;
}
}
}
尾插插入元素
void SeqListPushBack(SeqList* pq, SLDataType x)
{
assert(pq);
// 首先要检查顺序表容量是否充足,如果容量不充足需要扩容
CapacityCheck(pq);
// 尾插
pq->a[pq->size] = x;
pq->size++;
}
头部插入元素
void SeqListPushFront(SeqList* pq, SLDataType x)
{
assert(pq);
// 首先检查顺序表容量是否充足,如果容量不充足需要扩容
CapacityCheck(pq);
// 头插
for (int i = pq->size - 1; i >= 0; i--)
{
pq->a[i + 1] = pq->a[i];
}
pq->a[0] = x;
pq->size++;
}
头插的时候需要将顺序表中的元素,从最后一个开始往后挪动,把第一个位置空下来然后将元素插入进去。
尾删和头删
void SeqListPopBack(SeqList* pq)
{
assert(pq);
assert(pq->size > 0); // 顺序表中没有数据就不能尾删
pq->size--;
}
void SeqListPopFront(SeqList* pq)
{
assert(pq);
assert(pq->size > 0); // 顺序表中没有数据就不能头删
for (int i = 0; i < pq->size - 1; i++)
{
pq->a[i] = pq->a[i + 1];
}
pq->size--;
}
尾删的时候,我们只需要将最后一个元素的位置当作空就行;头删的时候,需要将第二个元素到最后一个元素往前挪动。
按值查找
int SeqListFind(SeqList* pq, SLDataType x)
{
assert(pq);
for (int i = 0; i < pq->size; i++)
{
if (pq->a[i] == x)
return i;
}
return -1;
}
在任意位置插入元素
void SeqListInsert(SeqList* pq, int pos, SLDataType x)
{
assert(pq);
assert(pos >= 0 && pos <= pq->size); // 需要确保要插入的位置在[0,pq->size]范围内,pq->size位置插入相当于尾插
for (int i = pq->size - 1; i >= pos; i--)
{
pq->a[i + 1] = pq->a[i];
}
pq->a[pos] = x;
pq->size++;
}
删除任意位置的元素
void SeqListErase(SeqList* pq, int pos)
{
assert(pq);
assert(pos >= 0 && pos <= pq->size - 1); // 需要保证要删除的元素位置是已有元素的位置
for (int i = pos; i < pq->size - 1; i++)
{
pq->a[i] = pq->a[i + 1];
}
pq->size--;
}
修改元素
void SeqListModify(SeqList* pq, int pos, SLDataType x)
{
assert(pq);
assert(pos >= 0 && pos <= pq->size - 1); // 需要保证要修改的元素位置是已有元素的位置
pq->a[pos] = x;
}