ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

详解动态顺序表

2026/9/30 19:22:37 拓冰建站 浏览量
详解动态顺序表

𝙉𝙞𝙘𝙚!!👏🏻‧✧̣̥̇‧✦👏🏻‧✧̣̥̇‧✦ 👏🏻‧✧̣̥̇:Solitary-walk

      ⸝⋆   ━━━┓
     - 个性标签 - :来于“云”的“羽球人”。 Talk is cheap. Show me the code
┗━━━━━━━  ➴ ⷯ

本人座右铭 :   欲达高峰,必忍其痛;欲戴王冠,必承其重。

👑💎💎👑💎💎👑 
💎💎💎自💎💎💎
💎💎💎信💎💎💎
👑💎💎 💎💎👑    希望在看完我的此篇博客后可以对你有帮助哟

👑👑💎💎💎👑👑   此外,希望各位大佬们在看完后,可以互赞互关一下,看到必回
👑👑👑💎👑👑👑     

目录 

一:顺序表的介绍

  1:顺序表定义

    顺序表是线性表的一种,首先顺序表是是用一段物理地址连续的存储单元依次存储数据元素的线性结构,多数情况下借助数组来存储

二:动态顺序表和静态顺序表区别

  1:静态顺序表:

   静态就体现了静态顺序表的特征,数组的空间大小是固定的

//静态顺序表的结构体的构造
#define N 10
typedef int SLDataTYpe;//便于实现各种数据类型,一改全改typedef struct SeqList
{SLDataTYpe a[N];int size;//记录数据有效的个数
}SL;
 2:动态顺序表

 动态体现了是一个不断变化的过程,可以频繁进行扩容

//动态顺序表
typedef int SLDataType;//便于实现各种数据类型,一改全改
typedef struct SeqList
{SLDataType* a;int size;//记录数据有效的个数int capacity;//空间空间的容量
}SL;
3:二者区别

静态顺序表:以定长数组的形式存储

动态顺序表:以动态开辟的数组进行存储

本质上二者没有优劣之分,只不过动态顺序表多了一个成员:空间容量

三:动态顺序表的接口实现

1. 初始化

为了避免不必要的麻烦,我们在初始化的时候直接就对数组进行动态开辟

void SLInit(SL* psl)
{assert(psl);psl->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);//先为数组开4 个空间if (psl->a == NULL)  //空间检查{printf("perror malloc\n");return;}// 开辟成功psl->size = 0;psl->capacity = 4;
}
2.销毁
void SLDestroy(SL* psl)
{assert(psl);free(psl->a);psl->a = NULL;psl->capacity = 0;psl->size = 0;
}
3.尾插

分析:首先我们在尾插之前需要先进行空间容量检查

 

void SLPushBack(SL* psl, SLDataType x)
{assert(psl);//先判断空间是否足够CheckCapacity(psl);//之后直接尾插psl->a[psl->size] = x;psl->size++;
}
4.头插

分析:

1)空间容量的检查

2) 数据的挪动:从后往前挪动(避免数据覆盖)

3)下标边界值的确定

 

void SLPushFront(SL* psl, SLDataType x)
{assert(psl);//先判断空间是否足够CheckCapacity(psl);挪动数据:从后往前挪动数据 注意边界的问题int end = psl->size - 1;while (end >= 0){psl->a[end + 1] = psl->a[end];end--;}psl->a[0] = x;psl->size++;
}
 5.尾删

先进行判空,其次直接size--

void SLPopBack(SL* psl)
{assert(psl);//判断是否为空   温柔  / 暴力判断if (psl->size == 0){printf("为空 \n");return;}psl->size--;}
6.头删

先进行判空

其次挪动数据:从前往后挪动

下标边界的确定

 

void SLPopFront(SL* psl)
{assert(psl);assert(psl->size);//判空// 挪动数据:从前往后挪数据int start = 0;while (start < psl->size - 1){psl->a[start] = psl->a[start + 1];start++;}//SLEarse(psl, 0);//注意:别忘了size--psl->size--;}
7.任意位置的插入

1)空间容量检查

2)pos这个位置是否合法

3)数据挪动:和头插一样

 

void SLInsert(SL* psl, int pos, SLDataType x)
{assert(psl);// 先进行空间判断,以及位置的合法CheckCapacity(psl);assert(pos >= 0 && pos <= psl->size);  //这里可以取等,因为数组下标是连续的,可以在psl->size 这个位置插入int i = psl->size - 1;while (i >= pos){psl->a[i + 1] = psl->a[i];i--;}psl->a[pos] = x;psl->size++;// 灵活运用: 头插,尾插就是此函数的一个特列}
8.任意位置的删除

1)判空检查

2)pos是否合法

3)数据挪动:同头删一样

 

void SLEarse(SL* psl, int pos)
{assert(psl);//删除之前,先对pos这个位置判断是否合法,是否为空assert(pos >= 0 && pos < psl->size);  //注意这里没有必要取等  ,同时这个语句暗含着对判空的操作了int i = pos;//挪动数据:从前往后while (i < psl->size - 1){psl->a[i] = psl->a[i + 1];i++;}//别忘了 size--psl->size--;}

9.空间容量的检查

    当我们在进行头插,尾插,任意位置插入时都需要进行空间容量的检查,这里为了避免不必要的麻烦,写了一个函数

void CheckCapacity(SL* psl)
{assert(psl);if (psl->capacity == psl->size){//realloc来扩容   void* realloc (void* ptr, size_t size);  第二个参数:扩容之后新的空间字节数,而不是要增加的字节数// 注意这样写是错误的,在free 的时候有问题  SLDataType* tmp = (SLDataType*)realloc(psl->a, (sizeof(SLDataType) *  4) * 2);//以原来2倍空间扩容SLDataType* tmp = (SLDataType*)realloc(psl->a, (sizeof(SLDataType) * psl->capacity) * 2);//以原来2倍空间扩容if (tmp == NULL){printf("perror realloc\n");return;}// 扩容成功,进行更新psl->a = tmp;psl->capacity *= 2;}
}
10. 查找

1)前期的判断:位置是否合法?  顺序表是否为空表

2) 其实就是暴力求解,依次遍历顺序表即可,若是找到返回下标,找不到返回-1

int  SLFind(SL* psl, SLDataType x)//查找
{assert(psl);assert(psl->size);//避免为空int i = 0;while (i < psl->size){if (psl->a[i] == x){return i;// 返回下标}i++;}return -1;//没有找到
}

11.任意位置修改 

1)依然是老生常谈,对位置以及顺序表进行判断

2)直接进行修改

void SLModify(SL* psl, int pos, SLDataType x) //指定位置修改
{assert(psl);assert(psl->size);//避免为空assert(pos >= 0 && pos <= psl->size - 1);psl->a[pos] = x;}

完整代码:

SeqList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"void SLInit(SL* psl)
{assert(psl);psl->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);//先为数组开4 个空间if (psl->a == NULL){printf("perror malloc\n");return;}psl->size = 0;psl->capacity = 4;
}
void SLDestroy(SL* psl)
{assert(psl);free(psl->a);psl->a = NULL;psl->capacity = 0;psl->size = 0;
}
void CheckCapacity(SL* psl)
{assert(psl);if (psl->capacity == psl->size){//realloc来扩容   void* realloc (void* ptr, size_t size);  第二个参数:扩容之后新的空间字节数,而不是要增加的字节数// 注意这样写是错误的,在free 的时候有问题  SLDataType* tmp = (SLDataType*)realloc(psl->a, (sizeof(SLDataType) *  4) * 2);//以原来2被空间扩容SLDataType* tmp = (SLDataType*)realloc(psl->a, (sizeof(SLDataType) * psl->capacity) * 2);//以原来2被空间扩容if (tmp == NULL){printf("perror realloc\n");return;}// 扩容成功,进行更新psl->a = tmp;psl->capacity *= 2;}
}
void SLPushBack(SL* psl, SLDataType x)
{assert(psl);//先判断空间是否足够CheckCapacity(psl);//之后直接尾插/*psl->a[psl->size] = x;psl->size++;*/if (psl->size == 0){psl->a[psl->size] = x;psl->size++;}else{SLInsert(psl, psl->size, x);//注意这里不用size++,因为SLInsert这个函数以及涉及到了}
}
void SLPushFront(SL* psl, SLDataType x)
{assert(psl);//先判断空间是否足够CheckCapacity(psl);挪动数据:从后往前挪动数据 注意边界的问题//int end = psl->size - 1;//while (end >= 0)//{//	psl->a[end + 1] = psl->a[end];//	end--;//}//psl->a[0] = x;SLInsert(psl, 0, x);// psl->size++;
}
void SLPopBack(SL* psl)
{assert(psl);//判断是否为空   温柔  / 暴力判断/*if (psl->size == 0){printf("为空 \n");return;}*/assert(psl->size);psl->size--;}
void SLPopFront(SL* psl)
{assert(psl);assert(psl->size);//判空// 挪动数据:从前往后挪数据int start = 0;while (start < psl->size - 1){psl->a[start] = psl->a[start + 1];start++;}//SLEarse(psl, 0);//注意:别忘了size--psl->size--;}
void SLPrint(SL* psl)
{assert(psl);int i = 0;while (i < psl->size){printf("%d ", psl->a[i]);i++;}printf("\n");
}
void SLEarse(SL* psl, int pos)
{assert(psl);//删除之前,先对pos这个位置判断是否合法,是否为空assert(pos >= 0 && pos < psl->size);  //注意这里没有必要取等  ,同时这个语句暗含着对判空的操作了int i = pos;//挪动数据:从前往后while (i < psl->size - 1){psl->a[i] = psl->a[i + 1];i++;}//别忘了 size--psl->size--;}
void SLInsert(SL* psl, int pos, SLDataType x)
{assert(psl);// 先进行空间判断,以及位置的合法CheckCapacity(psl);assert(pos >= 0 && pos <= psl->size);  //这里可以取等,因为数组下标是连续的,可以在psl->size 这个位置插入int i = psl->size - 1;while (i >= pos){psl->a[i + 1] = psl->a[i];i--;}psl->a[pos] = x;psl->size++;// 灵活运用: 头插,尾插就是此函数的一个特列}
SeqList.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//顺序表分类:静态顺序表  动态顺序表//静态的:空间开大了浪费,空间开小了不够用/*静态顺序表的结构体的构造
#define N 10
typedef int SLDataTYpe;//便于实现各种数据类型,一改全改typedef struct SeqList
{SLDataTYpe a[N];int size;//记录数据有效的个数
}SL;
*///动态顺序表
typedef int SLDataType;//便于实现各种数据类型,一改全改
typedef struct SeqList
{SLDataType* a;int size;//记录数据有效的个数int capacity;//空间空间的容量
}SL;
//接口函数的实现void SLInit(SL* psl);
void SLDestroy(SL* psl);
void SLPushBack(SL* psl, SLDataType x);
void SLPushFront(SL* psl, SLDataType x);
void SLPopBack(SL* psl);
void SLPopFront(SL* psl);
void SLPrint(SL* psl);
void SLEarse(SL* psl,int pos);
void SLInsert(SL* psl, int pos, SLDataType x);

结束语:

以上就是我今日要为大家分享的,希望各位大佬随时指正,咱一波关注走起,看到必回