1、可扩容顺序表
结构设计
#define INIT_SIZE 100 //设置每次扩展的容量
//顺序表结构内容
typedefintELEM_TYPE;//设置顺序表中所存储的内容
//设置顺序表结构的内容
typedefstructSqlist
{
ELEM_TYPE*elem;//设置顺序表的头指针,指向使用malloc所创建的内存地址
intlength;//保存此时顺序表中所存储的内容
intlist_size;//此时顺序表的长度
}Sqlist,*PSqlist;
初始化
数据插入方式,有三种(头插、尾插、按位置插)
//顺序表初始化
voidInit_Sqlist(PSqlistsq)
{
//指针判空
assert(sq!=NULL);
//使用elem接受malloc所创建的内存
sq->elem= (ELEM_TYPE*)malloc(INIT_SIZE*sizeof(ELEM_TYPE));
assert(sq->elem!=NULL);
//有效长度设置
sq->length=0;
//顺序表容量设置
sq->list_size=INIT_SIZE;
}
头插
//头插
boolInsert_head(PSqlistsq, ELEM_TYPEval)
{
//指针判空
assert(sq!=NULL);
//判满操作
if (IsFull(sq))//为真则进行扩容操作
{
Inc(sq);
}
//头插,则需要将顺序表所存储的内容向后移动
for (inti=sq->length-1; i>=0; i--)//因此出length并不代表顺序的所有长度,因此进行i+1操作不会出现错误
{
sq->elem[i+1] =sq->elem[i];
}
//进行头插
sq->elem[0] =val;
//有效长度加一
sq->length++;
returntrue;
}
尾插
//尾插
boolInsert_tail(PSqlistsq, ELEM_TYPEval)
{
assert(sq!=NULL);
if (IsFull(sq))
{
Inc(sq);
}
sq->elem[sq->length] =val;
sq->length++;
returntrue;
}
按位置插入
//按位置插入
boolInsert_pos(PSqlistsq, intpos, ELEM_TYPEval)//结构体指针sq,插入位置pos(此处的pos是值得从0开始算起的位置),插入指val
{
assert(sq!=NULL);
assert(pos>=0&&pos<=sq->length);//此处<=为sq->length,是因为当超过此长度时,插入时会出现空挡,不连续
if (IsFull(sq))
{
Inc(sq);
}
for (inti=sq->length-1; i>=pos; i--)//将插入位置之后的内容
{
sq->elem[i+1] =sq->elem[i];
}
sq->elem[pos] =val;
sq->length++;
returntrue;
}
数据删除方式,有四种(头删、尾删、按位置删、按值删)
头删
//头删
boolDel_head(PSqlistsq)
{
assert(sq!=NULL);
if (IsEmpty(sq))
{
returnfalse;
}
for (inti=1; i<sq->length; i++)
{
sq->elem[i-1] =sq->elem[i];
}
sq->length--;
returntrue;
}
尾删
//尾删
boolDel_tail(PSqlistsq)
{
assert(sq!=NULL);
if (IsEmpty(sq))
{
returnfalse;
}
sq->length--;//此处不用对尾部数据进行操作,只要对有效长度进行操作,即可达到数据删除的效果
returntrue;
}
按位置删
//按位置删
boolDel_pos(PSqlistsq, intpos)
{
assert(sq!=NULL);
assert(pos>=0&&pos<=sq->length);//所删除位置在有效的范围内
if (IsEmpty(sq))
{
returnfalse;
}
for (inti=pos+1; i<=sq->length; i++)
{
sq->elem[i-1] =sq->elem[i];
}
sq->length--;
returntrue;
}
按值删
//按值删
bool Del_val(PSqlist sq, ELEM_TYPE val)
{
assert(sq != NULL);
if (IsEmpty(sq))
{
return false;
}
int pos = Search(sq, val);
if (pos == -1)
{
return false;
}
return Del_pos(sq, pos);
}
功能设计
按值查找
//按值查找
bool Search(PSqlist sq, ELEM_TYPE val)
{
assert(sq != NULL);
for (int i = 0; i < sq->length; i++)
{
if (sq->elem[i] == val)
{
return i;
}
else
{
return false;
}
}
}
判空和判满操作
//判空
bool IsEmpty(PSqlist sq)
{
assert(sq != NULL);
return sq->length == 0;
}
//判满
bool IsFull(PSqlist sq)
{
assert(sq != NULL);
return sq->length == sq->list_size;
}
扩容操作
//扩容操作
bool Inc(PSqlist sq)
{
assert(sq != NULL);
sq->elem = (ELEM_TYPE*)realloc(sq->elem, sq->list_size * sizeof(ELEM_TYPE) * 2);//realloc(原指针,扩容大小)
assert(sq->elem != NULL);
sq->list_size *= 2;//此处的扩容使递增的,如第一次是100,第二次则是200,第三次是400,第四次是800···第n次是100(2^n - 1)
return true;
}
清空销毁操作
//清空
void Clear(PSqlist sq)
{
assert(sq != NULL);
sq->length = 0;//清空即是将有效值设置为0
}
//销毁,释放内存
void Des(PSqlist sq)
{
assert(sq != NULL);
sq->length = sq->list_size = 0;
free(sq->elem);
}
打印
//打印
void Print(PSqlist sq)
{
assert(sq != NULL);
for (int i = 0; i < sq->length; i++)
{
printf("第%d个 -> %d\n", i, sq->elem[i]);
}
}
可扩容顺序表的优缺点
优点:
1.支持随机访问
2.尾插和尾删效率高
缺点:
1.头插头删,中间插入,中间删除,效率低
2.扩容代价高:申请,拷贝,释放
使用场景
适用于需要大量随机访问数据元素,并插入和删除操作大都是在尾部进行的。