前言
本篇文章主要是带领大家用C语言实现动态顺序表。
一、结构体创建及其初始化
//顺序表结构体创建
struct SeqList
{
SLDataType* sl;
int size;
int capacity;
}SL;
//初始化
void SLInit(struct SeqList* ps)
{
ps->sl = NULL;
ps->size = 0;
ps->capacity = 0;
}
ps:SLDataType是#define定义的顺序表的数据类型,这里我们用的是int
#define SLDataType int
二、顺序表打印
//顺序表打印
void Print(struct SeqList* ps)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
printf("%d", ps->sl[i]);
}
printf("\n");
}
三、扩容函数
由于我们写的是动态顺序表,所以需要用到malloc,realloc等动态内存管理函数来进行动态扩容,因此我们专门写了一个扩容函数进行扩容。
//扩容函数
void SLDila(struct SeqList* ps)
{
if (ps->size == ps->capacity)
{
int Newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//判断是否已经开辟空间,没有则开辟四个SLDataType的空间
SLDataType* ptr = realloc(ps->sl, Newcapacity * sizeof(SLDataType));
if (ptr == NULL)
{
perror("ralloc");
exit(-1);
}
ps->sl = ptr;
ps->capacity = Newcapacity;
}
}
四、尾插/尾删
尾插:即从顺序表末尾将数据插入进去
//顺序表尾插
void SLPushBack(struct SeqList* ps, SLDataType x)
{
SLDila(ps);
ps->sl[ps->size] = x;
ps->size++;
}
尾删:由于我们是靠size读取写入的数字,所以没必要将最后一位挪走或者初始化,直接size--即可
void SLPopBack(struct SeqList* ps)
{
assert(ps->size);//如果size为0则没有要删除的内容,直接报错
ps->size--;
}
五、首插/首删
首插:从头部的位置插入数据,由于从头部插入我们需要挪数据,我们采用的是从后往前挪的办法,如下图所示:
//顺序表首插
void SLPushFront(struct SeqList* ps, SLDataType x)
{
assert(ps);
SLDila(ps);
int end = ps->size - 1;
while (end >= 0)
{
ps->sl[end + 1] = ps->sl[end];
end--;
}
ps->sl[0] = x;
ps->size++;
}
首删:和首插相反,从前往后挪
//顺序表首删
void SLPopFront(struct SeqList* ps)
{
assert(ps);
assert(ps->size > 0);
int begin = 0;
while (begin < ps->size-1)
{
ps->sl[begin] = ps->sl[begin+1];
begin++;
}
ps->size--;
}
六、中间插入/中间删除/查找数字
中间插入:输入坐标,将数据插入到坐标位置,方法与首插类似
//顺序表中间插入
void SLInsert(struct SeqList* ps, int a, SLDataType x)
{
assert(ps);
assert(a >= 0 && a <= ps->size);
SLDila(ps);
int end = ps->size-1;
while (end>=a)
{
ps->sl[end + 1] = ps->sl[end];
end--;
}
ps->sl[a] = x;
ps->size++;
}
中间删除:方法和首删类似
//顺序表中间删除
void SLErase(struct SeqList* ps, int a)
{
assert(ps);
assert(a >= 0 && a < ps->size);
int begin = a;
while (begin < ps->size)
{
ps->sl[begin] = ps->sl[begin + 1];
begin++;
}
ps->size--;
}
查找数字:输入要查找的数字,找到返回下标,未找到返回-1
//查找目标数
int SLFind(struct SeqList* ps, SLDataType x)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
if (ps->sl[i] == x)
{
return i;
}
}
printf("未找到该数字");
return -1;
}
七、退出销毁及菜单
销毁:
//顺序表销毁
void SLDestroy(struct SeqList* ps)
{
free(ps->sl);
ps->sl = NULL;
}
菜单:
void menu()
{
printf("*******************************\n");
printf("****1.尾部插入 2.尾部删除 ****\n");
printf("****3.头部插入 4.头部删除 ****\n");
printf("****5.中间插入 6.中间删除 ****\n");
printf("****7.打印 0.退出 ****\n");
printf("*******************************\n");
}
八、效果演示
九、代码
SeqList.h
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define SLDataType int
//顺序表结构体创建
struct SeqList
{
SLDataType* sl;
int size;
int capacity;
}SL;
//初始化
void SLInit(struct SeqList* ps);
//顺序表打印
void Print(struct SeqList* ps);
//顺序表尾插
void SLPushBack(struct SeqList* ps, SLDataType x);//x是要插进去的数字
//顺序表尾删
void SLPopBack(struct SeqList* ps);
//顺序表销毁
void SLDestroy(struct SeqList* ps);
//扩容函数
void SLDila(struct SeqList* ps);
//顺序表首插
void SLPushFront(struct SeqList* ps, SLDataType x);
//顺序表首删
void SLPopFront(struct SeqList* ps);
//顺序表中间插入
void SLInsert(struct SeqList* ps, int a, SLDataType x);
//顺序表中间删除
void SLErase(struct SeqList* ps, int a);
//查找目标数
int SLFind(struct SeqList* ps, SLDataType x);
test.c
#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.打印 0.退出 ****\n");
printf("*******************************\n");
}
int main()
{
menu();
SLInit(&SL);
int input;
do
{
printf("请选择:");
scanf("%d", &input);
switch(input)
{
case 1:
printf("请输入要写入的数字:");
SLDataType i;
scanf("%d", &i);
SLPushBack(&SL, i);
break;
case 2:
SLPopBack(&SL);
break;
case 3:
printf("请输入要写入的数字:");
SLDataType a;
scanf("%d", &a);
SLPushFront(&SL, a);
break;
case 4:
SLPopFront(&SL);
break;
case 5:
printf("请输入要写入的数字及下标:");
SLDataType b;
int j;
scanf("%d %d", &b,&j);
SLInsert(&SL, j, b);
break;
case 6:
printf("请输入要删除的数字:");
int c;
scanf("%d", &c);
int ret = SLFind(&SL, c);
if (ret != -1)
{
SLErase(&SL, ret);
}
else
{
printf("未找到该数字");
}
break;
case 7:
Print(&SL);
break;
case 0:
printf("退出");
SLDestroy(&SL);
break;
default:
printf("输入错误,请重新输入");
break;
}
} while (input);
return 0;
}
SeqList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
//扩容函数
void SLDila(struct SeqList* ps)
{
if (ps->size == ps->capacity)
{
int Newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//判断是否已经开辟空间,没有则开辟四个SLDataType的空间
SLDataType* ptr = realloc(ps->sl, Newcapacity * sizeof(SLDataType));
if (ptr == NULL)
{
perror("ralloc");
exit(-1);
}
ps->sl = ptr;
ps->capacity = Newcapacity;
}
}
//初始化
void SLInit(struct SeqList* ps)
{
ps->sl = NULL;
ps->size = 0;
ps->capacity = 0;
}
//顺序表打印
void Print(struct SeqList* ps)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
printf("%d", ps->sl[i]);
}
printf("\n");
}
//顺序表尾插
void SLPushBack(struct SeqList* ps, SLDataType x)
{
SLDila(ps);
ps->sl[ps->size] = x;
ps->size++;
}
//顺序表尾删
void SLPopBack(struct SeqList* ps)
{
assert(ps->size);//如果size为0则没有要删除的内容,直接报错
ps->size--;
}
//顺序表销毁
void SLDestroy(struct SeqList* ps)
{
free(ps->sl);
ps->sl = NULL;
}
//顺序表首插
void SLPushFront(struct SeqList* ps, SLDataType x)
{
assert(ps);
SLDila(ps);
int end = ps->size - 1;
while (end >= 0)
{
ps->sl[end + 1] = ps->sl[end];
end--;
}
ps->sl[0] = x;
ps->size++;
}
//顺序表首删
void SLPopFront(struct SeqList* ps)
{
assert(ps);
assert(ps->size > 0);
int begin = 0;
while (begin < ps->size-1)
{
ps->sl[begin] = ps->sl[begin+1];
begin++;
}
ps->size--;
}
//顺序表中间插入
void SLInsert(struct SeqList* ps, int a, SLDataType x)
{
assert(ps);
assert(a >= 0 && a <= ps->size);
SLDila(ps);
int end = ps->size-1;
while (end>=a)
{
ps->sl[end + 1] = ps->sl[end];
end--;
}
ps->sl[a] = x;
ps->size++;
}
//顺序表中间删除
void SLErase(struct SeqList* ps, int a)
{
assert(ps);
assert(a >= 0 && a < ps->size);
int begin = a;
while (begin < ps->size)
{
ps->sl[begin] = ps->sl[begin + 1];
begin++;
}
ps->size--;
}
//查找目标数
int SLFind(struct SeqList* ps, SLDataType x)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
if (ps->sl[i] == x)
{
return i;
}
}
printf("未找到该数字");
return -1;
}
总结
以上就是顺序表的全部内容,希望铁子们能够有所收获。