数据结构之顺序表详解:从原理到C语言实现

引言

在上一篇文章中我们讲到了时间复杂度空间复杂度,今天我们接着讲数据结构中的内容。

数据的存储和组织方式决定了程序的效率。而顺序表,也就是大家熟悉的数组,正是我们编程中的"起步工具"。它简单易懂,却能帮你解决许多实际问题。那么什么是顺序表呢?

1. 什么是顺序表?

顺序表 ,简单来说就是你常见的数组(Array)。它是一种线性表 ,指的是数据按照顺序排列、依次存储在连续的内存空间中。你可以把顺序表想象成一排紧密排列的座位,每个座位上都可以放一个数据,每个座位都有自己的编号(索引),你可以通过这个编号快速找到想要的座位上的数据。

虽然顺序表看似简单,但理解它的运作原理以及如何高效使用它,将为你后续学习更复杂的数据结构打下坚实的基础。

在这篇文章中,我将带你深入探讨顺序表的基础知识、实现方式、常见操作以及优缺点,并结合C语言代码一步步展示如何操作和应用顺序表。无论你是刚开始编程,还是想巩固基础,这篇文章都将帮助你更好地掌握这一重要的概念。废话不多说,我们开始今天的学习之旅吧~~~

2. 顺序表的特点

顺序表的几个显著特点 包括存储连续性、随机访问、固定大小和插入删除的代价较高。这些特点直接影响了我们在不同场景下选择使用顺序表的决策。具体如何,我们接着看。

3. 顺序表的基本操作

顺序表的基本操作包括:插入删除查找更新。下面我将逐一介绍这些操作,并对每段代码进行详细的解释。

1). 插入元素

在顺序表中插入元素时,我们需要注意插入的位置。如果是在表的末尾,操作相对简单;如果是在中间,可能需要移动后面的元素。以下是插入元素的代码实现:

cpp 复制代码
#include <stdio.h>

void insert(int arr[], int *size, int pos, int value) {
    // 向后移动元素
    for (int i = *size; i > pos; i--) {
        arr[i] = arr[i - 1]; // 将元素逐一向后移动
    }
    // 插入新值
    arr[pos] = value; // 在指定位置插入新值
    (*size)++; // 增加顺序表的大小
}
  • void insert(int arr[], int *size, int pos, int value):定义了一个函数,接受数组arr、当前大小size的指针、插入位置pos和要插入的值value
  • for (int i = *size; i > pos; i--):从顺序表的最后一个元素开始,向前遍历到插入位置。*size代表当前顺序表的大小。
  • arr[i] = arr[i - 1]:将当前位置的元素向后移动一个位置,以腾出插入的空间。
  • arr[pos] = value:在指定位置插入新值。
  • (*size)++:插入元素后,顺序表的大小增加1。
2). 删除元素

删除元素时,同样需要将删除位置之后的元素向前移动,以保持顺序表的连续性。以下是删除元素的代码实现:

cpp 复制代码
void delete(int arr[], int *size, int pos) {
    // 向前移动元素
    for (int i = pos; i < *size - 1; i++) {
        arr[i] = arr[i + 1]; // 将后面的元素向前移动
    }
    (*size)--; // 减少顺序表的大小
}
  • void delete(int arr[], int *size, int pos):定义了一个函数,接受数组arr、当前大小size的指针和要删除的元素位置pos
  • for (int i = pos; i < *size - 1; i++):从删除位置开始,遍历到倒数第二个元素(因为最后一个元素需要被覆盖)。
  • arr[i] = arr[i + 1]:将当前位置的元素替换为下一个位置的元素,从而"覆盖"要删除的元素。
  • (*size)--:删除元素后,顺序表的大小减少1。
3). 查找元素

查找顺序表中的元素可以通过索引直接访问。以下是查找元素的代码实现:

cpp 复制代码
int get(int arr[], int size, int pos) {
    if (pos >= 0 && pos < size) {
        return arr[pos]; // 返回指定位置的值
    }
    return -1; // 返回-1表示索引无效
}
  • int get(int arr[], int size, int pos):定义了一个函数,接受数组arr、当前大小size和要查找的元素位置pos
  • if (pos >= 0 && pos < size):检查索引pos是否有效,确保在合法范围内。
  • return arr[pos]:如果索引有效,返回对应位置的值。
  • return -1:如果索引无效,返回-1作为错误指示。
4). 更新元素

更新顺序表中的元素只需通过索引找到目标元素并进行赋值。以下是更新元素的代码实现:

cpp 复制代码
void update(int arr[], int size, int pos, int value) {
    if (pos >= 0 && pos < size) {
        arr[pos] = value; // 更新指定位置的值
    }
}
  • void update(int arr[], int size, int pos, int value):定义了一个函数,接受数组arr、当前大小size、要更新的元素位置pos和新值value
  • if (pos >= 0 && pos < size):检查索引是否有效。
  • arr[pos] = value:如果有效,将指定位置的值更新为新值。

4. 顺序表的优缺点

上面我们说到顺序表的特点。所以它在不同的场景下表现各异。我们就需要充分理解它的优缺点,以便在合适的场景中使用它。

优点:
  • 快速访问 :由于支持随机访问,顺序表能够在O(1)的时间内通过索引找到元素,这在需要频繁查找的场景中非常有用。
  • 结构简单:顺序表的实现相对简单,是编程入门的一个良好选择。
缺点:
  • 插入和删除效率低:每次在中间插入或删除元素时,都会导致大量的元素移动,效率较低,特别是数据量大时。
  • 固定容量 :数组一旦定义,大小就固定了,无法动态调整。因此在实际使用中,可能会出现空间不足或浪费空间的情况。

5. 顺序表的应用场景

顺序表非常适合那些需要频繁访问元素的场景,比如:

  • 查找元素频繁 :当需要快速访问元素时,顺序表的随机访问特性可以提供极高的性能。
  • 插入和删除较少:顺序表适合数据更新较少的情况,尤其是数据量固定、变动较少的场景。

例如:

  • 学生成绩表:当我们只需要根据学生的序号快速查找成绩时,顺序表是一个非常好的选择。
  • 图像处理:像素点数据通常以二维数组的形式存储,可以高效访问和处理。

6. 何时不使用顺序表

尽管顺序表有很多优点,但它并不适合所有场景,特别是在以下情况下:

  • 频繁插入/删除 :当你的程序中存在大量的插入和删除操作时,顺序表会变得低效,链表可能是更好的选择。
  • 动态扩展需求:当数据量不可预估且需要动态扩展时,顺序表的固定大小会成为限制。

当然,顺序表也能有动态扩展,但是它并不是最好的选择,每次扩容它都会有额外的消耗,如果有老铁想要知道顺序表的动态扩展可以评论区留言,这里我不展开讲。


7. 总结

顺序表是数据结构的基础部分,它提供了快速的随机访问能力,适合数据量固定且访问频繁的场景。在C语言中,顺序表的实现相对简单,是初学者理解线性数据结构的理想起点。

在学习顺序表的过程中,建议你多动手实践,尝试实现插入、删除、查找等操作,这不仅能帮助你理解顺序表的原理,还能为你未来学习更复杂的数据结构(如链表、栈、队列)打下坚实的基础。

下一步,我将深入讨论链表及其在灵活数据存储中的应用。顺序表虽然性能优越,但在一些特定场景中,链表的灵活性会表现得更好。

最后如果觉得有收获的话记得点赞加收藏哦~~~

相关推荐
一只小透明啊啊啊啊1 分钟前
Leetcode100子串
算法
木向1 分钟前
leetcode:114. 二叉树展开为链表
算法·leetcode·链表
sky_smile_Allen6 分钟前
[C#] 关于数组的详细解释以及使用注意点
开发语言·算法·c#
冷心笑看丽美人11 分钟前
Spring 框架七大模块(Java EE 学习笔记03)
学习·spring·架构·java-ee
希望有朝一日能如愿以偿23 分钟前
力扣题解(新增道路查询后的最短距离II)
算法
huaqianzkh25 分钟前
学习C#中的BackgroundWorker 组件
开发语言·学习·c#
最后一个bug27 分钟前
如何理解Lua 使用虚拟堆栈
linux·c语言·开发语言·嵌入式硬件·lua
我感觉。32 分钟前
【机器学习chp6】对数几率回归
算法·机器学习·逻辑回归·分类模型·对数几率回归
今天我又学废了1 小时前
Scala学习记录,Array
学习