【数据结构与算法】数据结构初阶:详解顺序表和链表(二)
🔥个人主页:艾莉丝努力练剑
❄专栏传送门:《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题
🍉学习方向:C/C++方向
⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平
前言:本篇文章,我们继续介绍顺序表和链表相关的知识点,在初阶的数据结构与算法阶段,我们把知识点分成三部分,复杂度作为第一部分,顺序表和链表、栈和队列、二叉树为第二部分,排序为第二部分,我们之前已经介绍完了第一部分:算法复杂度,本文我们继续学习第二部分中的顺序表和链表部分内容啦。
目录
正文
二、顺序表(续)
(五)详解顺序表书写(续)
2、动态顺序表
(2)头插
(3)尾删
(4)头删
(5)随机位置插入
(6)随机位置删除
(7)查改:查找和修改
(8)写菜单
(9)复用
结尾
正文
二、顺序表(续)
(五)详解顺序表书写(续)
2、动态顺序表
上文给大家详解了尾插,上文受篇幅限制,剩余内容本文将继续介绍。
(2)头插
(1)SeqList.h
#ifdef __SEQLIST__H__
#define __SEQLIST__H__#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
//增强程序可维护性
typedef int SLTDataType;typedef struct SeqList
{SQDataType*a;int size; //有效数据的个数int capacity;//容量
}SL;
//增删查改等接口函数
void SeqListInit(SL*ps);
void SeqListPrint(SL*ps);
void SeqListPushBack(SL*ps,SLTDataType x);//尾插
void SeqListPushFront(SL*ps,SLTDataType x);//头插
void SeqListPopBack(SL*ps);//尾删
void SeqListPopFront(SL*ps);//头删
#endif
(2)SeqList.c
#include"SeqList.h"void SeqListInit(SL*ps)
{
//粗暴一点,先置为空,再改成0,然后capacity也改为0ps->a = NULL;ps->size = 0;ps->capacity = 0;
//当然我们也可以直接malloc
}void SeqListCheckCapacity(SL*ps)
{//满了就要扩容if(ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;SLTDataType* tmp = realloc(ps->a, newcapacity * sizeof(SLTDataType));if(tmp == NULL){printf("realloc fail\n");exit(-1);}else{ps->a = tmp;ps->capacity = newcapacity;}}
}
//头插 尾插 头删 尾删
void SeqListPushBack(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}
void SeqListPushFront(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);//1、初始条件//2、结束条件//3、迭代过程int end = ps->size - 1;while(end >= 0){ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;
}
void SeqListPopBack(SL*ps);
void SeqListPopFront(SL*ps);
//测试能不能打印出来
void SeqListPrint(SL*ps)
{for(int i = 0;i < ps->size;++i){printf("%d ",ps->a[i]);}printf("\n");
}
(3)test.c
#include"SeqList.h"void TestSeqList2()
{SL sl;SeqListInit(&sl);SeqListPushFront(&sl,1);SeqListPushFront(&sl,2);SeqListPushFront(&sl,3);SeqListPushFront(&sl,4);SeqListPushFront(&sl,5);SeqListPushFront(&sl,6);…… SeqListPrint(&sl);
}int main()
{TestSeqList2();return 0;
}
(3)尾删
(1)SeqList.h
#ifdef __SEQLIST__H__
#define __SEQLIST__H__#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
//增强程序可维护性
typedef int SQDataType;typedef struct SeqList
{SQDataType*a;int size; //有效数据的个数int capacity;//容量
}SL;
//增删查改等接口函数
void SeqListInit(SL*ps);
void SeqListPrint(SL*ps);
void SeqListPushBack(SL*ps,SQDataType x);//尾插
void SeqListPushFront(SL*ps,SQDataType x);//头插
void SeqListPopBack(SL*ps);//尾删
void SeqListPopFront(SL*ps);//头删
#endif
(2)SeqList.c
#include"SeqList.h"void SeqListInit(SL*ps)
{
//粗暴一点,先置为空,再改成0,然后capacity也改为0ps->a = NULL;ps->size = 0;ps->capacity = 0;
//当然我们也可以直接malloc
}void SeqListCheckCapacity(SL*ps)
{//满了就要扩容if(ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;SLTDataType* tmp = realloc(ps->a, newcapacity * sizeof(SLTDataType));if(tmp == NULL){printf("realloc fail\n");exit(-1);}else{ps->a = tmp;ps->capacity = newcapacity;}}
}
//头插 尾插 头删 尾删
void SeqListPushBack(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}
void SeqListPushFront(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);//1、初始条件//2、结束条件//3、迭代过程int end = ps->size - 1;while(end >= 0){ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;
}
void SeqListPopBack(SL*ps)
{//粗暴一点直接assertassert(ps->size > 0);ps->a[ps->size - 1] = 0;//这句代码加上也可以,没有也不影响ps->size--;
}
void SeqListPopFront(SL*ps);
//测试能不能打印出来
void SeqListPrint(SL*ps)
{for(int i = 0;i < ps->size;++i){printf("%d ",ps->a[i]);}printf("\n");
}
(3)test.c
#include"SeqList.h"void TestSeqList3()
{SL sl;SeqListInit(&sl);SeqListPopBack(&sl,1);SeqListPopBack(&sl,2);SeqListPopBack(&sl,3);SeqListPopBack(&sl,4);SeqListPopBack(&sl,5);SeqListPopBack(&sl,6);SeqListPopBack(&sl);SeqListPrint(&sl);
}int main()
{TestSeqList3();return 0;
}
(4)头删
(1)SeqList.h
#ifdef __SEQLIST__H__
#define __SEQLIST__H__#include<stdio.h>
#include<string.h>
#include<assert.h>
//增强程序可维护性
typedef int SLTDataType;typedef struct SeqList
{SQDataType*a;int size; //有效数据的个数int capacity;//容量
}SL;
//增删查改等接口函数
void SeqListInit(SL*ps);
void SeqListPrint(SL*ps);
void SeqListPushBack(SL*ps,SLTDataType x);//尾插
void SeqListPushFront(SL*ps,SLTDataType x);//头插
void SeqListPopBack(SL*ps);//尾删
void SeqListPopFront(SL*ps);//头删
#endif
(2)SeqList.c
#include"SeqList.h"void SeqListInit(SL*ps)
{
//粗暴一点,先置为空,再改成0,然后capacity也改为0ps->a = NULL;ps->size = 0;ps->capacity = 0;
//当然我们也可以直接malloc
}void SeqListCheckCapacity(SL*ps)
{//满了就要扩容if(ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;SLTDataType* tmp = realloc(ps->a, newcapacity * sizeof(SLTDataType));if(tmp == NULL){printf("realloc fail\n");exit(-1);}else{ps->a = tmp;ps->capacity = newcapacity;}}
}
//头插 尾插 头删 尾删
//尾插
void SeqListPushBack(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}
//头插
void SeqListPushFront(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);//1、初始条件//2、结束条件//3、迭代过程int end = ps->size - 1;while(end >= 0){ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;
}
//尾删
void SeqListPopBack(SL*ps)
{//粗暴一点直接assertassert(ps->size > 0);ps->a[ps->size - 1] = 0;//这句代码加上也可以,没有也不影响ps->size--;
}
//头删
void SeqListPopFront(SL*ps)
{assert(ps->size > 0);int start = 1;while(start < ps->size){ps->a[start - 1] = ps->a[start];++start;}ps->size--;
}
//测试能不能打印出来
void SeqListPrint(SL*ps)
{for(int i = 0;i < ps->size;++i){printf("%d ",ps->a[i]);}printf("\n");
}
(3)test.c
#include"SeqList.h"void TestSeqList4()
{SL sl;SeqListInit(&sl);SeqListPushFront(&sl,1);SeqListPushFront(&sl,2);SeqListPushFront(&sl,3);SeqListPushFront(&sl,4);SeqListPushFront(&sl,5);SeqListPushFront(&sl,6);SeqListPrint(&sl);SeqListPopBack(&sl);SeqListPopBack(&sl);SeqListPopBack(&sl);SeqListPrint(&sl);SeqListPopFront(&sl);SeqListPrint(&sl);
}int main()
{TestSeqList4();return 0;
}
(5)随机位置插入
(1)SeqList.h
#ifdef __SEQLIST__H__
#define __SEQLIST__H__#include<stdio.h>
#include<string.h>
#include<assert.h>
//增强程序可维护性
typedef int SLTDataType;typedef struct SeqList
{SQDataType*a;int size; //有效数据的个数int capacity;//容量
}SL;
//增删查改等接口函数
void SeqListInit(SL*ps);
void SeqListPrint(SL*ps);
void SeqListPushBack(SL*ps,SLTDataType x);//尾插
void SeqListPushFront(SL*ps,SLTDataType x);//头插
void SeqListPopBack(SL*ps);//尾删
void SeqListPopFront(SL*ps);//头删
void SeqListInsert(SL*ps,int pos,SLTDataType x);//随机插入
void SeqListErase(SL*ps,int pos);//随机删除
#endif
(2)SeqList.c
#include"SeqList.h"void SeqListInit(SL*ps)
{
//粗暴一点,先置为空,再改成0,然后capacity也改为0ps->a = NULL;ps->size = 0;ps->capacity = 0;
//当然我们也可以直接malloc
}void SeqListCheckCapacity(SL*ps)
{//满了就要扩容if(ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;SLTDataType* tmp = realloc(ps->a, newcapacity * sizeof(SLTDataType));if(tmp == NULL){printf("realloc fail\n");exit(-1);}else{ps->a = tmp;ps->capacity = newcapacity;}}
}
//头插 尾插 头删 尾删
//尾插
void SeqListPushBack(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}
//头插
void SeqListPushFront(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);//1、初始条件//2、结束条件//3、迭代过程int end = ps->size - 1;while(end >= 0){ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;
}
//尾删
void SeqListPopBack(SL*ps)
{//粗暴一点直接assertassert(ps->size > 0);ps->a[ps->size - 1] = 0;//这句代码加上也可以,没有也不影响ps->size--;
}
//头删
void SeqListPopFront(SL*ps)
{assert(ps->size > 0);int start = 1;while(start < ps->size){ps->a[start - 1] = ps->a[start];++start;}ps->size--;
}
//随机插入
void SeqListInsert(SL*ps,int pos,SLTDataType x)
{assert(ps->size > 0);SeqListCheckCapacity(ps);int end = ps->size - 1;while(end >= pos){ps->a[end + 1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}
//随机删除
void SeqListErase(SL*ps,int pos);
//测试能不能打印出来
void SeqListPrint(SL*ps)
{for(int i = 0;i < ps->size;++i){printf("%d ",ps->a[i]);}printf("\n");
}
这个就是我们写的这个随机插入的接口。
(3)test.c
#include"SeqList.h"void TestSeqList5()
{SL sl;SeqListInit(&sl);SeqListPushFront(&sl,1);SeqListPushFront(&sl,2);SeqListPushFront(&sl,3);SeqListPushFront(&sl,4);SeqListPushFront(&sl,5);SeqListPushFront(&sl,6);SeqListPrint(&sl);SeqListInsert(&sl,1,20);SeqListPrint(&sl);
}int main()
{TestSeqList5();return 0;
}
(6)随机位置删除
(1)SeqList.h
#ifdef __SEQLIST__H__
#define __SEQLIST__H__#include<stdio.h>
#include<string.h>
#include<assert.h>
//增强程序可维护性
typedef int SLTDataType;typedef struct SeqList
{SQDataType*a;int size; //有效数据的个数int capacity;//容量
}SL;
//增删查改等接口函数
void SeqListInit(SL*ps);
void SeqListPrint(SL*ps);
void SeqListDestory(SL*ps);//销毁
void SeqListPushBack(SL*ps,SLTDataType x);//尾插
void SeqListPushFront(SL*ps,SLTDataType x);//头插
void SeqListPopBack(SL*ps);//尾删
void SeqListPopFront(SL*ps);//头删
void SeqListInsert(SL*ps,int pos,SLTDataType x);//随机插入
void SeqListErase(SL*ps,int pos);//随机删除
#endif
(2)SeqList.c
#include"SeqList.h"void SeqListInit(SL*ps)
{
//粗暴一点,先置为空,再改成0,然后capacity也改为0ps->a = NULL;ps->size = 0;ps->capacity = 0;
//当然我们也可以直接malloc
}void SeqListDestory(SL*ps)
{free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}void SeqListCheckCapacity(SL*ps)
{//满了就要扩容if(ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;SLTDataType* tmp = realloc(ps->a, newcapacity * sizeof(SLTDataType));if(tmp == NULL){printf("realloc fail\n");exit(-1);}else{ps->a = tmp;ps->capacity = newcapacity;}}
}
//头插 尾插 头删 尾删
//尾插
void SeqListPushBack(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}
//头插
void SeqListPushFront(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);//1、初始条件//2、结束条件//3、迭代过程int end = ps->size - 1;while(end >= 0){ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;
}
//尾删
void SeqListPopBack(SL*ps)
{//粗暴一点直接assertassert(ps->size > 0);ps->a[ps->size - 1] = 0;//这句代码加上也可以,没有也不影响ps->size--;
}
//头删
void SeqListPopFront(SL*ps)
{assert(ps->size > 0);int start = 1;while(start < ps->size){ps->a[start - 1] = ps->a[start];++start;}ps->size--;
}
//随机位置插入
void SeqListInsert(SL*ps,int pos,SLTDataType x)
{assert(ps->size > 0);SeqListCheckCapacity(ps);int end = ps->size - 1;while(end >= pos){ps->a[end + 1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}
//随机位置删除
void SeqListErase(SL*ps,int pos)
{assert(pos < ps->size)int start = pos + 1;while(start < ps->size){ps->a[start - 1] = ps->a[start];++start;}ps->size--;
}
//测试能不能打印出来
void SeqListPrint(SL*ps)
{for(int i = 0;i < ps->size;++i){printf("%d ",ps->a[i]);}printf("\n");
}
(3)test.c
#include"SeqList.h"void TestSeqList6()
{SL sl;SeqListInit(&sl);SeqListPushFront(&sl,1);SeqListPushFront(&sl,2);SeqListPushFront(&sl,3);SeqListPushFront(&sl,4);SeqListPushFront(&sl,5);SeqListPushFront(&sl,6);SeqListPrint(&sl);SeqListInsert(&sl,1,20);SeqListPrint(&sl);SeqListErase(&sl,1);SeqListPrint(&sl);SeqListDestory(&sl);
}int main()
{TestSeqList6();return 0;
}
注意:
1、删除数据之后空间还是在的,因为顺序表是连续的,只是把后面的数据挤到一起,只删数据,不删空间;
2、start用前置++和后置++都是一样的,前置会高一点点,但是现在的计算机的算力非常强大,可以忽略不计,以后遇到前置和后置有区别的地方主包会讲的。
我们动态申请的内存要还给操作系统(销毁),数据没了,空间还在,只是还给操作系统了。我们的六个接口虽然是分开写的,但实际上它们是写在同一个文件里面的,因此博主就只在【随机位置插入】写了void SeqListDestory(SL*ps);。
讲到这里,我们顺序表的增删查改接口函数已经讲完了增删了。
(7)查改:查找和修改
(1)SeqList.h
#ifdef __SEQLIST__H__
#define __SEQLIST__H__#include<stdio.h>
#include<string.h>
#include<assert.h>
//增强程序可维护性
typedef int SLTDataType;typedef struct SeqList
{SLTDataType*a;int size; //有效数据的个数int capacity;//容量
}SL;
//增删查改等接口函数
void SeqListInit(SL*ps);
void SeqListPrint(SL*ps);
void SeqListDestory(SL*ps);//销毁
void SeqListPushBack(SL*ps,SLTDataType x);//尾插
void SeqListPushFront(SL*ps,SLTDataType x);//头插
void SeqListPopBack(SL*ps);//尾删
void SeqListPopFront(SL*ps);//头删
void SeqListInsert(SL*ps,int pos,SLTDataType x);//随机插入
void SeqListErase(SL*ps,int pos);//随机删除
int SeqListFind(SL*ps,SLTDataType x);// 查找
void SeqListModity((SL*ps,int pos,SLTDataType x);//修改
#endif
(2)SeqList.c
#include"SeqList.h"void SeqListInit(SL*ps)
{
//粗暴一点,先置为空,再改成0,然后capacity也改为0ps->a = NULL;ps->size = 0;ps->capacity = 0;
//当然我们也可以直接malloc
}void SeqListDestory(SL*ps)
{free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}void SeqListCheckCapacity(SL*ps)
{//满了就要扩容if(ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;SLTDataType* tmp = realloc(ps->a, newcapacity * sizeof(SLTDataType));if(tmp == NULL){printf("realloc fail\n");exit(-1);}else{ps->a = tmp;ps->capacity = newcapacity;}}
}
//头插 尾插 头删 尾删
//尾插
void SeqListPushBack(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}
//头插
void SeqListPushFront(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);//1、初始条件//2、结束条件//3、迭代过程int end = ps->size - 1;while(end >= 0){ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;
}
//尾删
void SeqListPopBack(SL*ps)
{//粗暴一点直接assertassert(ps->size > 0);ps->a[ps->size - 1] = 0;//这句代码加上也可以,没有也不影响ps->size--;
}
//头删
void SeqListPopFront(SL*ps)
{assert(ps->size > 0);int start = 1;while(start < ps->size){ps->a[start - 1] = ps->a[start];++start;}ps->size--;
}
//随机位置插入
void SeqListInsert(SL*ps,int pos,SLTDataType x)
{assert(ps->size > 0);SeqListCheckCapacity(ps);int end = ps->size - 1;while(end >= pos){ps->a[end + 1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}
//随机位置删除
void SeqListErase(SL*ps,int pos)
{assert(pos < ps->size)int start = pos + 1;while(start < ps->size){ps->a[start - 1] = ps->a[start];++start;}ps->size--;
}
//查找
int SeqListFind(SL*ps,SLTDataType x)
{//如果查找的地方是有序的,可以用二分查找,但是现在不是有序,就不能写二分查找for(int i = 0;i < ps->size;++i){if(ps->a[i] == x){return i;}}return -1;
}
//修改
void SeqListModity((SL*ps,int pos,SLTDataType x)
{assert(pos < ps->size);ps->a[pos] = x;
}
//测试能不能打印出来
void SeqListPrint(SL*ps)
{for(int i = 0;i < ps->size;++i){printf("%d ",ps->a[i]);}printf("\n");
}
(3)test.c
#include"SeqList.h"void TestSeqList6()
{SL sl;SeqListInit(&sl);SeqListPushFront(&sl,1);SeqListPushFront(&sl,2);SeqListPushFront(&sl,3);SeqListPushFront(&sl,4);SeqListPushFront(&sl,5);SeqListPushFront(&sl,6);SeqListPrint(&sl);SeqListInsert(&sl,1,20);SeqListPrint(&sl);SeqListErase(&sl,1);SeqListPrint(&sl);SeqListDestory(&sl);
}int main()
{TestSeqList6();return 0;
}
如果我们还要实现一些接口,比如说空、满、size啊这些接口,uu们感兴趣可以自己加。
我们学完了这几个接口,是时候做点什么练练手了!我们来写一个【菜单】——
(8)写菜单
提醒:
(1)SeqList.h
#ifdef __SEQLIST__H__
#define __SEQLIST__H__#include<stdio.h>
#include<string.h>
#include<assert.h>
//增强程序可维护性
typedef int SLTDataType;//ContactInfo
typedef int SLTDataType;typedef struct SeqList
{SLTDataType*a;int size; //有效数据的个数int capacity;//容量
}SL;
//增删查改等接口函数
void SeqListInit(SL*ps);
void SeqListPrint(SL*ps);
void SeqListDestory(SL*ps);//销毁
void SeqListPushBack(SL*ps,SLTDataType x);//尾插
void SeqListPushFront(SL*ps,SLTDataType x);//头插
void SeqListPopBack(SL*ps);//尾删
void SeqListPopFront(SL*ps);//头删
void SeqListInsert(SL*ps,int pos,SLTDataType x);//随机插入
void SeqListErase(SL*ps,int pos);//随机删除
int SeqListFind(SL*ps,SLTDataType x);// 查找
void SeqListModity((SL*ps,int pos,SLTDataType x);//修改
#endif
(2)SeqList.c
#include"SeqList.h"void SeqListInit(SL*ps)
{
//粗暴一点,先置为空,再改成0,然后capacity也改为0ps->a = NULL;ps->size = 0;ps->capacity = 0;
//当然我们也可以直接malloc
}void SeqListDestory(SL*ps)
{free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}void SeqListCheckCapacity(SL*ps)
{//满了就要扩容if(ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;SLTDataType* tmp = realloc(ps->a, newcapacity * sizeof(SLTDataType));if(tmp == NULL){printf("realloc fail\n");exit(-1);}else{ps->a = tmp;ps->capacity = newcapacity;}}
}
//头插 尾插 头删 尾删
//尾插
void SeqListPushBack(SL*ps,SLTDataType x);
{SeqListCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;
}
//头插
void SeqListPushFront(SL*ps,SLTDataType x)
{SeqListCheckCapacity(ps);//1、初始条件//2、结束条件//3、迭代过程int end = ps->size - 1;while(end >= 0){ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;
}
//尾删
void SeqListPopBack(SL*ps)
{//粗暴一点直接assertassert(ps->size > 0);ps->a[ps->size - 1] = 0;//这句代码加上也可以,没有也不影响ps->size--;
}
//头删
void SeqListPopFront(SL*ps)
{assert(ps->size > 0);int start = 1;while(start < ps->size){ps->a[start - 1] = ps->a[start];++start;}ps->size--;
}
//随机位置插入
void SeqListInsert(SL*ps,int pos,SLTDataType x)
{assert(ps->size > 0);SeqListCheckCapacity(ps);int end = ps->size - 1;while(end >= pos){ps->a[end + 1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}
//随机位置删除
void SeqListErase(SL*ps,int pos)
{assert(pos < ps->size)int start = pos + 1;while(start < ps->size){ps->a[start - 1] = ps->a[start];++start;}ps->size--;
}
//查找
int SeqListFind(SL*ps,SLTDataType x)
{//如果查找的地方是有序的,可以用二分查找,但是现在不是有序,就不能写二分查找for(int i = 0;i < ps->size;++i){if(ps->a[i] == x){return i;}}return -1;
}
//修改
void SeqListModity((SL*ps,int pos,SLTDataType x)
{assert(pos < ps->size);ps->a[pos] = x;
}
//测试能不能打印出来
void SeqListPrint(SL*ps)
{for(int i = 0;i < ps->size;++i){printf("%d ",ps->a[i]);}printf("\n");
}
(3)test.c
#include"SeqList.h"void TestSeqList6()
{SL sl;SeqListInit(&sl);SeqListPushFront(&sl,1);SeqListPushFront(&sl,2);SeqListPushFront(&sl,3);SeqListPushFront(&sl,4);SeqListPushFront(&sl,5);SeqListPushFront(&sl,6);SeqListPrint(&sl);SeqListInsert(&sl,1,20);SeqListPrint(&sl);SeqListErase(&sl,1);SeqListPrint(&sl);SeqListDestory(&sl);
}void menu()
{printf("******************************\n");printf("1.尾插数据, 2.头插数据\n");printf("3.尾删数据, 4.头删数据\n");printf("5.打印数据,-1.退出\n");printf("******************************\n");printf("请输入你的操作选项:");
}int main()
{SL s:SeqListInit(&s):int option = 0;int x = 0;while(option != -1){menu();scanf("%d",&option);switch(option){case 1:printf("请输入你要插入的数据,以-1为结束\n");do{scanf("%d",x);if(x != -1){SeqListPushBack(&s,x);}}while((x != -1);break;//中间几个选项类似case 2:break;case 3:break;case 4:break;case 5:SqeListPrint(&s);break;default:break;}}SeqListDestory(&s);return 0;
}
我们不要直接写菜单,要测试到所有的接口都没问题了,再来写,因为一个接口出问题了,就可能浪费大把时间,自己把自己难住了。因此我们先写接口,再写菜单。
(9)复用
这里我们我们展示一下复用的强大之处,复用一般是指“复制代码”。
(1)SeqList.h
#pragma once
//#ifdef __SEQLIST__H__
//#define __SEQLIST__H__#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
//增强程序可维护性
typedef int SLTDataType;typedef struct SeqList
{SLTDataType* a;int size; //有效数据的个数int capacity;//容量
}SL;
//增删查改等接口函数
void SeqListInit(SL* ps);
void SeqListPrint(SL* ps);
void SeqListDestory(SL* ps);//销毁
void SeqListPushBack(SL* ps, SLTDataType x);//尾插
void SeqListPushFront(SL* ps, SLTDataType x);//头插
void SeqListPopBack(SL* ps);//尾删
void SeqListPopFront(SL* ps);//头删
void SeqListInsert(SL* ps, int pos, SLTDataType x);//随机插入
void SeqListErase(SL* ps, int pos);//随机删除
int SeqListFind(SL* ps, SLTDataType x);// 查找
void SeqListModity(SL* ps, int pos, SLTDataType x);//修改
/*#endif */
(2)SeqList.c
#define _CRT_SECURE_NO_WARNINGS 1#include"SeqList.h"void SeqListInit(SL* ps)
{//粗暴一点,先置为空,再改成0,然后capacity也改为0ps->a = NULL;ps->size = 0;ps->capacity = 0;//当然我们也可以直接malloc
}void SeqListDestory(SL* ps)
{free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}void SeqListCheckCapacity(SL* ps)
{//满了就要扩容if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLTDataType* tmp = realloc(ps->a, newcapacity * sizeof(SLTDataType));if (tmp == NULL){printf("realloc fail\n");exit(-1);}else{ps->a = tmp;ps->capacity = newcapacity;}}
}
//头插 尾插 头删 尾删
//尾插
void SeqListPushBack(SL* ps, SLTDataType x)
{//SeqListCheckCapacity(ps);//ps->a[ps->size] = x;//ps->size++;SeqListInsert(ps, ps->size, x);
}
//头插
void SeqListPushFront(SL* ps, SLTDataType x)
{//SeqListCheckCapacity(ps);1、初始条件2、结束条件3、迭代过程//int end = ps->size - 1;//while (end >= 0)//{// ps->a[end + 1] = ps->a[end];// --end;//}//ps->a[0] = x;//ps->size++;//SeqListCheckCapacity(ps);SeqListInsert(ps, 0, x);
}
//尾删
void SeqListPopBack(SL* ps)
{粗暴一点直接assert//assert(ps->size > 0);//ps->a[ps->size - 1] = 0;//这句代码加上也可以,没有也不影响//ps->size--;SeqListErase(ps, ps->size - 1);
}
//头删
void SeqListPopFront(SL* ps)
{/* assert(ps->size > 0);int start = 1;while (start < ps->size){ps->a[start - 1] = ps->a[start];++start;}ps->size--;*/SeqListErase(ps, 0);
}
//随机位置插入
void SeqListInsert(SL* ps, int pos, SLTDataType x)
{assert(pos <= ps->size);SeqListCheckCapacity(ps);int end = ps->size - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}
//随机位置删除
void SeqListErase(SL* ps, int pos)
{assert(pos < ps->size);int start = pos + 1;while (start < ps->size){ps->a[start - 1] = ps->a[start];++start;}ps->size--;
}
//查找
int SeqListFind(SL* ps, SLTDataType x)
{//如果查找的地方是有序的,可以用二分查找,但是现在不是有序,就不能写二分查找for (int i = 0; i < ps->size; ++i){if (ps->a[i] == x){return i;}}return -1;
}
//修改
void SeqListModity(SL* ps, int pos, SLTDataType x)
{assert(pos < ps->size);ps->a[pos] = x;
}
//测试能不能打印出来
void SeqListPrint(SL* ps)
{for (int i = 0; i < ps->size; ++i){printf("%d ", ps->a[i]);}printf("\n");
}
(3)test.c
#define _CRT_SECURE_NO_WARNINGS 1#include"SeqList.h"void TestSeqList6()
{SL sl;SeqListInit(&sl);SeqListPushFront(&sl, 1);SeqListPushFront(&sl, 2);SeqListPushFront(&sl, 3);SeqListPushFront(&sl, 4);SeqListPushFront(&sl, 5);SeqListPushFront(&sl, 6);SeqListPrint(&sl);SeqListInsert(&sl, 1, 20);SeqListPrint(&sl);SeqListErase(&sl, 1);SeqListPrint(&sl);SeqListDestory(&sl);
}int main()
{TestSeqList6();return 0;
}
是不是很爽?这就是复用大王的实力!
结尾
往期回顾:
【数据结构与算法】数据结构初阶:详解顺序表和链表(一)
【数据结构】详解算法复杂度:时间复杂度和空间复杂度
本期内容需要回顾的C语言知识放在下面了(指针博主写了6篇,列出来有水字数嫌疑了,就只放指针第六篇的网址,博主在指针(六)把指针部分的前五篇的网址都放在【往期回顾】了,点击【传送门】就可以看了),大家如果对前面部分的知识点印象不深,可以去看看:
【动态内存管理】深入详解:malloc和free、calloc和realloc、常见的动态内存的错误、柔性数组、总结C/C++中程序内存区域划分
【自定义类型:结构体】:类型声明、结构体变量的创建与初始化、内存对齐、传参、位段
C语言指针深入详解(六):sizeof和strlen的对比,【题解】数组和指针笔试题解析、指针运算笔试题解析
【深入详解】函数栈帧的创建与销毁:寄存器、压栈、出栈、调用、回收空间
结语:本篇文章到这里就结束了,对数据结构的顺序表知识感兴趣的友友们可以在评论区留言,博主创作时可能存在笔误,或者知识点不严谨的地方,大家多担待,有什么错误欢迎在评论区斧正,感谢友友们的关注和支持!