目录
1、前言
在上一篇文章中我们写了两个函数分别为创建空间和插入数据,在这篇文章中,我们开始编写其他的函数,主函数和makefile我们在下一篇文章中进行编写,
2.工程文件
2.1:删除数据
我们还是先画一张图,我们要把88这个数据进行删除,那么我们要怎么删除呢?我们先来写一下伪代码
//在删除之前我们先要把我们要删除的数据进行保存,当然也可以不保存,看个人的习惯
//将pos以后的数据向前移动一位数据
for(int i=pos;i<count-1;i++)
{
arr[i]=a[i+1];
}
//或者下面这种方式
for(int i=pos;i<count;i++)
{
a[i-1]=a[i];
}
count--;
我们接下来在我们原来的list.c中继续编写我们的子函数
//创建顺序表
int my_malloc_func(SeqList **ppList)
{
//入参检查
if(NULL == ppList)
{
printf("null error: ");
return NULL_ERROR;
}
//开辟空间
*ppList=(SeqList *)malloc(sizeof(SeqList));
//查看开间开辟与否
if(NULL==*pList)
{
printf("mallo error: ");
return MALLOC_ERROR;
}
//初始化开辟的空间值
memset(*ppList,'\0',sizeof(SeqList));
return OK;
}
//在顺序表中插入数据
//函数第一个参数是结构体指针,第二个是插入的位置,第三个参数是要插入的数据
int my_insert(SeqList *pList,int pos ,int Newdata)
{
//还是入参检查
if(NULL == pList)
{
printf("creat error: ");
return CREAT_ERROR;
}
//判断插入的位置是否合适
if(pos<0 || pos>=count)
{
printf("pos error: ")
return POS_ERROR;
}
//在插入的时候我们还要注意我们的顺序表是否满了,
//因为插入是要有空余位置才能插入
if(10==pList->count)
{
printf("full error: ");
return FULL ERROR;
}
//开始插入
//将pos以后的数据向后移一个
for(int i=pList->count-1;i>=pos;i--)
{
pList->arr[i+1]=pList->a[i];
}
pList->arr[pos]=Newdata;
pList->count++;
return OK;
}
//删除数据函数
//参数1 结构体指针
//参数2 位置
// 参数3 保存删除数据的值
int my_delete(SeqList *pList,int pos,data_type *pdeledata)
{
//入参检查
if(NULL==pList)
{
printf("null error: ");
return NULL_ERROR;
}
//判断删除的位置
//不能删除0以下和大于等于count的位置
if(pos<0 || pos>=pList->count)
{
printf("pos error: ");
return POS_ERROR;
}
//还有一种情况就是表空的情况下是不能删除的
if(0==pList->count)
{
printf("empty error: ");
return EMPTY_ERROR;
}
//保存要删除的数据
*pdeldata=pList->arr[pos];
//执行删除
for(int i=pos;i<pList->count-1;i++)
{
pList->arr[i]=pList->arr[i+1];
}
//更新count中的值
pList->count--;
return OK;
}
我们接下来更新一下我们的库文件
#ifndef _LIST_H
#define _LIST_H
//引入头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//创建结构体
//数据类型的定义
typedef int data_type
struct seqlist
{
data_type arr[10];
data_type count;
}SeqList;
//定义错误枚举,在这里我把我们接下来可能出现的错误进行定义,以便我们可以快速查找错误
enum value
{
EMPTY_ERROR=-7,
FULL_ERROR,
POS_ERROR,
CREAT_ERROR,
NULL_ERROR,
MALLOC_ERROR,
ERROR,
OK
};
//函数说明
int my_mollac_func(SeqList **ppList);//开辟空间函数
int my_insert(SeqList *pList,int pos,int Newdata);//插入函数
int my_delete(SeqList *pList,int pos,int *pdeldata);//删除数据
#endif
2.2修改数据
//创建顺序表
int my_malloc_func(SeqList **ppList)
{
//入参检查
if(NULL == ppList)
{
printf("null error: ");
return NULL_ERROR;
}
//开辟空间
*ppList=(SeqList *)malloc(sizeof(SeqList));
//查看开间开辟与否
if(NULL==*pList)
{
printf("mallo error: ");
return MALLOC_ERROR;
}
//初始化开辟的空间值
memset(*ppList,'\0',sizeof(SeqList));
return OK;
}
//在顺序表中插入数据
//函数第一个参数是结构体指针,第二个是插入的位置,第三个参数是要插入的数据
int my_insert(SeqList *pList,int pos ,int Newdata)
{
//还是入参检查
if(NULL == pList)
{
printf("creat error: ");
return CREAT_ERROR;
}
//判断插入的位置是否合适
if(pos<0 || pos>=count)
{
printf("pos error: ")
return POS_ERROR;
}
//在插入的时候我们还要注意我们的顺序表是否满了,
//因为插入是要有空余位置才能插入
if(10==pList->count)
{
printf("full error: ");
return FULL ERROR;
}
//开始插入
//将pos以后的数据向后移一个
for(int i=pList->count-1;i>=pos;i--)
{
pList->arr[i+1]=pList->a[i];
}
pList->arr[pos]=Newdata;
pList->count++;
return OK;
}
//删除数据函数
//参数1 结构体指针
//参数2 位置
// 参数3 保存删除数据的值
int my_delete(SeqList *pList,int pos,data_type *pdeledata)
{
//入参检查
if(NULL==pList)
{
printf("null error: ");
return NULL_ERROR;
}
//判断删除的位置
//不能删除0以下和大于等于count的位置
if(pos<0 || pos>=pList->count)
{
printf("pos error: ");
return POS_ERROR;
}
//还有一种情况就是表空的情况下是不能删除的
if(0==pList->count)
{
printf("empty error: ");
return EMPTY_ERROR;
}
//保存要删除的数据
*pdeldata=pList->arr[pos];
//执行删除
for(int i=pos;i<pList->count-1;i++)
{
pList->arr[i]=pList->arr[i+1];
}
//更新count中的值
pList->count--;
return OK;
}
//修改数据
int my_revise(SeqList *pList,int pos,int Newdata)
{
//入参检查
if(NULL==pList)
{
printf("null error: ");
return NULL_ERROR;
}
//判断位置是否合适
if(pos<0 || pos>=pList->count)
{
printf("pos error : ");
return POS_ERROR;
}
//修改数据
pList->arr[pos]=Newdata;
return OK;
}
更新一下库文件
#ifndef _LIST_H
#define _LIST_H
//引入头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//创建结构体
//数据类型的定义
typedef int data_type
struct seqlist
{
data_type arr[10];
data_type count;
}SeqList;
//定义错误枚举,在这里我把我们接下来可能出现的错误进行定义,以便我们可以快速查找错误
enum value
{
EMPTY_ERROR=-7,
FULL_ERROR,
POS_ERROR,
CREAT_ERROR,
NULL_ERROR,
MALLOC_ERROR,
ERROR,
OK
};
//函数说明
int my_mollac_func(SeqList **ppList);//开辟空间函数
int my_insert(SeqList *pList,int pos,int Newdata);//插入函数
int my_delete(SeqList *pList,int pos,int *pdeldata);//删除数据
int my_revise(SeqList *pList,int pos,int Newdata);
#endif
2.3:查找数据
我们直接上代码,其中的一些注意点我将会在代码中说明
//创建顺序表
int my_malloc_func(SeqList **ppList)
{
//入参检查
if(NULL == ppList)
{
printf("null error: ");
return NULL_ERROR;
}
//开辟空间
*ppList=(SeqList *)malloc(sizeof(SeqList));
//查看开间开辟与否
if(NULL==*pList)
{
printf("mallo error: ");
return MALLOC_ERROR;
}
//初始化开辟的空间值
memset(*ppList,'\0',sizeof(SeqList));
return OK;
}
//在顺序表中插入数据
//函数第一个参数是结构体指针,第二个是插入的位置,第三个参数是要插入的数据
int my_insert(SeqList *pList,int pos ,int Newdata)
{
//还是入参检查
if(NULL == pList)
{
printf("creat error: ");
return CREAT_ERROR;
}
//判断插入的位置是否合适
if(pos<0 || pos>=count)
{
printf("pos error: ")
return POS_ERROR;
}
//在插入的时候我们还要注意我们的顺序表是否满了,
//因为插入是要有空余位置才能插入
if(10==pList->count)
{
printf("full error: ");
return FULL ERROR;
}
//开始插入
//将pos以后的数据向后移一个
for(int i=pList->count-1;i>=pos;i--)
{
pList->arr[i+1]=pList->a[i];
}
pList->arr[pos]=Newdata;
pList->count++;
return OK;
}
//删除数据函数
//参数1 结构体指针
//参数2 位置
// 参数3 保存删除数据的值
int my_delete(SeqList *pList,int pos,data_type *pdeledata)
{
//入参检查
if(NULL==pList)
{
printf("null error: ");
return NULL_ERROR;
}
//判断删除的位置
//不能删除0以下和大于等于count的位置
if(pos<0 || pos>=count)
{
printf("pos error: ");
return POS_ERROR;
}
//还有一种情况就是表空的情况下是不能删除的
if(0==pList->count)
{
printf("empty error: ");
return EMPTY_ERROR;
}
//保存要删除的数据
*pdeldata=pList->arr[pos];
//执行删除
for(int i=pos;i<pList->count-1;i++)
{
pList->arr[i]=pList->arr[i+1];
}
//更新count中的值
pList->count--;
return OK;
}
//修改数据
int my_revise(SeqList *pList,int pos,int Newdata)
{
//入参检查
if(NULL==pList)
{
printf("null error: ");
return NULL_ERROR;
}
//判断位置是否合适
if(pos<0 || pos>=pList->count)
{
printf("pos error : ");
return POS_ERROR;
}
//修改数据
pList->arr[pos]=Newdata;
return Ok;
}
//查找函数
//第一个参数依旧是我们的结构体指针
//第二个参数是查找的数据
/*第三个数据是我要着重讲的,我们在查找的时候可能会有多个数据符合,这时我们在主函数中
定义一个数组用来存放数据的下标,这样可以把所有的数据找到*/
int my_search(SeqList *pList,int searchdata,int *pdata)
{
int i,j=0;
if(NULL==*pList)
{
printf("null_error:");
return NULL_error;
}
if(NULL==pdata)
{
printf("creat error:");
return CREAT_ERROR;
}
for(i=0;i<pList->count;i++)
{
if(searchdata==pList->arr[i])
{
*(pdata+j)=i;
j++;
}
}
return j;
}
读者可以自己更新一下库文件,篇幅问题我只在最后更新库文件了,如果读者想要自己去验证一下每个函数可以自行更新。
2.4:显示数据 。
我们在这个函数中,将顺序表进行打印,其实比较简单,就是一个for循环
//创建顺序表
int my_malloc_func(SeqList **ppList)
{
//入参检查
if(NULL == ppList)
{
printf("null error: ");
return NULL_ERROR;
}
//开辟空间
*ppList=(SeqList *)malloc(sizeof(SeqList));
//查看开间开辟与否
if(NULL==*pList)
{
printf("mallo error: ");
return MALLOC_ERROR;
}
//初始化开辟的空间值
memset(*ppList,'\0',sizeof(SeqList));
return OK;
}
//在顺序表中插入数据
//函数第一个参数是结构体指针,第二个是插入的位置,第三个参数是要插入的数据
int my_insert(SeqList *pList,int pos ,int Newdata)
{
//还是入参检查
if(NULL == pList)
{
printf("creat error: ");
return CREAT_ERROR;
}
//判断插入的位置是否合适
if(pos<0 || pos>=count)
{
printf("pos error: ")
return POS_ERROR;
}
//在插入的时候我们还要注意我们的顺序表是否满了,
//因为插入是要有空余位置才能插入
if(10==pList->count)
{
printf("full error: ");
return FULL ERROR;
}
//开始插入
//将pos以后的数据向后移一个
for(int i=pList->count-1;i>=pos;i--)
{
pList->arr[i+1]=pList->a[i];
}
pList->arr[pos]=Newdata;
pList->count++;
return OK;
}
//删除数据函数
//参数1 结构体指针
//参数2 位置
// 参数3 保存删除数据的值
int my_delete(SeqList *pList,int pos,data_type *pdeledata)
{
//入参检查
if(NULL==pList)
{
printf("null error: ");
return NULL_ERROR;
}
//判断删除的位置
//不能删除0以下和大于等于count的位置
if(pos<0 || pos>=count)
{
printf("pos error: ");
return POS_ERROR;
}
//还有一种情况就是表空的情况下是不能删除的
if(0==pList->count)
{
printf("empty error: ");
return EMPTY_ERROR;
}
//保存要删除的数据
*pdeldata=pList->arr[pos];
//执行删除
for(int i=pos;i<pList->count-1;i++)
{
pList->arr[i]=pList->arr[i+1];
}
//更新count中的值
pList->count--;
return OK;
}
//修改数据
int my_revise(SeqList *pList,int pos,int Newdata)
{
//入参检查
if(NULL==pList)
{
printf("null error: ");
return NULL_ERROR;
}
//判断位置是否合适
if(pos<0 || pos>=pList->count)
{
printf("pos error : ");
return POS_ERROR;
}
//修改数据
pList->arr[pos]=Newdata;
return Ok;
}
//查找函数
//第一个参数依旧是我们的结构体指针
//第二个参数是查找的数据
/*第三个数据是我要着重讲的,我们在查找的时候可能会有多个数据符合,这时我们在主函数中
定义一个数组用来存放数据的下标,这样可以把所有的数据找到*/
int my_search(SeqList *pList,int searchdata,int *pdata)
{
int i,j=0;
if(NULL==*pList)
{
printf("null_error:");
return NULL_error;
}
if(NULL==pdata)
{
printf("creat error:");
return CREAT_ERROR;
}
for(i=0;i<pList->count;i++)
{
if(searchdata==pList->arr[i])
{
*(pdata+j)=i;
j++;
}
}
return j;
}
//显示函数
int my_display(SeqList *pList)
{
if(NULL==pList)
{
printf(:null error:");
return NULL_ERROR;
}
for(int i=0;i<pList->count;i++)
{
printf("%2d",pList->arr[i]);
}
return OK;
}
2.4销毁顺序表
销毁顺序表主要运用了malloc函数和堆区的特点,在堆区由程序员开辟空间,释放空间也得程序员自己手动释放
//创建顺序表
int my_malloc_func(SeqList **ppList)
{
//入参检查
if(NULL == ppList)
{
printf("null error: ");
return NULL_ERROR;
}
//开辟空间
*ppList=(SeqList *)malloc(sizeof(SeqList));
//查看开间开辟与否
if(NULL==*pList)
{
printf("mallo error: ");
return MALLOC_ERROR;
}
//初始化开辟的空间值
memset(*ppList,'\0',sizeof(SeqList));
return OK;
}
//在顺序表中插入数据
//函数第一个参数是结构体指针,第二个是插入的位置,第三个参数是要插入的数据
int my_insert(SeqList *pList,int pos ,int Newdata)
{
//还是入参检查
if(NULL == pList)
{
printf("creat error: ");
return CREAT_ERROR;
}
//判断插入的位置是否合适
if(pos<0 || pos>=count)
{
printf("pos error: ")
return POS_ERROR;
}
//在插入的时候我们还要注意我们的顺序表是否满了,
//因为插入是要有空余位置才能插入
if(10==pList->count)
{
printf("full error: ");
return FULL ERROR;
}
//开始插入
//将pos以后的数据向后移一个
for(int i=pList->count-1;i>=pos;i--)
{
pList->arr[i+1]=pList->a[i];
}
pList->arr[pos]=Newdata;
pList->count++;
return OK;
}
//删除数据函数
//参数1 结构体指针
//参数2 位置
// 参数3 保存删除数据的值
int my_delete(SeqList *pList,int pos,data_type *pdeledata)
{
//入参检查
if(NULL==pList)
{
printf("null error: ");
return NULL_ERROR;
}
//判断删除的位置
//不能删除0以下和大于等于count的位置
if(pos<0 || pos>=count)
{
printf("pos error: ");
return POS_ERROR;
}
//还有一种情况就是表空的情况下是不能删除的
if(0==pList->count)
{
printf("empty error: ");
return EMPTY_ERROR;
}
//保存要删除的数据
*pdeldata=pList->arr[pos];
//执行删除
for(int i=pos;i<pList->count-1;i++)
{
pList->arr[i]=pList->arr[i+1];
}
//更新count中的值
pList->count--;
return OK;
}
//修改数据
int my_revise(SeqList *pList,int pos,int Newdata)
{
//入参检查
if(NULL==pList)
{
printf("null error: ");
return NULL_ERROR;
}
//判断位置是否合适
if(pos<0 || pos>=pList->count)
{
printf("pos error : ");
return POS_ERROR;
}
//修改数据
pList->arr[pos]=Newdata;
return Ok;
}
//查找函数
//第一个参数依旧是我们的结构体指针
//第二个参数是查找的数据
/*第三个数据是我要着重讲的,我们在查找的时候可能会有多个数据符合,这时我们在主函数中
定义一个数组用来存放数据的下标,这样可以把所有的数据找到*/
int my_search(SeqList *pList,int searchdata,int *pdata)
{
int i,j=0;
if(NULL==*pList)
{
printf("null_error:");
return NULL_error;
}
if(NULL==pdata)
{
printf("creat error:");
return CREAT_ERROR;
}
for(i=0;i<pList->count;i++)
{
if(searchdata==pList->arr[i])
{
*(pdata+j)=i;
j++;
}
}
return j;
}
//显示函数
int my_display(SeqList *pList)
{
if(NULL==pList)
{
printf(:null error:");
return NULL_ERROR;
}
for(int i=0;i<pList->count;i++)
{
printf("%2d",pList->arr[i]);
}
return OK;
}
// 销毁函数
int my_release(SeqList **ppList)
{
if(NULL==ppList)
{
printf("null error:");
return NULL_ERROR;
}
if(NULL==*ppList)
{
printf("creat error:");
return CREAT_ERROR;
}
free(*ppList);
*ppList=NULL;
}
3、主函数的编写
如果你看到这里恭喜你,我们已经完成了所有的子函数的编写,接下来读者可以自行编写主函数了,也可以模仿我的主函数的写法,万变不离其宗,
#include "../include/list.h"
int main()
{
int ret;
//开辟空间
SeqList *pList=NULL;
ret=my_malloc_func(&pList);
if(ret<0)
{
return error;
}
printf("申请成功");
//实现插入数据到顺序表中
data_type data,pos;
while(1)
{
printf("请输入插入的数据\n");
scanf("%d",&pos);
printf("请输入要插入的数据\n");
scanf("%d",&data);
if(pos==-1)
{
printf("插入完成\n");
break;
}
my_insert(pList,pos,data);
printf("显示顺序表");
my_diaplay(pList);
}
//销毁顺序表
my_release(pList);
return 0;
}
//其他的子函数可以根据读者自己的习惯进行调用即可,我如果全部调用,代码实在是太多了
//还请理解一下我,这篇文章的篇幅实在太长,我下面还要写makefile,大家多多包涵
4、makefile的编写
这个C语言的工程足够大了,我们接下来把我们学过的makefile用一下
4.1总makefile
MYAPP:=main
OBJS:=list.o text.o
CC:=gcc
CFLGAS:=-c -g -Wall
export MYAPP OBJS CC CFLGAS
ALL:
make -C src
make -C obj
.PHONY.clean
clean:
$(RM) obj/*.o
$(RM) bin/*
4.2src中的makefile
ALL:$(OBJS)
mv *.o ../obj/
list.o:list.c:
$(CC) $(CFLGAS) $< -o $@
main.o:main.c
$(CC) $(CFLGAS) $< -o $@
4.3:obj中的makefile
ALL:$(MYAPP)
mv * ../bin
$(MYAPP):$(OBJS)
$(CC) $^ -o $@
5、后记
我花费了两篇文章带大家认识顺序表和编写了顺序表的子函数以及主函数还把我们学的makefile运用了一下,我带大家敲了了一遍代码,说实话,如果只讲理论可能写不了这么多,但是大家学数据结构还是运用的多,所以我还是把代码敲了出来,也许在这些代码中有一些错误,如果大家看出来了还请告诉我,好了顺序表完结了,撒花,我们下一篇开单链表,我还会再开一个专栏讲IO感兴趣的同学也可以去看看,有不足的地方还请各位大佬帮我指出来