
数据结构——顺序表接口实现(C语言)
发布日期:2021-05-07 00:27:25
浏览次数:28
分类:原创文章
本文共 7861 字,大约阅读时间需要 26 分钟。
C语言实现顺序表的增删查改
github代码下载
代码下载:
一、概念及结构
顺序表是一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表可分为两类:
- 静态顺序表:使用定长数组存储。
- 动态顺序表:使用动态开辟的数组存储。
二、接口实现
2.1 顺序表的两种存储方式与结构图
2.1.1 顺序表的静态存储
#define N 100typedef int SLDataTpye;//2.1.1顺序表的静态存储typedef struct SeqList{ SLDataTpye arr[N]; //定长数组 size_t size; //有效数组的个数}SL,SeqList;
2.1.3 顺序表的动态存储
typedef int SLDataTpye;//2.1.2 顺序表的动态存储typedef struct SeqList{ SLDataTpye * array; //指向动态开辟的数组 size_t size; //有效数据的个数 size_t capacity; //容量空间的大小};
typedef int SLDataTpye 代表顺序表数组的类型,使用这种方式方便后续对类型的更改
2.2 顺序表初始化
该函数功能将顺序表初始化为空表
操作前提:SL为未初始化线性表
操作结果:将SL初始化为空表
//顺序表初始化void SeqListInit(SeqList * psl){ //开辟的大小随机给值 psl->array = (SLDataTpye *)malloc(sizeof(SLDataTpye) * 4); if (psl->array == NULL) { printf("初始化失败\n"); exit(-1); } psl->size = 0; //有效数据为0 psl->capacity = 4; //容量空间大小为4}
2.3 顺序表增容
该函数一方面可以检查空间是否满了,另一方面可以增容。
操作前提:顺序表空间满了,即 capacity==size,需要进行增容
操作结果:顺序表空间扩大原来容量的二倍,即capacity*=2
//2.3 顺序表增容//检查空间,如果满了,进行增容void CheckCapacity(SeqList * psl){ //有效数据与容量空间相等代表空间满了,需要增容! if (psl->size == psl->capacity) { //对顺序表容量扩大两倍 psl->capacity *= 2; //使用realloc扩展空间 psl->array = (SLDataTpye *)realloc(psl->array, sizeof(SLDataTpye)*psl->capacity); //判断下是否申请失败 if (psl->array == NULL) { printf("增容失败\n"); exit(-1); } }}
2.4 顺序表打印
操作前提:顺序表存在
操作结果:打印顺序表每个节点的元素值
//2.4 顺序表打印void SeqListPrint(SeqList * psl){ //判断指针合法性 assert(psl); //依次遍历顺序表每个节点,并打印节点中的元素值 for (size_t i = 0; i < psl->size; ++i) { printf("psl->array[%d]=%d\n", i, psl->array[i]); }}
2.5 顺序表尾插
//2.5 顺序表尾插void SeqListPushBack(SeqList * psl, SLDataTpye x){ //判断指针合法性 assert(psl); //检查空间,如果满了,进行增容 CheckCapacity(psl); psl->array[psl->size] = x; //将数据x插入到线性表末尾 psl->size++; //有效数据加1}
2.6 顺序表尾删
数据表尾删只需要对size-1即可,不需要对末尾节点置零。
//2.6 顺序表尾删void SeqListPopBack(SeqList * psl){ //判断指针合法性 assert(psl); //有效数据-1 psl->size--;}
2.7 顺序表头插
//2.7 顺序表头插void SeqListPushFront(SeqList * psl, SLDataTpye x){ //判断指针合法性 assert(psl); //检查空间,如果满了,进行增容 CheckCapacity(psl); //头插从后往前拷贝 int end = psl->size - 1; //指向最后一个节点 while(end >= 0) { psl->array[end + 1] = psl->array[end]; //节点向后移动一个位置 --end; } psl->array[0] = x; //插入元素x psl->size++; //有效数据+1}
2.8 顺序表头删
//2.8 顺序表头删void SeqListPopFront(SeqList * psl){ //判断指针合法性 assert(psl); size_t start = 0; //指向第一个节点 while (start < psl->size-1) { psl->array[start] = psl->array[start+1]; ++start; } psl->size--; //有效数据-1}
2.9 顺序表查找
//2.9 顺序表查找int SeqListFind(SeqList * psl, SLDataTpye x){ //判断指针合法性 assert(psl); //从第一个节点开始查找,如果找到就返回该位置的值 size_t start = 0; while (start < psl->size) { if (x == psl->array[start]) { return start + 1; } start++; } //没有找到返回-1 return -1;}
2.10 顺序表在任意位置插入
//2.10 顺序表在pos位置插入void SeqListInsert(SeqList * psl, size_t pos, SLDataTpye x){ //判断指针合法性 assert(psl); //判断位置的合法性 assert(pos <= psl->size); //检查空间,如果满了,进行增容 CheckCapacity(psl); //end指向最后一个位置 size_t end = psl->size - 1; //将pos位置的节点分别向后移动一个位置 while (end >= pos - 1) { psl->array[end + 1] = psl->array[end]; --end; } psl->array[pos - 1] = x; //将x插入到第pos个位置 psl->size++; //有效数据+1}
2.11 顺序表删除任意位置的值
//2.11 顺序表删除pos位置的值void SeqListErase(SeqList * psl, size_t pos){ //判断指针合法性 assert(psl); //判断位置的合法性,不能小于等于0并且大于size assert(pos && pos < psl->size); size_t start = pos-1; //指向要删除的位置 while (start < psl->size-1) { psl->array[start] = psl->array[start + 1]; ++start; } psl->size--; //有效数据-1}
2.12 顺序表销毁
//2.12 顺序表销毁void SeqListDestory(SeqList * psl){ //判断指针合法性 assert(psl); //销毁顺序表 free(psl->array); psl->array = NULL; psl->size = 0; psl->capacity = 0;}
3. 工程化实现
创建三个文件:
- SeqList.h 用于存放库函数头文件和函数声明等
- SeqList.c 用于实现顺序表的增删查改功能
- test.c 用于接口测试
3.1 SeqList.h
#ifndef _SEQLIST_H_#define _SEQLIST_H_#include<stdio.h>#include<stdlib.h>#include<assert.h>#define N 100typedef int SLDataTpye;2.1.1顺序表的静态存储//typedef struct SeqList//{ // SLDataTpye arr[N]; //定长数组// size_t size; //有效数组的个数//}SL,SeqList;//2.1.2 顺序表的动态存储typedef struct SeqList{ SLDataTpye * array; //指向动态开辟的数组 size_t size; //有效数据的个数 size_t capacity; //容量空间的大小}SL, SeqList;//顺序表基本增删查改接口功能函数声明//顺序表的初始化void SeqListInit(SeqList * psl);//顺序表销毁void SeqListDestory(SeqList * psl);//顺序表打印void SeqListPrint(SeqList * psl);//检查空间,如果满了,进行增容void CheckCapacity(SeqList * psl);//顺序表尾插void SeqListPushBack(SeqList * psl,SLDataTpye x);//顺序表尾删void SeqListPopBack(SeqList * psl);//顺序表头插void SeqListPushFront(SeqList * psl, SLDataTpye x);//顺序表头删void SeqListPopFront(SeqList * psl);//顺序表查找int SeqListFind(SeqList * psl, SLDataTpye x);//顺序表在pos位置插入void SeqListInsert(SeqList * psl, size_t pos, SLDataTpye x);//顺序表删除pos位置的值void SeqListErase(SeqList * psl, size_t pos);#endif
3.2 SeqList.c
#include "SeqList.h"//2.2 顺序表初始化void SeqListInit(SeqList * psl){ //开辟的大小随机给值 psl->array = (SLDataTpye *)malloc(sizeof(SLDataTpye) * 4); if (psl->array == NULL) { printf("初始化失败\n"); exit(-1); } psl->size = 0; //有效数据为0 psl->capacity = 4; //容量空间大小为4}//2.3 顺序表增容//检查空间,如果满了,进行增容void CheckCapacity(SeqList * psl){ //有效数据与容量空间相等代表空间满了,需要增容! if (psl->size == psl->capacity) { //对顺序表容量扩大两倍 psl->capacity *= 2; //使用realloc扩展空间 psl->array = (SLDataTpye *)realloc(psl->array, sizeof(SLDataTpye)*psl->capacity); //判断下是否申请失败 if (psl->array == NULL) { printf("增容失败\n"); exit(-1); } }}//2.4 顺序表打印void SeqListPrint(SeqList * psl){ //判断指针合法性 assert(psl); //依次遍历顺序表每个节点,并打印节点中的元素值 for (size_t i = 0; i < psl->size; ++i) { printf("psl->array[%d]=%d\n", i, psl->array[i]); }}//2.5 顺序表尾插void SeqListPushBack(SeqList * psl, SLDataTpye x){ //判断指针合法性 assert(psl); //检查空间,如果满了,进行增容 CheckCapacity(psl); psl->array[psl->size] = x; //将数据x插入到线性表末尾 psl->size++; //有效数据加1}//2.6 顺序表尾删void SeqListPopBack(SeqList * psl){ //判断指针合法性 assert(psl); //有效数据-1 psl->size--;}//2.7 顺序表头插void SeqListPushFront(SeqList * psl, SLDataTpye x){ //判断指针合法性 assert(psl); //检查空间,如果满了,进行增容 CheckCapacity(psl); //头插从后往前拷贝 int end = psl->size - 1; //指向最后一个节点 while(end >= 0) { psl->array[end + 1] = psl->array[end]; //节点向后移动一个位置 --end; } psl->array[0] = x; //插入元素x psl->size++; //有效数据+1}//2.8 顺序表头删void SeqListPopFront(SeqList * psl){ //判断指针合法性 assert(psl); size_t start = 0; //指向第一个节点 while (start < psl->size-1) { psl->array[start] = psl->array[start+1]; ++start; } psl->size--; //有效数据-1}//2.9 顺序表查找int SeqListFind(SeqList * psl, SLDataTpye x){ //判断指针合法性 assert(psl); //从第一个节点开始查找,如果找到就返回该位置的值 size_t start = 0; while (start < psl->size) { if (x == psl->array[start]) { return start + 1; } start++; } //没有找到返回-1 return -1;}//2.10 顺序表在pos位置插入void SeqListInsert(SeqList * psl, size_t pos, SLDataTpye x){ //判断指针合法性 assert(psl); //检查空间,如果满了,进行增容 CheckCapacity(psl); //end指向最后一个位置 size_t end = psl->size - 1; //将pos位置的节点分别向后移动一个位置 while (end >= pos - 1) { psl->array[end + 1] = psl->array[end]; --end; } psl->array[pos - 1] = x; //将x插入到第pos个位置 psl->size++; //有效数据+1}//2.11 顺序表删除pos位置的值void SeqListErase(SeqList * psl, size_t pos){ //判断指针合法性 assert(psl); size_t start = pos-1; //指向要删除的位置 while (start < psl->size-1) { psl->array[start] = psl->array[start + 1]; ++start; } psl->size--; //有效数据-1}//2.12 顺序表销毁void SeqListDestory(SeqList * psl){ //判断指针合法性 assert(psl); //销毁顺序表 free(psl->array); psl->array = NULL; psl->size = 0; psl->capacity = 0;}
3.3 test.c
#include "SeqList.h"//测试头尾插入删除void TestSeqList1(){ //首先定义一个顺序表 SeqList s; //顺序表初始化接口测试 SeqListInit(&s); //顺序表尾插尾删接口测试 SeqListPushBack(&s, 1); SeqListPushBack(&s, 2); SeqListPushBack(&s, 3); SeqListPushBack(&s, 4); SeqListPushBack(&s, 5); SeqListPushBack(&s, 6); SeqListPushBack(&s, 7); SeqListPushBack(&s, 8); SeqListPopBack(&s); SeqListPrint(&s); //头插头删接口测试 //SeqListPushFront(&s, -1); //SeqListPrint(&s); SeqListPopFront(&s); SeqListPrint(&s); //查找接口测试 printf("%d\n",SeqListFind(&s, 4)); //任意位置插入接口测试 SeqListInsert(&s, 3, 30); SeqListPrint(&s); //任意位置删除 SeqListErase(&s, 3); SeqListPrint(&s); //顺序表销毁 SeqListDestory(&s);}int main(){ TestSeqList1(); return 0;}
发表评论
最新留言
不错!
[***.144.177.141]2025年04月02日 02时20分33秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
.NET微信网页开发之使用微信JS-SDK获取当前地理位置
2021-05-08
Android Studio在android Emulator中运行的项目黑屏
2021-05-08
Python写代码的时候为什么要注释?Sun因此被Oracle收购
2021-05-08
JAVA高并发集合详解
2021-05-08
解决Spirng注入时名称下的红色波浪线
2021-05-08
Mybatis总结(一)
2021-05-08