💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤
📃个人主页 :阿然成长日记 👈点击可跳转
📆 个人专栏: 🔹数据结构与算法🔹C语言进阶
🚩 不能则学,不知则问,耻于问人,决无长进
🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍
🌟前言
本期博客主要是讲解动态的顺序表也就是
链表
,它比静态表更加具有实用性等等优势,。好了,接下来让我们一起学习吧 💪
文章目录
- 🚩数组越界问题:
一、什么是线性表
🔸
线性表
是最基本、最简单、也是最常用的一种数据结构。🔸 线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。
🔸线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,yey
🍉线性表(linear list)是n个具有相同特性的数据元素的有限序列。
常见的线性表有:顺序表、链表、栈、队列、字符串…
需要注意:线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的, 线性表在物理上存储时,通常以数组
和链式结构
的形式存储。
二、什么是顺序表
顺序表的概念:
顺序表
是用一段物理地址连续的存储单元依次存储数据元素的线性结构。
❗️顺序表又分静态顺序表
和动态顺序表
。
接下来的讲解主要是动态顺序表。
三、使用动态内存函数实现动态顺序表
1.接口实现
1.1 定义动态顺序表
typedef int SLDataType; typedef struct SeqList { SLDataType* array; // 指向动态开辟的数组 size_t size ; // 有效数据个数 size_t capicity ; // 容量空间的大小 }SeqList;
说明:
◾️
typedef int SLDataType
的作用是定义一种类型,后期使用时方便改变存储类型。◾️为了让定义的结构体使用时更方便,我使用 typedef 将其定义为
SL
1.2顺序表的初始化
//顺序表的初始化 void SeqListInit(SL* ps) { ps->array = (SLDataType*)malloc(sizeof(SLDataType)*4); if (ps->array = NULL) { perror("malloc failed"); exit(-1); } ps->size = 0; ps->capacity = 0; }
我这里刚开始给顺序表初始化了四个大小。
1.3扩容
// 检查空间,如果满了,进行增容 int CheckCapacity(SL* ps) { if (ps->size == ps->capacity) { SLDataType* tmp = NULL; tmp = (SLDataType*)realloc(ps->array, sizeof(ps->array) + sizeof(SLDataType) * INT_SIZE); if (tmp == NULL) { perror("扩容失败!"); return 0; } else { ps->array = tmp; ps->capacity += INT_SIZE; printf("扩容成功"); return 1; } } return 1; }
🚦当空间不够时,进行扩容操作,一次在原有基础上增加两个大小。这里由于很多的地方都需要使用扩容操作,所以,我专门将扩容提取出来做成一个函数
,供其他函数调用
。 。
1.4顺序表销毁
// 顺序表销毁 void SeqListDestory(SL* ps) { free(ps->array); ps->array = NULL; ps->capacity = 0; ps->size = 0; }
.5顺序表尾插
// 顺序表尾插 void SeqListPushBack(SL* ps, SLDataType x) { if (CheckCapacity(ps) == 0) { printf("空间已满,插入失败!"); } if (CheckCapacity(ps) == 1) { ps->array[ps->size] = x; ps->size += 1; } }
1.6顺序表尾删
// 顺序表尾删 void SeqListPopBack(SL* ps) { if (ps->size < 1) { printf("已经为空,无元素可删除"); return; } ps->array[ps->size - 1] = 0; ps->size--; }
1.7顺序表的头插
思路:
顺序表要求数据是连续存储的,且必须是从头开始存储。所以,对于顺序表而言如果要实现头插,就需要把数据往后挪动。不能从前往后挪,如果从前往后挪就挪就会把后面的数据覆盖掉。
// 顺序表头插 void SeqListPushFront(SL* ps, SLDataType x) { //判断空间是否够。 //先挪动 if (CheckCapacity(ps) == 0) { printf("空间已满,头插入失败!"); } if (CheckCapacity(ps) == 1) { int end = ps->size - 1; while (end>=0) { ps->array[end + 1] = ps->array[end]; --end; } ps->array[0] = x; ps->size++; } }
1.8顺序表的头删
思路:
// 顺序表头删 void SeqListPopFront(SL* ps) { int n = 1; while (n < ps->size) { ps->array[n - 1] = ps->array[n]; n++; } ps->size--; }
1.9顺序表在pos位置插入x
pos一般都是指下标
// 顺序表在pos位置插入x void SeqListInsert(SL* ps, size_t pos, SLDataType x) { assert(pos>=0&&pos<ps->size); if (CheckCapacity(ps) == 0) { printf("空间已满,插入失败!\n"); } if (CheckCapacity(ps) == 1) { int end = ps->size - 1 ; while (end >= pos) { ps->array[end + 1] = ps->array[end]; end--; } ps->array[pos] = x; ps->size++; } }
1.10在pos指定下标删除元素
思路分析:
// 顺序表删除pos位置的值 void SeqListErase(SL* ps, size_t pos) { assert(pos >= 0 && pos < ps->size); int n = pos + 1; while (n <= ps->size - 1) { ps->array[n - 1] = ps->array[n]; n++; } ps->size--; }
🚩数组越界问题:
假设有一块数组空间,我们的编辑器会在最容易出现越界的位置,比如数组前一段和后一段,放入一些值,程序结束后,他会检查这些值是否发生变化,如果变化了,就说明越界啦。
📋各位友友们,咱下回再见!
别忘了点赞👍 关注 💓加评论 ✏️哟
💙 💜 ❤️ 💚 💔 💓 💗 💕 💞 💘 💖 ✨ ⭐️ 🌟