数据结构——顺序表

简介: 数据结构——顺序表

即使你内心没有一尊明月,也要给自己留下一方皎洁


文章目录


什么是顺序表


顺序表的实现


顺序表内部基础设置


结构体数据类型重定义


顺序表结构定义


顺序表空间初始化及扩容设置


顺序表空间的初始化及销毁


顺序表的扩容


顺序表基本功能


尾插尾删


头插头删


在任意位置删和插


 大家好,我是纪宁。


 本文将介绍顺序表的内容,此内容为数据结构的入门内容,可以为后面的链表等困难数据结构的学习做铺垫。希望大家和我都可以将数据结构的基础扎实!


 有需要的老铁可以去看博主的往期作品

数据结构与算法对程序员的重要性

http://t.csdn.cn/muEFA


 本文使用的顺序表类型名和函数名如下表


SeqList 顺序表

SLDataType 重定义顺序表成员数据类型

SLInit 初始化顺序表

SLDestroy 销毁顺序表

SLPrint 打印顺序表

SLCheckCapacity 检查顺序表容量

SLPushFront 头插

SLPopFront

头删


SLPushBack 尾插

SLPopBack 尾删

SLInsert 在pos位置插入

SLErase 删除pos位置的成员

什么是顺序表

 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,通俗的来讲就是数组存储,在数组的基础上多了增删查改的功能。


 一般顺序表分为静态顺序表和动态顺序表。静态顺序表采用定长数组存储元素的形式,动态顺序表使用动态开辟的数组存储。因为顺序表只适用于已知需要存储多少数据的形式,而到底数组长度  N 空间开辟多大难以把握(开辟太大导致空间浪费,太少导致不够用)。所以我们一般使用的是动态顺序表,可以动态分配内存大小。


顺序表的实现

顺序表内部基础设置

 顺序表的基础设置中包括顺序表结构体的定义和结构体数据类型的重定义,结构开辟的动态数组空间是由 SLDataType*(重定义)类型的指向顺序表成员的指针和 表示顺序表最大空间的变量 capacity 共同维护的。


结构体数据类型重定义

typedef int SLDataType;

 将顺序表内的数据类型重定义,可以方便顺序表成员数据类型的修改。如果要修改结构体变量数据类型(如由 int 变为 double)时,只需要修改 typedef 后面的数据类型,那么程序中顺序表的元素类型变为 double 型。


顺序表结构定义

typedef struct SeqList

{

SLDataType* arr;

int sz;

int capacity;

}SL;

 arr是一个指针,指向动态开辟的顺序表数组,数据类型为 typedef 重定义后的数据类型,方便修改;sz表示顺序表元素个数;capacity表示顺序表的最大空间。


顺序表空间初始化及扩容设置

顺序表空间的初始化及销毁

void SLInit(SL* s)

{

s->arr = (SLDataType*)malloc(4 * sizeof(SLDataType));

if (s->arr == NULL)

{

 perror("malloc");

 exit(-1);

}

s->sz = 0;

s->capacity = 4;

}

 首先,可以使用 malloc 函数开辟 k 个成员的空间,并且将首空间的地址强转后赋值给 arr 指针,同时将最大空间变量 capacity 赋值为4,但顺序表成员个数变量 sz 依旧是0,因为只是初始化了顺序表空间,并未往顺序表中加入成员。


 在程序结束的阶段,在保存数据后,最好做到能将顺序表销毁。


void SLDestroy(SL* s)

{

free(s->arr);

s->arr = NULL;

s->sz = s->capacity = 0;

}

 销毁阶段将初始化时开辟的内存释放,并将指针置空,同时成员个数 sz 和 最大空间 capacity 的值都改为0。


顺序表的扩容

 因为动态的顺序表初始状态下只开辟了较少的空间,在程序判断出顺序表内存空间已满后要进行顺序表空间的扩容处理,所以最好可以封装一个函数,达到既可以判断最大空间与当前成员的关系(即判断满没满),又能在将顺序表扩容。


void SLCheckCapacity(SL* s)

{

if (s->sz == s->capacity)

{

 SLDataType* tmp = realloc(s->arr, 2 * sizeof(SLDataType) * (s->capacity));

 if (tmp == NULL)

 {

  perror("realloc");

  exit(-1);

 }

 else

 {

  s->arr = tmp;

  s->capacity *= 2;

 }

}

}


 使用 realloc  函数可以将顺序表扩容,因为 realloc 每扩容一次都需要耗费一定的资源,那么如果使用过于频繁,势必会让内存的压力变得非常大,所以一般顺序表扩容都是以2倍的速度增长。realloc 函数扩容动态内存分为原地扩容和异地扩容,可以先用一个指针来接受扩容后的首地址,再赋值给 arr,同时顺序表的最大空间乘2。


顺序表基本功能

 顺序表的基本功能为头插、头删、尾插、尾删。


尾插尾删

void SLPushBack(SL* s, SLDataType x)

{

SLCheckCapacity(s);

*(s->arr + s->sz) = x;

s->sz++;

}

void SLPpoBack(SL* s)

{

if (s->sz == 0)

{

 exit(-1);

}

s->sz--;

}

 顺序表尾插之前要检查顺序表是否需要增容,然后将元素插在 arr[sz] 的位置即可,尾删的时候需要注意如果元素个数为0,就要强制要退出或断言。


头插头删

void SLPushFront(SL* s, SLDataType x)

{

SLCheckCapacity(s);

if (s->sz == 0)

{

 s->arr[0] = x;

 s->sz++;

}

else

{

 int i = 0;

 for (i = s->sz-1; i>=0; i--)

 {

  *(s->arr + i+1) = *(s->arr + i);

 }

 *(s->arr) = x;

 s->sz++;

}

}

void SLPopFront(SL* s)

{

if (s->sz == 0)

 exit(-1);

else

{

 int i = 0;

 for (i = 0; i < s->sz - 1; i++)

 {

  s->arr[i] = s->arr[i + 1];

 }

 s->sz--;

}

}


 头插的时候要判断元素个数,如果没有成员,就直接将首元素赋值为 x ;如果有成员,就先将所有成员后移,再首元素赋值为 x,最后将元素个数 sz 加1。


 头删的时候只需要将所有成员前移一个位置,再将元素个数 sz 减1。


在任意位置删和插

void SLInsert(SL* s, int pos, SLDataType x)

{

s->sz++;

int i = 0;

for (i =s->sz-1-1; i>=pos; i--)

{

 *(s->arr + i + 1) = *(s->arr + i);

}

*(s->arr + pos) = x;

}

void SLErase(SL* s, int pos)

{

if (s->sz < pos)

 exit(-1);

for (int i = pos; i < s->sz - 1; i++)

{

 *(s->arr + i) = *(s->arr + i + 1);

}

s->sz--;

}


 在任意位置插入数据和删除数据其实原理和头插头删是一样的,在任意位置插和删只需要把握部分整体后移的‘度’就行,建议新手多画图来理解这种较为复杂的情况,尽量不要出现“代码5分钟,调试两小时。”的情况。

相关文章
|
1月前
|
存储 编译器 C语言
数据结构-顺序表详解(看这篇就足够了,哈哈哈)
数据结构-顺序表详解(看这篇就足够了,哈哈哈)
51 2
|
20天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
20天前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
52 3
|
20天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
1月前
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
30 6
|
1月前
|
存储 安全 Java
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
23 3
|
1月前
|
存储 C语言
探索C语言数据结构:利用顺序表完成通讯录的实现
本文介绍了如何使用C语言中的顺序表数据结构实现一个简单的通讯录,包括初始化、添加、删除、查找和保存联系人信息的操作,以及自定义结构体用于存储联系人详细信息。
19 2
|
1月前
|
存储 算法 索引
【数据结构】——顺序表
【数据结构】——顺序表
|
1月前
|
存储
【数据结构】线性表和顺序表
【数据结构】线性表和顺序表
22 1
|
1月前
|
存储
数据结构1——顺序表
数据结构1——顺序表
17 1