顺序表的简单介绍与实现

#顺序表# 顺序表

一.顺序表简单的说明

  1. 本质:顺序表是通过开辟一个连续的空间来存储数据。即通过数组存储数据。

  2. 特性:2.1 中间/头部的插入删除,时间复杂度为O(N)

    ​ 2.2 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。

    ​ 2.3 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,

    ​ 再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

  3. 顺序表的存储结构

    ​ 3.1顺序表静态存储结构

           #define N 7
           typedef int SLdataType;
           typedef struct SeqList
           {
               SLdataType array[N];//创建一个定长数组;
               size_t size;//有效数据个数 ,即数组的下标   
           }SL;
    

    ​ 静态存储结构数组大小是定值,数据存满后无法扩容。#difine 将标识符 N 的值 定义为7

    ​ typedef 是类型重定义 就是给一个东西取个外号,让这个外号可以被编译器识别

    ​ 3.2顺序表动态存储结构

           typedef int SLdataType;
           typedef struct SeqList
           {
               SLdataType* arrayPointer;//记录数组地址,数组大小可以通过内存函数进行调整.
               size_t size;//有效数据个数 
               size_t capacity;//记录数组的最大容量,通过 与有效数据个数 进行比较 来 判断数组 是否 还有 空间 存储数据
           }SL;
    

二.动态顺序表的实现

1.动态顺序表的功能

​ 功能包含:1.顺序表的初始化,即

​ 1.1 在栈空间malloc一个数组并将地址信息保存与顺序表结构中。

​ 1.2 将有效数组个数 初始化为0.

​ 1.3 记录数组的最大容量,申请的数组空间所能存储的最大元素个数

​ 2.顺序表空间容量检查: 检查是否还有空间存储数据,不够时进行扩容。

​ 3.头插 :在下标为0的位置插入数据

​ 4.尾插 : 在下标为 size 的的地方插入数据(size是数组当前的有效数据个数,即当前存储了多少个数,

​ 下标是从0 开始所以比元素个数小1.)

​ 5.在指定下标位置插入数据

​ 6.头删:将下标为0的位置数据删除

​ 7.尾删:将下标为 size 的位置数据删除

​ 8.删除指定下标的数据

​ 9.查找数据所在下标

​ 10.修改指定位置的数据

​ 11.顺序表数数据打印

​ 12.顺序表销毁 : 在栈空间上储存的数据需要手动释放

2.顺序表初始化

void SLInit(SL*ps)
{
    assert(ps);
    ps->arrayPointer=(SLdataType*)malloc(sizeof(SLdataType)*4);//为数组申请4个元素空间
    if(ps->arrayPointer==NULL)
    {
         perror("arrayPointer malloc fail");
         return NULL;
    }
    ps->size=0;
    ps->capacity=4;
    
}                

3.顺序表的容量检查

void SLCapacityCheck(SL*ps)
{
    assert(ps);
    if(ps->size==ps->capacity)
    {
        SLdataType*p=(SLdataType*)realloc(ps->arrayPointer,sizeof(SLdataType)*ps->capacity*2);
        if(p==NULL)
        {
            perror("realloc fail");
            return ;
        }
        ps->arrayPointer=p;
        ps->capacity*=2;//最大容量重新记录
    }
   
}

4.头插

void SLPushFront(SL*ps,SLdataType x)
{
    assert(ps);//指针为空检查
    SLCapacityCheck(ps);//容量检查
    int i=0;
    int size=ps->size;
    for(i=size;i>0;i--)
    {
        ps->arrayPointer[i]= ps->arrayPointer[i-1];
    }
    ps->arrayPointer[0]=x;
    ps->size++;
}//时间复杂度为o(N)

5.尾插

void SLPushBack(SL*ps,SLdataType x)
{
    assert(ps);//指针为空检查
    SLCapacityCheck(ps);//容量检查
    ps->arrayPointer[ps->size]=x;
    ps->size++;
}//时间复杂度为o(1)

6.在pos位置之前插入数据

void SLInsert(SL*ps,int pos,SLdataType x)
{
    assert(ps);//指针为空检查
    SLCapacityCheck(ps);//容量检查 
    int moveDataNum=ps->size-1-pos+1;//ps->size是当前存储的元素个数,与下标一起进行计算须先自减1;
    int i=0;
    int size=ps->size;
    for(i=0;i<moveDataNum;i++)//挪数据循环,挪 moveDataNum 次
    {
        ps->arrayPointer[size-i]=ps->arrayPointer[size-i-1];
    }
    ps->arrayPointer[pos]=x;
    ps->size++;
}

7.头删

void SLPopFront(SL*ps)
{
    assert(ps);//指针为空检查
    assert(ps->size);//顺序表为空检查
    int i=0;
    int size=ps->size;
    for(i=1;i<size;i++)//挪数据循环,挪 size-1 次
    {
        ps->arrayPointer[i-1]=ps->arrayPointer[i];//数据覆盖,变相删除
    }
    ps->size--;
}

8.尾删

void SLPopback(SL*ps)
{
    assert(ps);//指针为空检查
    assert(ps->size);//顺序表为空检查
    int i=0;
    int size=ps->size;
    ps->size--;
}

9.删除指定下标的数据

void SLErase(SL*ps,int pos)
{
    assert(ps);//指针为空检查
    assert(ps->size);//顺序表为空检查 
    int moveDataNum=ps->size-1-pos+1;//ps->size是当前存储的元素个数,与下标一起进行计算须先自减1;
    int i=0;
    int size=ps->size;
    for(i=0;i<moveDataNum;i++)//挪数据循环,挪 moveDataNum 次
    {
        ps->arrayPointer[pos+i]=ps->arrayPointer[pos+i+1];
    }
    ps->size--;
}

10.查找数据所在下标

int SLFind(SL*ps,SLdataType x)
{
    assert(ps);//指针为空检查
    int i=0;
    for(i=0;i<ps->size;i++)
    {
        if(ps->arrayPointer[i]==x);
        //printf("第一个值为 %d 的数据下标为 %d\n",x,i);
        return i;
    }
    printf("未发现该数据\n");
    return -1;      
}

11.修改下标为pos位置的数据

void SLModify(SL*ps,int pos,SLdataType x)
{
    assert(ps);
    assert(pos<=ps->size||pos>=0)
    if(pos==ps->size)
    {
        SLPushBack(ps,x);//尾插
        return;
    }
    ps->arrayPointer[pos]=x;
}

12.顺序表数据打印

void SLprint(SL*ps)
{ 
    int i = 0;
    printf("\n          下标:>");
    for (i = 0; i < ps->size; i++)
    {
        printf(" %-3d ", i);
    }
    printf("\n          数据:>");
    for (i = 0; i < ps->size; i++)
    {
        printf(" %-3d ", ps->arrayPointer[i]);
    }
    printf("\n");
}

13.顺序表销毁

void SLDestory(SL*ps)
{
    assert(ps);
    free(ps->arrayPointer);
    ps->arrayPointer=NULL;
    ps->capacity=0;
    ps->size=0;
}

14代码汇总SL.c

#define _CRT_SECURE_NO_WARNINGS
#include"SL.h"
void SLInit(SL* ps)
{
    assert(ps);
    ps->arrayPointer = (SLdataType*)malloc(sizeof(SLdataType) * 4);//为数组申请4个元素空间
    if (ps->arrayPointer == NULL)
    {
        perror("arrayPointer malloc fail");
        return NULL;
    }
    ps->size = 0;
    ps->capacity = 4;

}
void SLCapacityCheck(SL* ps)
{
    assert(ps);
    if (ps->size == ps->capacity)
    {
        SLdataType* p = (SLdataType*)realloc(ps->arrayPointer, sizeof(SLdataType) * ps->capacity * 2);
        if (p == NULL)
        {
            perror("realloc fail");
            return;
        }
        ps->arrayPointer = p;
        ps->capacity *= 2;//最大容量重新记录
    }

}
// 4.头插
void SLPushFront(SL * ps, SLdataType x)
{
    assert(ps);//指针为空检查
    SLCapacityCheck(ps);//容量检查
    int i = 0;
    int size = ps->size;
    for (i = size; i > 0; i--)
    {
        ps->arrayPointer[i] = ps->arrayPointer[i - 1];
    }
    ps->arrayPointer[0] = x;
    ps->size++;
}//时间复杂度为o(N)


// 5.尾插
void SLPushBack(SL * ps, SLdataType x)
{
    assert(ps);//指针为空检查
    SLCapacityCheck(ps);//容量检查
    ps->arrayPointer[ps->size] = x;
    ps->size++;
}//时间复杂度为o(1)


// 6.在pos位置之前插入数据
void SLInsert(SL * ps, int pos, SLdataType x)
{
    assert(ps);//指针为空检查
    SLCapacityCheck(ps);//容量检查 
    int moveDataNum = ps->size - 1 - pos + 1;//ps->size是当前存储的元素个数,与下标一起进行计算须先自减1;
    int i = 0;
    int size = ps->size;
    for (i = 0; i < moveDataNum; i++)//挪数据循环,挪 moveDataNum 次
    {
        ps->arrayPointer[size - i] = ps->arrayPointer[size - i - 1];
    }
    ps->arrayPointer[pos] = x;
    ps->size++;
}


// 7.头删
int SLPopFront(SL * ps)
{
    assert(ps);//指针为空检查
    if (ps->size == 0)//顺序表为空检查
    {
        printf("\n顺序表已经删空了\n");
        return 1;
    }
    int i = 0;
    int size = ps->size;
    for (i = 1; i < size; i++)//挪数据循环,挪 size-1 次
    {
        ps->arrayPointer[i - 1] = ps->arrayPointer[i];//数据覆盖,变相删除
    }
    ps->size--;
    return 0;
}


// 8.尾删
int SLPopback(SL * ps)
{
    assert(ps);//指针为空检查
    if (ps->size == 0)//顺序表为空检查
    {
        printf("\n顺序表已经删空了\n");
        return 1;
    }
    int i = 0;
    int size = ps->size;
    ps->size--;
}


// 9.删除指定下标的数据
void SLErase(SL * ps, int pos)
{
    assert(ps);//指针为空检查
    assert(ps->size);//顺序表为空检查 
    int moveDataNum = ps->size - 1 - pos + 1;//ps->size是当前存储的元素个数,与下标一起进行计算须先自减1;
    int i = 0;
    int size = ps->size;
    for (i = 0; i < moveDataNum; i++)//挪数据循环,挪 moveDataNum 次
    {
        ps->arrayPointer[pos + i] = ps->arrayPointer[pos + i + 1];
    }
    ps->size--;
}


// 10.查找数据所在下标
int SLFind(SL * ps, SLdataType x)
{
    assert(ps);//指针为空检查
    int i = 0;
    for (i = 0; i < ps->size; i++)
    {
        if (ps->arrayPointer[i] == x)
        {
            printf("第一个值为 %d 的数据的下标为 %d\n", x, i);
            return i;
        }
    }
    printf("未发现该数据\n");
    return -1;
}


// 11.修改下标为pos位置的数据
void SLModify(SL * ps, int pos, SLdataType x)
{
    assert(ps);
    assert(pos <= ps->size || pos >= 0);
    if (pos == ps->size)
    {
          SLPushBack(ps, x);//尾插
          return;
    }
    ps->arrayPointer[pos] = x;
}




//12.顺序表数据打印
void SLprint(SL * ps)
{
    int i = 0;
    printf("\n          下标:>");
    for (i = 0; i < ps->size; i++)
    {
        printf(" %-3d ", i);
    }
    printf("\n          数据:>");
    for (i = 0; i < ps->size; i++)
    {
        printf(" %-3d ", ps->arrayPointer[i]);
    }
    printf("\n");
}


// 13.顺序表销毁
void SLDestory(SL * ps)
{
    assert(ps);
    free(ps->arrayPointer);
    ps->arrayPointer = NULL;
    ps->capacity = 0;
}

15测试代码text.c

#define _CRT_SECURE_NO_WARNINGS
#include"SL.h"
int main()
{
	SL s;
	SLInit(&s);
	SLPopFront(&s);
	SLPopback(&s);
	SLPushFront(&s, 1);
	SLPushFront(&s, 2);
	SLPushFront(&s, 3);
	SLPushFront(&s, 4);
	SLPushFront(&s, 5);
	SLPushBack(&s, 6);
	SLPushBack(&s, 7);
	SLPushBack(&s, 8);
	SLPushBack(&s, 9);
	SLPushBack(&s, 10);
	SLprint(&s);
	int pos = SLFind(&s, 10);
	SLModify(&s, pos, 20);
	SLModify(&s, --pos, 20);
	SLInsert(&s, pos, 100);
	SLErase(&s, 4);
	SLprint(&s);

	SLDestory(&s);
	return 0;
}

16运行截图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值