顺序表:
本质上就是结构体数组,数据在内存中 连续存放的:
顺序表结构
//动态顺序表
typedef int SLDataType;
typedef struct SqeList
{
SLDataType* a;
int size;//数据个数
int capacity;//容量
}SL;
顺序表接口
void SLInit(SL* ps);//初始化顺序表
void SLPrint(SL* ps);//打印顺序表
void SLPushFront(SL* ps,SLDataType x);//头插
void SLPushBack(SL* ps,SLDataType x);//尾插
void SLPopFront(SL* ps);//头删
void SLPopBack(SL* ps);//尾删
void SLDestory(SL* ps);//销毁
void SLInsert(SL* ps,int pos,SLDataType x);//选择插入
void SLErase(SL* ps,int pos);//选择删除
void SLFind(Sl* ps,int pos);//查找
void SLModify(SL* ps,int pos,SLDataType x);//修改数据
初始化顺序表
void SLInit(SL* ps)
{
assert(ps);
ps->a = NULL;
ps->size = ps->capacity = 0;
}
打印顺序表
void SLPrint(SL* ps)
{
assert(ps);
for(int i = 0; i < ps->size; ++i)
printf("%d ",ps->a[i]);
printf("\n");
}
头插
头插,当容量满的时候,我们要增容,才能插入。
并且头插之前,还需要挪动当前所有数据,这便会导致顺序表头插不方便。
void SLCheckCapacity(SL* ps)
{
if(ps->size==ps->capacity)
{
int newcapacity = capacity == 0 ? 4:capacity*2;
SLDdataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
assert(tmp);//断言是否realloc成功
}
ps->a = tmp;
ps->capacity = newCapacity;
}
void SLPushFront(SL* ps,SLDataType x)
{
assert(ps);
//扩容
SLCheckCapacity(ps);
//挪动数据
int end = ps->size - 1;
while (end >= 0)
{
ps->a[end + 1] = ps->a[end];
--end;
}
ps->a[0] = x;
ps->size++;
}
尾插
void SListPushBack(SL* ps, SLDdataType x)
{
assert(ps);
//扩容
SLCheckCapacity(ps);
ps->a[ps->size] = x;
ps->size++;
}
头删
头删时,要注意顺序表中要有数据,其次头删需要将除第一个数据后的所有数据向前挪动(从左开始挪动)。
void SLPopFront(SL* ps)
{
assert(ps);
assert(ps->size > 0);
int begin = 1;
//挪动数据
while (begin < ps->size)
{
ps->a[begin - 1] = ps->a[begin];
++begin;
}
ps->size--;
}
尾删
尾删只需将ps->size–即可
void SLPopBack(SL* ps) {
assert(ps);
assert(ps->size > 0);
ps->size--;
}
销毁
void SLDestory(SL* ps)
{
assert(ps);
free(ps->a);
ps->a=NULL;
ps->size=ps->capacity=0;
}
选择插入
此处也需要扩容和挪动数据,还需注意控制pos的位置不能越界。
void SLInsert(SL* ps, int pos, SLDataType x) {
assert(ps);
assert(pos >= 0 && pos <= ps->size);
SLCheckCapacity(ps);
int end = ps->size - 1;
while (end >= pos)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[pos] = x;
ps->size++;
}
//有了这个之后,我们要尾插头插都可以复用了
}
选择删除
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
int begin = pos;
while (begin < ps->size - 1)
{
ps->a[begin] = ps->a[begin + 1];
++begin;
}
ps->size--;
}
查找
int SLFind(SL* ps, SLDataType x)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
if (ps->a[i] == x) {
return i;//找到了
}
}
return -1;//找不到
}
修改数据
void SLModify(SL* ps, int pos, SLDdataType x)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
ps->a[pos] = x;
}
test.c
#include "SeqList.h"
void TestSeqList1()
{
SL s1;
SLInit(&s1);
SLPushBack(&s1, 1);
SLPushBack(&s1, 2);
SLPushBack(&s1, 3);
SLPushBack(&s1, 4);
SLPushBack(&s1, 5);
SLPrint(&s1);
SLPopBack(&s1);
SLPrint(&s1);
SLDestory(&s1);
}
void TestSeqList4()
{
SL s1;
SLInit(&s1);
SLPushBack(&s1, 1);
SLPushBack(&s1, 2);
SLPushBack(&s1, 3);
SLPushBack(&s1, 4);
SLPushBack(&s1, 5);
//SLPopFront(&s1);
//SLInsert(&s1, 2, 20);
SLErase(&s1,2);
SLErase(&s1, 0);
SLPrint(&s1);
}
int main()
{
TestSeqList4();
return 0;
}
SeqList.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLDateType;
typedef struct SeqList
{
SLDateType* a;
int size;
int capacity;
}SL;
//初始化顺序表
void SLInit(SL* ps);
//尾插
void SLPushBack(SL* ps, SLDateType x);
//头插
void SLPushFront(SL* ps, SLDateType x);
//打印
void SLPrint(SL* ps);
//尾删
void SLPopBack(SL* ps);
//销毁
void SLDestory(SL* ps);
//头删
void SLPopFront(SL* ps);
//查找
void SLFind(SL* ps, SLDateType x);
//选择插入
void SLInsert(SL* ps,int pos, SLDateType x);
//选择删除
void SLErase(SL* ps, int pos);