目录
1.什么是数据结构
2. 顺序表概念及结构
3. 顺序表分类
4. 实现动态顺序表
1.什么是数据结构
数据结构分为数据和结构两个部分
数据:不管是手机,还是电脑,你上网的时候,你看见的图片,文字,数字,一切的一切都可以被称为数据
数据按照一定的结构排列,这就是数据结构,有了数据结构,原本很乱的东西可以按照一定的方式排列,方便我们对它进行操作,通过学习数据结构,你可以在后期制作一个通讯录,实现对数据的增加,删除,插入操作
2.顺序表的概念和和结构
1.1,线性表
线性表( linear?list )是n个具有相同特性的数据元素的有限序列。?线性表是⼀种在实际中⼴泛使
⽤的数据结构,常⻅的线性表:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的,
线性表在物理上存储时,通常以数组和链式结构的形式存储。
案例:蔬菜分为绿叶类、⽠类、菌菇类。线性表指的是具有部分相同特性的⼀类数据结构的集合
如何理解逻辑结构和物理结构
1.2、顺序表分类
顺序表和数组的区别
◦ 顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝
顺序表的分类:静态顺序表,动态顺序表
静态顺序表
typedef int SLDateType;
#define N 9
typedef struct SeqList
{
SLDateType a[N];
int size;//有效数据的个数
}
解释:上面的对整形数据进行从定义的原因是
如果在以后写代码的时候,要求将顺序表里面的int类型的数据转换成为其他数据类型的时候会比较方便,如果要求改顺序表里面的int类型的话,但是其他部分的代码也有int类型的话,你如果使用一键替换功能的话,就会把其他部分的替换了,但是使用从定义的话,就不存在这个问题
静态顺序表缺陷:空间给少了不够⽤,给多了造成空间浪费
动态顺序表
3. 实现动态顺序表
以下是头文件
#pragma once
typedef int typedate;
typedef struct SL
{
typedate* arr;
int size;//定义有效数据个数
int capticy;//记录顺序表的空间大小
}sl;
void Print(SL* s);
void SLinit(SL* s);//初始化
void checkSL(SL* s);//扩容
void SLpushfront(SL* s,int x);//顺序表的头插
void SLpushback(SL* s, int x);//顺序表的尾插
void SLpopback(SL* s);//顺序表的尾部删除
void SLpopfront(SL* s);//顺序表的头部进行操作
void SLpoppos(SL* s, int pos);//对顺序表的任意位置进行删除
以下是源文件
#include<stdio.h>
#include"SL.H"
#include<stdlib.h>
#include<assert.h>
//初始化顺序表
void SLinit(SL* s)
{
s->arr = NULL;
s->size = s->capticy = 0;
}
void Print(SL* s)
{
for (int i = 0; i <s-> size; i++)
{
printf("%d ", s->arr[i]);
}
}
void checkSL(SL* s)//给数据表初始化空间
{
if (s->size == s->capticy)
{
int newcpaticy = s->capticy = 0 ? 4 : 2 * s->capticy;
int* tmp = (typedate*)realloc(s->arr, sizeof(typedate) * newcpaticy);
if (tmp == NULL)
{
perror("");
exit(1);
}
//扩容成功
s->arr = tmp;
s->capticy = newcpaticy;
}
}
void SLpushfront(SL* s,int x)
{
assert(s);
checkSL(s);
for (int i = s->size; i > 0; i--)
{
s->arr[i] = s->arr[i-1];
}
s->arr[0] = x;
s->size++;
}
void SLpushback(SL* s, int x)
{
assert(s);
checkSL(s);
s->arr[s->size] = x;
s->size++;
}
void SLpopback(SL* s)
{
assert(s);
assert(s->size);//判断数组是否为空数组,否则不能进行删除工作
checkSL(s);
s->arr[s->size--] = 0;
}
void SLpopfront(SL* s)
{
assert(s);
assert(s->size);
for (int i = 0; i <s->size-1; i++)
{
s->arr[i] = s->arr[i + 1];
}
s->size--;
}
void SLpoppos(SL* s, int pos)
{
assert(s);
assert(s->size);
for (int i = pos; i < s->size - 1; i++)
{
s->arr[i] = s->arr[i + 1];
}
s->size--;
}
以下是测试文件
#include<stdio.h>
#include"SL.h"
void SLtest01()
{
SL sl;
SLinit(&sl);
SLpushfront(&sl, 4);
SLpushfront(&sl, 5);
SLpushfront(&sl, 6);
SLpushfront(&sl, 7);
SLpushfront(&sl, 8);
SLpushback(&sl, 9);
SLpopback(&sl);
SLpopfront(&sl);
SLpoppos(&sl, 2);
Print(&sl);
}
int main()
{
SLtest01();
return 0;
}
值得注意的是:
在进行扩容的时候,最好是扩容到原来的1.5,2,或是4倍,如果一次扩容一点的话,就会扩容的越频繁,由前面对动态内存管理里面realloc函数的理解,浪费的空间可能会越来越多,倍数太大的话又会造成空间浪费过多
对顺序表进行添加元素,删除元素的原理都是对元素进行移位操作,方法不止这一种,比如可以使用memmove函数进行操作