顺序表的概念:
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,在数组上完成数据的增删查改。
头文件:
内部包含一些库函数的头文件,顺序表的结构体,操作函数的声明
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int SLDateType;
#define Initcapacity 5//设置初始化时capacity的大小
typedef struct SeqList
{
SLDateType* a;
int size;//有效元素个数
int capacity;//空间大小
}SeqList;
// 对数据的管理:增删查改
void SeqListInit(SeqList* ps);//初始化顺序表
void SeqListDestroy(SeqList* ps);//销毁顺序表
void SeqListPrint(SeqList* ps);
void SeqListPushBack(SeqList* ps, SLDateType x);
void SeqListPushFront(SeqList* ps, SLDateType x);
void SeqListPopFront(SeqList* ps);
void SeqListPopBack(SeqList* ps);
void SeqcheckCapacity(SeqList* ps);
// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);
初始化顺序表
void SeqListInit(SeqList* ps)//接收结构体的地址
{
assert(ps);//断言,若ps为NULL空,则终止程序
int *p= (int*)malloc(sizeof(SLDateType) * Initcapacity);//使用malloc申请动态内存空间
assert(p);//这里不想用assert也能直接if判断若ps==NULL则显示错误并return返回。
ps->a = p;//把p赋给顺序表ps中的a
ps->capacity = Initcapacity;//空间大小初始化,注意这里实际空间大小应该是sizeof(SLDateType) * Initcapacity,也就是有Initcapacity个所设置类型的大小
ps->size = 0;//有效元素个数初始化为0个
}
这里解释一下断言的好处,使用断言在较大的程序中可以直接在输出框提示哪里错了,不设置断言时出现ps=NULL的情况,程序会走一段时间就没了,不好找到出错的地方,所以在这种ps绝对不能为空的情况下最好断言一下。
销毁顺序表
void SeqListDestroy(SeqList* ps)
{
assert(ps);
free(ps->a);//释放空间
ps->a = NULL;//将a置空
ps->capacity = ps->size = 0;
}
打印顺序表
void SeqListPrint(SeqList* ps)
{
assert(ps);
int i = 0;
for (i = 0; i < ps->size; i++)
{
printf("%d\t", ps->a[i]);
}
printf("\n");
}
判断顺序表是否需要扩容
这里用到了扩容的库函数realloc,如果需要扩容即扩容为当前空间大小的二倍。
void SeqcheckCapacity(SeqList* ps)
{
assert(ps);
if (ps->size == ps->capacity)
{
int *p= (int*)realloc(ps->a, sizeof(SLDateType) * ps->capacity * 2);
ps->capacity = ps->capacity * 2;
assert(p != NULL);
ps->a = p;
}
}
尾插(在数组尾部插入一个数据)
void SeqListPushBack(SeqList* ps, SLDateType x)
{
assert(ps);
SeqcheckCapacity(ps);
ps->a[ps->size++] = x;//后置++,在操作时size并未+1,赋值完成后才+1.
}
尾删(在数组尾部删除一个数据)
void SeqListPopBack(SeqList* ps)
{
assert(ps);
assert(ps->size > 0);//保证有效元素个数>0
ps->size--;//有效元素个数-1即可实现
}
头插
从最后一个数据开始依次把数据往后移一位,最后把首元素赋值即可
void SeqListPushFront(SeqList* ps, SLDateType x)
{
assert(ps);
SeqcheckCapacity(ps);
int i = ps->size - 1;
for (;i>=0;i--)
{
ps->a[i+1] = ps->a[i];
}
ps->a[0] = x;
ps->size++;
}
头删
void SeqListPopFront(SeqList* ps)
{
assert(ps);
assert(ps->size > 0);
SeqcheckCapacity(ps);
int i = 1;
for (i = 1; i < ps->size; i++)
{
ps->a[i-1] = ps->a[i];
}
ps->size--;
}
顺序表查找
int SeqListFind(SeqList* ps, SLDateType x)
{
assert(ps);
int i = 0;
for (i = 0; i < ps->size; i++)
{
if (x == ps->a[i])
{
printf("找到了,是第%d个元素\n", i+1);
return;
}
}
printf("没找到\n");
}
顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
SeqcheckCapacity(&ps);
int i = ps->size-1;
while (pos <= i)
{
ps->a[i + 1] = ps->a[i];
i--;
}
ps->a[pos] = x;
ps->size++;
}
顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
int i = pos+1;
while (i<ps->size)
{
ps->a[i-1] = ps->a[i];
i++;
}
ps->size--;
}