数据结构——顺序表专题


乐观学习,乐观生活,才能不断前进啊!!!

我的主页:optimistic_chen
我的专栏:c语言
点击主页:optimistic_chen专栏:c语言
创作不易,大佬们点赞鼓励下吧~

前言

什么是数据结构呢?
· 数据结构是由“数据”和“结构”两词组合⽽来。
· 概念:数据结构是计算机存储、组织数据的⽅式。
· 数据结构是指相互之间存在⼀种或多种特定关系的数据元素的集合。数据结构反映数据的内部构成,即数据由那部分构成,以什么⽅式构成,以及数据元素之间呈现的结构。
总结:
1)能够存储数据(如顺序表、链表等结构)
2)存储的数据能够⽅便查找

顺序表概念

线性表( linear list )是n个具有相同特性的数据元素的有限序列。线性表是⼀种在实际中⼴泛使⽤的数据结构,常⻅的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

顺序表的分类

顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝

静态顺序表

struct SeqList
{
   
	int arr[100];//开少了不够,开多了浪费
	int size;//有效数据个数
};

typedef int SLDataType;

静态顺序表是一种在数据结构中常见的线性表实现方式,它使用定长数组来存储数据元素。这种数据结构在初始化时就确定了存储空间的大小,并在运行期间保持不变。

动态顺序表

typedef struct SeqList
{
   
	SLDataType* arr;//按需申请空间
	int size;//有效数据个数
	int capacity;//空间大小
}SL;

动态顺序表是一种可以动态调整其大小的顺序表,它克服了静态顺序表在大小固定方面的限制。

对比

分类 静态顺序表 动态顺序表
空间分配 创建时就分配了固定的内存空间,这避免了在运行时频繁地申请或释放内存 根据数据的实际需求动态地扩展或缩小存储空间,从而避免了静态顺序表在存储空间分配上可能出现的浪费或不足的问题
灵活性 不灵活 灵活性强
效率 由于数据元素在内存中是连续存放的,因此可以通过下标直接计算出元素在内存中的位置,实现快速存取 尽管动态顺序表能够动态调整大小,但在插入或删除元素时,仍可能需要移动其他元素以保持数据的连续性。这尤其在元素数量较大或需要频繁进行插入/删除操作时可能导致效率降低
管理 静态顺序表的实现相对简单,因为数组的操作是基础的编程技能,所以理解和使用都比较容易 动态顺序表需要维护额外的元数据(如当前大小、最大容量等),并需要实现相应的内存管理操作(如分配、释放等)。这增加了实现的复杂性和出错的可能性

总结:
静态顺序表在数据规模确定且不需要频繁改变的情况下表现良好,但在面对动态变化的数据规模时,其缺点就显得尤为突出。动态顺序表在处理动态变化的数据规模时具有较大的优势,但也需要考虑其带来的额外开销和实现的复杂性。在选择使用顺序表时,需要根据具体的应用场景和需求进行权衡。

顺序表的实现

我们以动态顺序表为例,完成顺序表的实现:

我们首先将顺序表的所有需求定义在一个头文件SeqList.h中。

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLDataType
#define INIT_CAPACITY 4
/动态顺序表
typedef struct SeqList
{
   
	SLDataType* arr;
	int size;
	int capacity;//空间大小
}SL;

//顺序表初始化
void SLInit(SL* ps);

//顺序表的销毁
void SLDestroy(SL* ps);

//顺序表的扩容
void SLCheckCapacity(SL* ps);

//顺序表的打印  
void SLPrintf(SL* ps);

//头部插入 / 尾部插入
void SLPushBack(SL* ps, SLDataType x);
void SLPushPront(SL* ps, SLDataType x);

//头部删除 / 尾部删除
void SLPopBack(SL* ps);
void SLPopPront(SL* ps);

//在指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLFrase(SL* ps, int pos);

//查找数据
int SLFind(SL* ps, SLDataType x);

我们后期的一系列操作都是根据头文件中的需求实现的。

一、顺序表的初始化

void SLInit(SL* ps)
{
   
	assert(ps);
 
	ps->arr = (SLDataType*)malloc(sizeof(SLDataType)* INIT_CAPACITY);
	if (ps->arr == NULL)
	{
   
		perror("malloc fail");
		return;
	}
 
	ps->size =0; 
	ps->capacity = INIT_CAPACITY;
}

代码分析:

断言(assert):

assert(ps);

断言用于检查传入的指针 ps 是否为 NULL。如果 ps 是 NULL,程序会在调试模式下终止执行,并显示一条错误消息。提前检查错误,确保ps 指向了一个有效的内存地址。
开辟内存空间

ps->arr = (SLDataType*)malloc(sizeof(SLDataType)* INIT_CAPACITY);

malloc 函数分配了 INIT_CAPACITY 个 SLDataType 大小的内存块,并将其地址赋值给 ps->arr。
这里SLDataType 是顺序表中存储的数据类型,而 INIT_CAPACITY 是一个常量,表示顺序表初始的容量
内存开辟失败:

if (ps->arr == NULL)  
 {
     
 perror("malloc fail");  
 return;  
 }

如果malloc函数没有顺利开辟内存,那么就会打印错误信息,不执行后面的代码。
初始化顺序表:

    ps->size =0; 
	ps->capacity = INIT_CAPACITY;

size 表示顺序表中当前存储的元素数量,初始化为0,表示顺序表是空的。
capacity 表示顺序表的容量,即它可以存储的最大元素数量,初始化为 INIT_CAPACITY。

二、顺序表的销毁

void SLDestroy(SL* ps)//销毁
{
   
	if (ps->arr)
	{
   
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

代码分析:

释放内存:

if (ps->arr)
	{
   
		free(ps->arr);
	}

if 的判断条件为ps->arr不为NULL则释放arr所占用的空间
这是一个非常重要的步骤,因为如果不释放已分配的内存,会导致内存泄漏
重置指针和属性

ps->arr = NULL;
p
### 学习数据结构的最佳方法 学习数据结构的核心在于掌握其基本概念并将其应用于实际问题解决过程中。通过有效的学习策略,可以显著提高效率和效果。 #### 基础理论的理解 为了更好地理解数据结构的概念,建议从以下几个方面入手: - **定义与分类**:明确什么是数据结构以及它包含哪些部分。例如,数据结构分为逻辑结构(线性、树形、图状等)和存储结构(顺序存储、链式存储等)。这些基础知识可以通过阅读经典教材获得[^2]。 - **抽象数据类型 (ADT)**:熟悉 ADT 的定义及其重要性,这有助于构建更高层次的数据处理模型。 #### 实践中的应用 仅仅了解理论是不够的,还需要动手实践来巩固所学知识。具体做法如下: - 使用编程语言实现各种常见的数据结构组、栈、队列、链表、哈希表、堆、二叉树等,并测试它们的功能是否正常工作; - 尝试解决一些基于特定数据结构的实际问题,比如利用图表示社交网络关系或者用动态规划优化背包问题解决方案; #### 工具辅助学习 除了传统的书籍之外,现在有许多优秀的在线平台可以帮助初学者快速入门并深入探索这一领域。以下是几个值得推荐的学习工具: - Codecademy 和 LeetCode 提供互动教程及挑战题目,使用户能够在真实环境中练习编码技能的同时加深对不同种类数据结构的认识[^3]; - Visualgo 是一个可视化网站,在这里你可以看到每一步操作是如何改变整个数据集布局的,这对于直观感受某些复杂过程尤其有用; ### 推荐资料 对于希望进一步提升自己在这方面能力的人来说,以下几套公开课程是非常宝贵的学习资源: 1. **MIT 开设的经典系列课——算法导论(6.046J/18.410J)** 由 Charles E.Leiserson 教授等人授课,该课程全面覆盖了计算机科学中最核心的一些主题,包括但不限于时间空间权衡分析、分治法原理等内容。作为 CLRS 这本书籍的主要编写者之一,他的讲解往往更加贴近原著精神[^4]. 2. **浙江大学提供的免费慕课项目—数据结构** 主讲人为何钦铭老师团队成员们共同完成的一门面向本科生开设的基础必修科目。整堂课节奏紧凑合理,案例选取恰当贴切日常生活场景便于记忆吸收. 3. **北京大学出品的相关专题讲座 — 算法设计与分析** 此版本主要围绕离散学背景下的组合最优化展开讨论,适合有一定前期积累后再回过头复习加强版型同学选读. ```python class Node: def __init__(self, value=None): self.value = value self.next = None def append_to_list(head, new_value): current_node = head while current_node is not None and current_node.next !=None : current_node=current_node.next temp=Node(new_value) if(current_node==None): return temp else: current_node.next=temp return head head=None for i in range(5,-1,-1): head=append_to_list(head,i) while head!=None: print(str(head.value)+"->",end="") head=head.next print("NULL") ``` 上述代码片段展示了如何创建单向链接列表并向其中追加新节点的过程实例演示.
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值