提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
一、前期准备
typedef int SLData;
typedef struct SeqList
{
SLData* a;
SLData size;
SLData capacity;
}SL;
//初始化
void SLInit(SL* ps);
//打印
void SLPrint(SL* ps);
//检查是否有空间
void SLCheckCapacity(SL* ps);
//销毁
void SLDestory(SL* ps);
1.链表初始化
void SLInit(SL* ps)
{
ps->a = NULL;//将指针置为空
ps->capacity = ps->size = 0;//链表的序号和容量设为0
}
2.链表的打印
void SLPrint(SL* ps)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);//设一个for循环来打印
}
printf("\n");
}
3.检查链表的空间
void SLCheckCapacity(SL* ps)
{
if (ps->capacity == ps->size)//如果序号和容量相等那说明空间已满,需要扩充空间
{
//设一个变量并判断容量是否为0,若为0给4个空间,不为0则扩大二倍
int newnode = ps->capacity == 0 ? 4 : ps->capacity * 2;
//开辟一个动态空间,可保证容量随时扩充(按字节算)
SLData* tmp = (SLData*)realloc(ps->a, sizeof(SLData) * newdata);
if (tmp == NULL)
{
printf("relloc错误");
exit(-1);
}
ps->capacity = newdata;//将变量和指针赋给ps对应的值
ps->a = tmp;
}
}
4.销毁链表
void SLDestory(SL* ps)
{
assert(ps);
if (ps->a)
{
free(ps->a);
ps->a = NULL;//将指针置为空
ps->capacity = ps->size = 0;//将序号和容量置为0
}
}
二、头插和尾插
1.头插
void SLPushFront(SL* ps, SLData x)
{
SLCheckCapacity(ps);//判断空间是否为满
assert(ps);//防止为空指针
int end = ps->size -1;//设一个end方便将数移动位置
while (end >= 0)//用while循环以end为下标将数进行移位
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[0] = x;//将头赋值
ps->size++;//并将size+1
//SLInsert(ps, 0, x);//可以使用下面的函数插入进行函数复用
}
2.尾插
void SLPushBack(SL* ps, SLData x)
{
SLCheckCapacity(ps);//判断是否为满
assert(ps);
ps->a[ps->size] = x;//直接插入
ps->size++;
//SLInsert(ps,ps->size,x);//可以使用下面的函数插入进行函数复用
}
三、头删和尾删
1.头删
void SLPopFront(SL* ps)
{
assert(ps);
assert(ps->size > 0);//断言 ps->size>0防止越界
int begin = 1;//设begin为1,方便进行位置的移动
while (begin<ps->size)//使用while循环将位置进行移动
{
ps->a[begin - 1] = ps->a[begin];//注意防止begin越界
++begin;
}
ps->size--;
//SLErase(ps, 0);
}
2.尾删
void SLPopBack(SL* ps)
{
assert(ps);
assert(ps->size > 0);
ps->size--;//直接删除
//SLErase(ps,ps->size);
}
四、查找和修改
1.查找
int SLFind(SL* ps, SLData x)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
if (ps->a[i] == x)
{
return i;//找到则传出序号
}
}
return -1;//找不到则传出-1
}
2.修改
void SLModify(SL* ps, int pos, SLData x)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
ps->a[pos] = x;//更改一般可以和查找搭配使用
}
5.插入和删除
1.插入
void SLInsert(SL* ps, int pos, SLData x)
{
SLCheckCapacity(ps);//判断空间是否为满
assert(ps);
assert(pos >= 0 && pos <= ps->size);//pos必须在0到size之间
int end = ps->size - 1;//设一个end来作为下标移动数字
while (end >= pos)
{
ps->a[end+1] = ps->a[end];
end--;
}
ps->a[pos] = x;
ps->size++;
}
2.删除
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
int begin = pos;
while (begin < ps->size)
{
ps->a[begin] = ps->a[begin + 1];
begin++;
}
ps->size--;
}
六、顺序表的实现
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
void menu()
{
printf("****************************\n");
printf("1.头插 2.尾插\n");
printf("3.头删 4.尾删\n");
printf("5.查找 6.更改\n");
printf("7.插入 8.删除\n");
printf("9.销毁 0.退出\n");
printf("****************************\n");
}
void test()
{
menu();
SL sl;
SLInit(&sl);
SLPushBack(&sl, 0);
SLPushBack(&sl, 1);
SLPushBack(&sl, 2);
SLPushBack(&sl, 3);
SLPrint(&sl);
int option = -1;
do
{
printf("请输入要选择的操作:>");
while(scanf("%d", &option) == EOF)
{
printf("输入错误,请重新输入");
}
getchar();
int x = 0;
int y = 0;
int pos = 0;
switch (option)
{
case 1:
printf("请输入头插的数字:>");
scanf("%d", &x);
SLPushFront(&sl, x);
SLPrint(&sl);
break;
case 2:
printf("请输入尾插的数字:>");
scanf("%d", &x);
SLPushBack(&sl, x);
SLPrint(&sl);
break;
case 3:
SLPopFront(&sl);
SLPrint(&sl);
break;
case 4:
SLPopBack(&sl);
SLPrint(&sl);
break;
case 5:
printf("请输入查找的数字:>");
scanf("%d", &x);
y = SLFind(&sl, x);
if (y == -1)
{
printf("没找到\n");
}
else
{
printf("找到了\n");
}
break;
case 6:
printf("请输入要更改之前的和更改之后的数字:>");
scanf("%d %d", &x, &y);
x = SLFind(&sl, x);
SLModify(&sl, x, y);
SLPrint(&sl);
break;
case 7:
printf("请输入要插入数的位置和要插入的数:>");
scanf("%d %d", &pos, &x);
SLInsert(&sl, pos, x);
SLPrint(&sl);
break;
case 8:
printf("请输入要删除的数>");
scanf("%d", &x);
pos = SLFind(&sl, x);
SLErase(&sl, pos);
SLPrint(&sl);
break;
default:
printf("输入错误,请重新输入\n");
break;
};
} while (option != 0);
}
int main()
{
test();
return 0;
}
总结
以上为顺序表实现的全部内容。