数据结构顺序表的动态实现,作为学习过程的记录
顺序表要求所存数据在逻辑上和物理上均是连续存放,因此顺序表采用数组形式存放数据,主要使用realloc函数来为顺序表动态分配存储空间。
编译器环境
visual studio 2022
项目结构
SqList.h
结构定义及接口函数
#pragma once
#include<stdio.h>
#include<stdlib.h>
//#define N 1000
//
静态顺序表
//typedef int SLDataType;
//
//typedef struct SqList
//{
// SLDataType data[N];
// int size; //表示数组中存储了多少个元素
//}SL;
//
//void SqListInit(SL* ps);
静态特点:如果满了就不让插入
N给小了不够用,N给大了浪费空间
//void SqListPushBack(SL* ps, SLDataType x);
//void SqListPopBack(SL* ps);
//void SqListPushFront(SL* ps, SLDataType x);
//void SqListPopFront(SL* ps);
//动态顺序表
typedef int SLDataType;
typedef struct SqList
{
SLDataType* data;
int size; //表示数组中存储了多少个元素
int capacity;//表示数组实际容量
}SL;
void SqListPrint(SL* ps);
void SqListInit(SL* ps);
void SqListDestroy(SL* ps);
void SqListCheckCapacity(SL* ps);
void SqListPushBack(SL* ps, SLDataType x);
void SqListPopBack(SL* ps);
void SqListPushFront(SL* ps, SLDataType x);
void SqListPopFront(SL* ps);
//查找某个值的下标,没有找到返回-1
int SqListFind(SL* ps, SLDataType x);
//在指定pos下标位置插入x
void SqListInsert(SL* ps, int pos, SLDataType x);
//删除在pos下标处的数据
void SqListErase(SL* ps, int pos);
SqList.c 接口函数的具体实现
#pragma once
#include "SqList.h"
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
void SqListPrint(SL* ps)
{
for (int i = 0; i < ps->size; ++i)
{
printf("%d ", ps->data[i]);
}
printf("\n");
}
void SqListInit(SL* ps)
{
ps->data = NULL;
ps->size = ps->capacity = 0;
}
void SqListDestroy(SL* ps)
{
free(ps->data); //free()只将指针指向的空间还给系统
ps->data = NULL;
ps->size = ps->capacity = 0;
}
void SqListCheckCapacity(SL* ps)
{
if (ps->size == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SLDataType* tmp = (SLDataType*)realloc(ps->data, newcapacity * sizeof(SLDataType));
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->data = tmp;
ps->capacity = newcapacity;
}
}
void SqListPushBack(SL* ps, SLDataType x)
{
//如果没有空间,或者空间不足,那么就扩容
SqListCheckCapacity(ps);
ps->data[ps->size] = x;
ps->size++;
}
void SqListPopBack(SL* ps)
{
//温柔方式
if (ps->size > 0)
{
ps->size--;
}
else
{
printf("SqList has already been null. Fail to destroy!\n");
}
或者采用以下方式
//assert(ps->size > 0); //断言,括号内条件为假时,直接终止程序运行并报错。
//ps->size--;
}
void SqListPushFront(SL* ps, SLDataType x)
{
SqListCheckCapacity(ps);
// 挪动数据
int end = ps->size - 1;
while (end >= 0)
{
ps->data[end + 1] = ps->data[end];
end--;
}
ps->data[0] = x;
ps->size++;
}
void SqListPopFront(SL* ps)
{
assert(ps->size > 0); // 有数据才删
int begin = 1;
while (begin < ps->size )
{
ps->data[begin-1] = ps->data[begin];
begin++;
}
ps->size--;
}
int SqListFind(SL* ps, SLDataType x)
{
int index = -1;
for (int i = 0; i < ps->size; i++)
{
if (ps->data[i] == x)
{
index = i;
break;
}
}
return index;
}
void SqListInsert(SL* ps, int pos, SLDataType x)
{
//不允许在已用数据区外插入数据
assert(pos <= ps->size && pos >= 0);
SqListCheckCapacity(ps);
int end = ps->size;
while (end > pos)
{
ps->data[end] = ps->data[end - 1];
end--;
}
ps->data[pos] = x;
ps->size++;
}
void SqListErase(SL* ps, int pos)
{
//只允许在有效数据区内操作
assert(pos >= 0 && pos < ps->size);
int begin = pos + 1;
while (begin < ps->size)
{
ps->data[begin - 1] = ps->data[begin];
begin++;
}
ps->size--;
}
Test.c 测试用例
#pragma once
#include "SqList.h"
#include<stdio.h>
#include<stdlib.h>
void TestSqList1()
{
SL sl;
SqListInit(&sl);
SqListPushBack(&sl, 1);
SqListPushBack(&sl, 2);
SqListPushBack(&sl, 3);
SqListPushBack(&sl, 4);
SqListPushBack(&sl, 5);
SqListPrint(&sl);
SqListPopBack(&sl);
SqListPopBack(&sl);
SqListPopBack(&sl);
SqListPopBack(&sl);
SqListPopBack(&sl);
SqListPopBack(&sl);
SqListPopBack(&sl);
SqListPopBack(&sl);
SqListPrint(&sl);
SqListPushBack(&sl, 1);
SqListPrint(&sl);
SqListDestroy(&sl);
}
void TestSqList2()
{
SL sl;
SqListInit(&sl);
SqListPushBack(&sl, 1);
SqListPushBack(&sl, 2);
SqListPushBack(&sl, 3);
SqListPushBack(&sl, 4);
SqListPushBack(&sl, 5);
SqListPrint(&sl);
SqListPushFront(&sl, 10);
SqListPushFront(&sl, 20);
SqListPushFront(&sl, 30);
SqListPushFront(&sl, 40);
SqListPushFront(&sl, 50);
SqListPrint(&sl);
SqListPopFront(&sl);
SqListPopFront(&sl);
SqListPrint(&sl);
SqListDestroy(&sl);
}
void TestSqList3()
{
SL sl;
SqListInit(&sl);
SqListPushBack(&sl, 1);
SqListPushBack(&sl, 2);
SqListPushBack(&sl, 3);
SqListPushBack(&sl, 4);
SqListPushBack(&sl, 5);
SqListPrint(&sl);
printf("%d\n", SqListFind(&sl, 5));
printf("%d\n", SqListFind(&sl, 10));
SqListPrint(&sl);
SqListDestroy(&sl);
}
void TestSqList4()
{
SL sl;
SqListInit(&sl);
SqListPushBack(&sl, 1);
SqListPushBack(&sl, 2);
SqListPushBack(&sl, 3);
SqListPushBack(&sl, 4);
SqListPrint(&sl);
SqListInsert(&sl, 1, 10);
SqListInsert(&sl, 5, 10);
SqListPrint(&sl);
SqListErase(&sl, 0);
SqListPrint(&sl);
SqListErase(&sl, 4);
SqListPrint(&sl);
SqListErase(&sl, 2);
SqListPrint(&sl);
SqListDestroy(&sl);
}
int main() {
//TestSqList1();
//TestSqList2();
//TestSqList3();
TestSqList4();
return 0;
}