(数据结构)顺序表实现-增删查改
1.线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
2.顺序表
2.1概念及结构
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表就是数组,但是在数组的基础上,它还要数据是连续存储的,不能跳跃间隔。
#pragma once
#define N 100
typedef int SLDataType;//静态顺序表
typedef struct SeqList
{SLDataType arr[N];int size;//表示数组中存了多少个数据
}SL;//接口函数
//静态特点:满了就不让插入,很难确定给多少空间void SeqListInit(SL* ps);
//尾插
void SeqListPushBack(SL* ps, SLDataType x);
//尾删
void SeqListPopBack(SL* ps);
//头插
void SeqListPushFront(SL* ps, SLDataType x);
//头删
void SeqListPopFront(SL* ps);
静态顺序表不够灵活,我们接下来要学习的是动态顺序表;
学习动态顺序表前先说一个我犯过的错误,希望你们可以避一下
所以要传的是地址
顺序表一般可以分为:
1.静态顺序表:使用定长数组存储元素
2.动态顺序表:使用动态开辟的数组存储
3.顺序表的实现
3.1尾插:在顺序表末尾插入数据
实现步骤:
1.检查空间是否足够,不足需要继续开辟空间
1.1如果容量为0先分配一个初始容量,后面容量不够可以进行2倍扩容
1.2通过realloc开辟空间,将这个空间的地址赋值给一个定义的指针变量
1.3如果这个指针变量为NULL,即空间开辟失败进行相应的保护
1.4令顺序表的空间地址等于定义的指针变量,同时将新的容量赋值给原容量
2.空间足够
2.1将数据直接插入当前顺序表尾部
2.2++当前的有效数据个数
void SeqListPushBack(SL* ps, SLDataType x)
{//当空间为0或空间不够时,要开辟空间if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp=(SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror(realloc);exit(-1);//不可以写return -1;因为return没有终止掉程序}ps->a = tmp;ps->capacity = newcapacity;}//空间充足,直接插入数据即可ps->a[ps->size] = x;ps->size++;
}
如果对动态内存管理的函数不太了解可以看看我这一篇文章:
理清C语言中动态内存管理相关函数-CSDN博客
3.2尾删
直接减小size就行
void SeqListPopBack(SL* ps)
{//两种方式都可以/*if (ps->size > 0){ps->size--;}*/assert(ps->size > 0);ps->size--;
}
3.3头插
和尾插一样,先判断空间是否充足
为了方便我直接将扩容的功能封装成一个函数
void SeqListCheckcapacity(SL* ps)
{//当空间为0或空间不够时,要开辟空间if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror(realloc);exit(-1);//不可以写return -1;因为return没有终止掉程序}ps->a = tmp;ps->capacity = newcapacity;}
}
头插数据最简单的方法就是把现在数组的数据都往后挪一位,再把要插入的数据放在顺序表头部
void SeqListPushFront(SL* ps, SLDataType x)
{SeqListCheckcapacity(ps);//挪动数据int end = ps->size - 1;while (end >= 0){ps->a[end + 1] = ps->a[end];end--;}ps->a[0] = x;ps->size++;
}
3.4头删
从第二个数据开始往前挪,覆盖第一个数据,然后size-1
void SeqListPopFront(SL* ps)
{assert(ps->size > 0);int start = 0;while (start < ps->size-1){ps->a[start] = ps->a[start + 1];start++;}ps->size--;
}
3.5搜寻数据
遍历一遍顺序表即可
//找到了返回x位置的下标,没有找到返回-1
int SeqListFind(SL* ps, SLDataType x)
{int j = -1;for (int i = 0; i < ps->size; i++){if (ps->a[i] == x){j = i;}}return j;
}
3.6在指定位置插入数据
和头插的逻辑一样,也是将数据往后挪
void SeqListInsert(SL* ps, int pos, SLDataType x)
{assert(pos >= 0 || 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++;}
3.7删除指定位置的数据
//删除pos位置的数据
void SeqListErase(SL* ps, int pos)
{SeqListCheckcapacity(ps);int start = pos;while (start < ps->size - 1){ps->a[start] = ps->a[start + 1];start++;}ps->size--;
}
3.9销毁顺序表
void SeqListDestory(SL* ps)
{free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}
完整的工程:
main.c
#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"void TestList1();int main()
{TestList1();return 0;
}void TestList1()
{SL plist;SeqListInit(&plist);SeqListPushBack(&plist, 1);SeqListPushBack(&plist, 2);SeqListPushBack(&plist, 3);SeqListPushBack(&plist, 4);SeqListPushBack(&plist, 5);// ListPushFront(plist, 0);SeqListPrint(&plist);}
SeqList.h
#pragma once //防止重复包含#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int SLDataType;//动态顺序表
typedef struct SeqList
{SLDataType* a; //指向开辟数组的指针int size; //表示数组中存了多少个数据int capacity; //数组实际能存数据的空间容量是多大
}SL;//接口函数
//初始化
void SeqListInit(SL* ps);
//尾插
void SeqListPushBack(SL* ps, SLDataType x);
//尾删
void SeqListPopBack(SL* ps);
//头插
void SeqListPushFront(SL* ps, SLDataType x);
//头删
void SeqListPopFront(SL* ps);
//找到了返回x位置的下标,没有找到返回-1
int SeqListFind(SL* ps, SLDataType x);
//指定pos下标位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x);
//删除pos位置的数据
void SeqListErase(SL* ps, int pos);//打印顺序表
void SeqListPrint(SL* ps);
//销毁顺序表
void SeqListDestory(SL* ps);
//查看顺序表空余的容量
void SeqListCheckcapacity(SL* ps);
SeqList.c
#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"//初始化
void SeqListInit(SL* ps)
{ps->a = NULL;ps->size = ps->capacity = 0;
}void SeqListDestory(SL* ps)
{free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}void SeqListPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}void SeqListCheckcapacity(SL* ps)
{//当空间为0或空间不够时,要开辟空间if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL){//perror(realloc);exit(-1);//不可以写return -1;因为return没有终止掉程序}ps->a = tmp;ps->capacity = newcapacity;}
}//尾插:在顺序表末尾插入数据
void SeqListPushBack(SL* ps, SLDataType x)
{//当空间为0或空间不够时,要开辟空间if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL){//perror(realloc);exit(-1);//不可以写return -1;因为return没有终止掉程序}ps->a = tmp;ps->capacity = newcapacity;}//空间充足,直接插入数据即可ps->a[ps->size] = x;ps->size++;
}//尾删
void SeqListPopBack(SL* ps)
{//两种方式都可以/*if (ps->size > 0){ps->size--;}*/assert(ps->size > 0);ps->size--;
}//头插
void SeqListPushFront(SL* ps, SLDataType x)
{SeqListCheckcapacity(ps);//挪动数据int end = ps->size - 1;while (end >= 0){ps->a[end + 1] = ps->a[end];end--;}ps->a[0] = x;ps->size++;
}
//头删
void SeqListPopFront(SL* ps)
{assert(ps->size > 0);int start = 0;while (start < ps->size - 1){ps->a[start] = ps->a[start + 1];start++;}ps->size--;
}//找到了返回x位置的下标,没有找到返回-1
int SeqListFind(SL* ps, SLDataType x)
{int j = -1;for (int i = 0; i < ps->size; i++){if (ps->a[i] == x){j = i;}}return j;
}//指定pos下标位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x)
{assert(pos >= 0 || 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++;}//删除pos位置的数据
void SeqListErase(SL* ps, int pos)
{SeqListCheckcapacity(ps);int start = pos;while (start < ps->size - 1){ps->a[start] = ps->a[start + 1];start++;}ps->size--;
}
上一篇:
算法的时间复杂度和空间复杂度_算法复杂度 计算复杂度和存储复杂度-CSDN博客
下一篇:
(数据结构)链表-CSDN博客