赞
踩
#pragma once #include <stdio.h> #include <stdlib.h> #include <assert.h> typedef int SLDataType; //动态顺序表 typedef struct SeqList { SLDataType* a;//数组指针,指向动态开辟内存的数组 int size;//数组存储数据的个数 int capacity;//数组实际存的数据最大容量 }SL;//重定义类型名 //接口函数 //打印顺序表 void SeqListPrint(SL* ps); //初始化 void SeqListInit(SL* ps); //清空 void SeqListDestory(SL* ps); //尾插 void SeqListPushBack(SL* ps, SLDataType x); //尾删 void SeqListPopBack(SL* ps); //头插 void SeqListPushFront(SL* ps, SLDataType x); //头删 void SeqListPopFront(SL* ps); //查找 int SeqListFind(SL* ps, SLDataType x); //指定下标位置插入 void SeqListInsert(SL* ps, int pos, SLDataType x); //删除指定下标的指定数据 void SeqListErase(SL* ps, int pos, SLDataType x);
typedef int SLDataType;
的意义是当需要改变顺序表的数据类型时直接改变此int
即可。
因为要实际存入数据到顺序表中,所以函数传值传其结构体指针。
初始化表的成员变量即可:将顺序表的数组指针置空,size
和capacity
置零
void SeqListInit(SL* ps)
{
asssert(ps != NULL);//防止传入的指针为空
ps->a = NULL;//初始数组置空
ps->size = ps->capacity = 0;//初始数据个数和容量置空
}
以元素个数size
为界,遍历打印每一个元素。
void SeqListPrint(SL* ps)
{
asssert(ps != NULL);
for (int i = 0; i < ps->size; i++)//打印当前的数据个数位
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
释放数组指针并置空,size,capacity置零。
void SeqListDestory(SL* ps)
{
free(ps->a);//释放动态开辟的空间
ps->a = NULL;//数组置空
ps->size = ps->capacity = 0;//数据个数和容量重新置为零
}
void SeqListCheckCapacity(SL* ps) { //如果没有空间或空间不足,扩容 if (ps->size == ps->capacity) { int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));//重设大小 if (tmp == NULL)//判断realloc是否成功 { perror(SeqListPushBack);//不成功报错 exit(-1);//退出程序 } ps->a = tmp;//将增容后的空间给ps->a ps->capacity = newcapacity;//将容量扩大 } }
这里使用三目运算符
ps->capacity == 0 ? 4 : ps->capacity * 2;
即如果初始容量为零则设为4否则变成二倍;
realloc
在申请空间时,如果数组本身没有空间那么realloc
的作用和malloc一
样
如果realloc
开辟空间失败会返回空,所以判断tmp是否为空
ps->size++
即可void SeqListPushBack(SL* ps, SLDataType x)
{
SeqListCheckCapacity(ps);//先检查是否需要增容
//存储
ps->a[ps->size] = x;//将需要插入的数据x放入
ps->size++;//size++,
}
ps->size--
即可void SeqListPopBack(SL* ps)
{
//ps->a[ps->size - 1] = 0; <-没必要,该位置本来就可能为零,size--后该位置直接被删去
//if (ps->size > 0)//防止越界
//{
// ps->size--;
//}
assert(ps->size > 0);
ps->size--;
}
这里
if(ps->size>0)
也可以,这样当我们删的次数超过顺序表元素后,ps->size
将不再减小,即最多减到零;而assert(ps->size > 0)会在我们删除过多后直接assert
报错。
void SeqListPushFront(SL* ps, SLDataType x)
{
//先检查是否需要扩容
SeqListCheckCapacity(ps);
int end = ps->size - 1;//end为顺序表最后一个元素的下标位置
while (end >= 0)
{
ps->a[end + 1] = ps->a[end];//数据后移
end--;
}
ps->a[0] = x;//把首位赋值为数据x
ps->size++;//数据个数增加
}
void SeqListPopFront(SL* ps)
{
assert(ps->size > 0);//断言数据个数大于0
int begin = 1;//从第二位设置begin
//数据前移
while (begin < ps->size)//begin小于数据个数
{
ps->a[begin - 1] = ps->a[begin];//数据前移
++begin;
}
ps->size--;
}
int SeqListFind(SL* ps, SLDataType x)
{
for (int i = 0; i < ps->size; i++)
{
if (ps->a[i] == x)
{
return i;
}
}
return -1;
}
if
判断或assert
断言,我们都选用断言void SeqListInsert(SL* ps, int pos, SLDataType x) { /*if (pos > ps->size || pos < 0) { printf("pos Invalid\n"); return; }*/ assert(pos >= 0 && pos <= ps->size);//插入0-size的任意位置 SeqListCheckCapacity(ps);//判断是否扩容 int end = ps->size - 1; //后移 while (end >= pos) { ps->a[end + 1] = ps->a[end]; end--; } ps->a[pos] = x; ps->size++; }
当此代码写完后,我们可以修改尾插和头插的内容
//尾插
void SeqListPushBack(SL* ps, SLDataType x)
{
SeqListInsert(ps, ps->size, x);//从size下标插入
}
//头插
void SeqListPushFront(SL* ps, SLDataType x)
{
SeqListInsert(ps, 0, x);//从零下标插入
}
void SeqListErase(SL* ps, int pos)
{
//这里同样可以用if语句,我们直接使用assert
assert(pos >= 0 && pos < ps->size);
int begin = pos + 1;
while (begin < ps->size)
{
ps->a[begin - 1] = ps->a[begin];
begin++;
}
ps->size--;
}
和上一个相同,我们也可以由此改变尾删和头删。’
//尾删
void SeqListPopBack(SL* ps)
{
SeqListErase(ps, ps->size - 1);//删除size-1下标元素
}
//头删
void SeqListPopFront(SL* ps)
{
SeqListErase(ps, 0);//删除0下标元素
}
void SeqListModify(SL* ps, int pos, SLDataType x)
{
assert(ps->size > 0 && pos >= 0 && pos < ps->size);//确保pos的范围合法,顺序表有元素0
ps->a[pos] = x;//更改
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。