目录
1>>闲话
大家国庆玩的开心不?小编是在国庆恶补了c的知识,然后玩了两天,给大家一个方法:节假日先学习,学习的天数一定要大于玩的天数,不然会一直想玩,假设你先玩两天,再想学习,你会发现很难学进去,因为你的心思早已不在,所以,先学习巩固完知识在玩是比较好的,小编就学了四天,玩了两天半。好了废话不多说,接着上一篇顺序表的博客,完善一下顺序表剩下的内容。
2>>顺序表尾删
删除尾部的数据较为容易,只需要传结构体变量指针就好
因此它的声明比较简单如上图。
它功能的实现,不用想的那么复杂,例如:该怎么把尾部数据置为0或者空呢?等等,其实只需要将有效数据也就是size减减就好,因为后续增加数据把原来删除的给覆盖了。
这里怕有同学忘记了上篇博客,附上顺序表的三个元素;
3>>顺序表的头插和头删
3.1>>头插
头插和头删跟尾部差不多,先看代码,然后我一一解释:
声明如上,x表示要插入的数。
首先要想实现头插,就要先判断传进来的地址是不是空地址,用assert断言判断,后面的功能实现也包括assert,后面就不在解释,接着,需要判断还有没有剩余空间可以插入,就要进入函数nospace中:
当ps指向的size和capacity相同时,说明空间不够了,拿一个新的变量newcapacity来存储,防止错误数据覆盖,三目操作符如果是0,也就是刚刚初始化,那么就置为4,如果不是0,那么就将原来的大小乘2;再接着,给一个新的指针tmp类型是datetype*,使用realloc进行扩容,扩容的大小还需要乘上一个sizeof(datetype)因为如果整形的话那么就要增大4倍;再者,判断tmp是否为空指针,如果不是则执行,是则打印错误信息。最后将新的指针赋给arr,然后新的空间大小给capacity。
接着返回来,实现头插部分:
头插也就是在下标0处插入,那么整体数据就要向后移动,如下图
因此循环从size开始然后--并且大于0,当循环结束对0下标进行赋值插入即可,然后size(有效数据个数)别忘记加加!
3.2>>头删
这里就是把头部也就是0下标之后的数据都往前移动一位,然后将size--就好,代码思路和前面都差不多,这里就不赘述啦,有问题欢迎评论区点出来~
4>>指定位置插入和删除
若是上面都搞懂了,接下来就比较容易理解啦:
4.1>>指定位置插入
声明中,pos表示在哪个下标插入,x表示插入的数据
这里的assert还要加一行pos在有效范围内噢别忘记了
当pos等于0是就表示头插,当pos等于size时就表示尾插。
插入还是和之前一样,需要用nospace函数判断空间够不够,然后将pos以及pos后的整体数据往后移动,插入的数据赋值给pos位置的数据,size加加就结束啦!
4.2>>指定位置删除
这个也比较简单,不过注意size的有效范围和插入不一样哟!
然后将pos后的整体数据往前移动即可。
5>>查找
这里代码也和前面的大抵相同,就是注意返回类型从void变为了int,因为返回的是下标,这里都不过多赘述啦,大家看看代码。
6>>查找替换修改
这个其实是修改和查找的组合
解读:查找99,返回下标,将此下标对应的数也就是99,替换为88.
7>>销毁
在我们不断的进行增删查改后,那么就要对它进行销毁并重置,这里首先判断arr是不是一个有效的指针,是的话那么就释放,然后置为空指针,size和capacity置为0;
最后让我们来测试一下吧:
8>>三个文件代码
test.c
#include"seqlist.h"
void SLtest()
{
SL sl;
SLset(&sl);//初始化
SLpushback(&sl, 1); //尾插
SLprint(&sl);
SLpushback(&sl, 2); //尾插
SLprint(&sl); SLpushback(&sl, 3); //尾插
SLprint(&sl); SLpushback(&sl, 4); //尾插
SLprint(&sl); SLpushback(&sl, 5); //尾插
SLprint(&sl); SLpushback(&sl, 6); //尾插
SLprint(&sl);
SLpushstart(&sl, 2);//头插
SLprint(&sl); SLpushstart(&sl, 3);//头插
SLprint(&sl); SLpushstart(&sl, 4);//头插
SLprint(&sl);
SLfind(&sl, 4, 99);
SLprint(&sl);
SLdfind(&sl, 2);
SLprint(&sl);
SLdback(&sl);
SLprint(&sl);
SLseedg(&sl, SLseed(&sl, 99) , 88);
SLprint(&sl);
SLruin(&sl);
SLprint(&sl);
system("pause");
}
int main()
{
SLtest();
return 0;
}
seqlist.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<Windows.h>
typedef int datetype;//不知道具体类型,可以一下子改
typedef struct seqlist {
datetype* arr;//(顺序表数组实现增、删、改、查)动态顺序表
int size;//有效数据
int capacity;//容量(包含有效和浪费的数据)
}SL;//将struct seqlist 重命名为typedef
void SLset(SL* ps);//初始化声明
void SLpushback(SL* ps, datetype x);//尾插
void SLdback(SL* ps);//尾删
void SLpushstart(SL* ps, datetype x);//头插
void SLdstart(SL* ps);//头删除
void SLprint(SL* ps);//打印
void SLfind(SL* ps, int pos, datetype x);//指定位置插入
void SLdfind(SL* ps, int pos);//指定位置删除
int SLseed(SL* ps, datetype x);//查找
void SLseedg(SL* ps, int pos,datetype x); //查找替换修改
void SLruin(SL* ps);//销毁
seqlist.c
#include"seqlist.h"
void SLset(SL* ps) {
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
void nospace(SL* ps) {
if (ps->size == ps->capacity) {
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
datetype* tmp = (datetype*)realloc(ps->arr, newcapacity * sizeof(datetype));
if (tmp == NULL) {
perror("realloc");
exit(1);
}
ps->arr = tmp;
ps->capacity = newcapacity;
}
}
void SLpushback(SL* ps, datetype x) {//x是插入数据
//情况2:空间不够进行扩容
nospace(ps);
ps->arr[ps->size++] = x;//情况1:空间够直接加
}
void SLpushstart(SL* ps, datetype x) {//头插
assert(ps);
nospace(ps);
for (int i = ps->size; i >0 ; i--) {
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[0] = x;
ps->size++;
}
void SLprint(SL* ps) {
for (int i = 0; i < ps->size ; i++) {
printf("%d ", ps->arr[i]);
}
printf("\n");
}
void SLdstart(SL* ps) {
assert(ps && ps->size);
for (int i = 0; i < ps->size-1; i++) {
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
void SLdback(SL* ps) {
assert(ps && ps->size);
ps->size--;
}
void SLfind(SL* ps, int pos, datetype x) {
assert(ps);
assert(pos >= 0 && pos <= ps->size);
nospace(ps);
for (int i = ps->size; i > pos; i--) {
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[pos] = x;
ps->size++;
}
void SLdfind(SL* ps, int pos) {
assert(ps);
assert(pos >= 0 && pos < ps->size);
for (int i = pos; i < ps->size - 1; i++) {
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
int SLseed(SL* ps, datetype x) {
assert(ps);
for (int i = 0; i < ps->size; i++) {
if (ps->arr[i] == x) {
printf("找到了,下标是%d\n",i);
return i;
}
}
printf("没找到\n");
return 0;
}
void SLseedg(SL* ps, int pos, datetype x) {
assert(ps);
assert(pos >= 0 && pos < ps->size);
ps->arr[pos] = x;
}
void SLruin(SL* ps) {
if (ps->arr )
free(ps->arr);
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
大家可以自己测试然后试着写写。
9>>结语
顺序表的内容就结束啦,怎么样?大家是否感觉还可以,数据结构也没那么那么难对吧,其实任何学科都一样,肯用心学,肯花心思,相信都能攻破,希望大家和我一起保持这份干劲,一直终身学下去!