【数据结构】顺序表的实现——静态分配

news/2024/4/28 5:25:43/文章来源:https://blog.csdn.net/m0_74195174/article/details/137124121

在这里插入图片描述

🎈个人主页:豌豆射手^
🎉欢迎 👍点赞✍评论⭐收藏
🤗收录专栏:数据结构
🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步!

【数据结构】顺序表的实现——静态分配

  • 引言
  • 一 静态分配内存的概念
    • 1.1 概念
    • 1.2 类比
    • 1.3 例子
  • 二 顺序表静态分配的概念
    • 2.1 概念
    • 2.2 类比
  • 三 顺序表静态分配的实现方式
    • 3.1 定义顺序表结构体
    • 3.2 初始化顺序表:
    • 3.3 插入元素:
    • 3.4 删除元素:
    • 3.5 查找元素:
    • 3.6 修改元素:
  • 四 静态分配顺序表的优缺点分析
    • 4.1 优点:
    • 4.2 缺点:
  • 五 示例代码
  • 总结

引言

在数据结构的领域中,顺序表是一种基础且重要的线性表实现方式。它采用一段地址连续的存储单元依次存储线性表的数据元素,通过下标进行访问。

本文将重点探讨顺序表的静态分配实现方式,通过对其概念、实现方式以及优缺点的分析,帮助读者深入理解并掌握顺序表的相关知识
在这里插入图片描述

一 静态分配内存的概念

1.1 概念

在数据结构中,静态分配内存是一种在程序编译时确定所需内存大小,并在程序执行之前进行内存分配的方式。

这种分配方式通常在声明变量或数组时进行,它们被存储在程序的静态存储区或栈上。

静态分配内存具有几个特点。

首先,其大小在编译时就已经确定,因此具有固定的位置和生命周期

这意味着一旦分配了内存,其大小在程序运行期间不会改变

其次,静态分配的内存分配和释放是自动进行的,不需要手动管理。

当变量或数组超出其作用域或被销毁时,其占用的内存会自动被释放。

静态分配内存通常用于存储程序中的常量、全局变量和静态局部变量,以及其他需要在程序运行期间保持固定位置和生命周期的数据结构

在C和C++等语言中,静态区和静态内存的使用需要开发者手动控制,通常通过对变量的声明和定义进行修饰实现。

然而,静态分配内存也有一些局限性。

由于其在编译时确定大小,因此无法适应程序运行时可能出现的动态内存需求变化

如果分配的内存过大,可能会浪费系统资源;

如果过小,则可能导致程序运行出错。

为了应对这种局限性,动态内存分配被引入。

动态内存分配允许程序在运行时根据需要分配和释放内存,从而更灵活地管理内存资源。但需要注意的是,动态内存分配需要手动管理,如果管理不当可能导致内存泄漏或其他问题。

总的来说,静态分配内存是一种简单且高效的内存管理方式,适用于那些大小固定且生命周期明确的数据结构。但在处理复杂或动态变化的内存需求时,可能需要结合动态内存分配来使用。

1.2 类比

我们可以用现实中的一个例子来类比数据结构中静态分配内存的概念。

假设你正在策划一场大型活动,如音乐会或运动会。在这个场景中,你可以将静态分配内存类比为提前规划和分配资源的过程

静态分配内存

  • 大小确定:在策划活动时,你需要提前确定一些固定的资源需求,比如座位的数量、舞台的大小、音响设备的配置等。这些资源在活动开始前就已经被确定,并且不会在活动进行过程中改变。
  • 自动管理:一旦你规划了这些资源,它们就会按照你的计划自动存在。你不需要在活动过程中时刻关注这些资源的分配和释放。
  • 固定位置:座位、舞台、设备等在场地内都有固定的位置,它们在活动开始前就已经布置好,并且在活动进行过程中保持不变

类比到数据结构

  • 大小确定:在编程时,当你声明一个静态数组时,你需要在声明时就确定数组的大小。这个大小在程序运行期间不会改变
  • 自动管理:数组的内存分配和释放是由编译器自动管理的。你不需要手动去申请或释放内存
  • 固定位置:数组的元素在内存中也有固定的位置,你可以通过索引直接访问数组中的某个元素

通过这个类比,我们可以看到静态分配内存与现实生活中规划和分配固定资源的过程有很多相似之处。

它们都是在开始前就确定好大小、位置和数量,并且在整个过程中保持不变。

当然,这种固定性也带来了一定的局限性,比如无法应对突发的变化或需求增长。

在编程中,这种局限性可以通过动态内存分配来克服。但在现实生活中,我们也需要灵活应对变化,可能需要一些额外的策略和规划来确保资源的有效利用。

1.3 例子

下面是一个简单的C语言代码示例,展示了静态内存分配的基本用法。在这个例子中,我们将声明一个固定大小的整数数组,然后对其进行初始化,并打印出数组的内容。

#include <stdio.h>int main() {// 静态分配内存,声明一个包含5个整数的数组int staticArray[5] = {1, 2, 3, 4, 5};// 遍历数组并打印每个元素的值for (int i = 0; i < 5; i++) {printf("staticArray[%d] = %d\n", i, staticArray[i]);}// 静态分配的内存在程序执行完毕后会自动释放return 0;
}

代码结果(假设运行在一个标准的终端或控制台):

staticArray[0] = 1
staticArray[1] = 2
staticArray[2] = 3
staticArray[3] = 4
staticArray[4] = 5

代码分析:

  1. main函数中,我们声明了一个名为staticArray的整数数组,并静态分配了5个整数的内存空间。这里的“静态”指的是内存分配是在编译时确定的,并且数组的大小在整个程序执行期间保持不变。

  2. 数组staticArray被初始化为包含5个整数值:1, 2, 3, 4, 5。这些值在编译时就已经确定,并存储在静态存储区。

  3. 通过一个for循环,我们遍历数组并打印出每个元素的值。由于数组是静态分配的,所以我们可以直接通过索引访问其元素。

  4. main函数返回后,由于staticArray是局部变量,其占用的内存会在函数结束时自动释放。然而,由于这是静态分配的内存,实际上编译器在程序编译时就已经确定了这块内存的释放时间,而不是在运行时。

注意:虽然这个例子中的数组名为staticArray,但这里的“静态”并不是指C语言中的static关键字。这里的“静态”仅用于描述内存分配的方式是静态的,即在编译时确定

在C语言中,static关键字用于声明变量的生命周期为整个程序执行期间,而不仅仅是它们所在的函数或代码块

在本例中,即使我们没有使用static关键字,数组仍然是静态分配的,因为它的大小在编译时确定,并且作为局部变量存储在栈上。

如果要使数组的生命周期跨越多个函数调用,可以使用static关键字,但这与静态内存分配的概念是不同的。

二 顺序表静态分配的概念

2.1 概念

在数据结构中,顺序表是一种线性表的存储结构,其中元素在物理内存中以连续的方式存储。

顺序表可以通过两种方式进行实现:静态分配和动态分配

静态分配是指顺序表在声明时其大小就已经确定,且这个大小在程序的整个运行期间都不会改变

在静态分配中,顺序表通常是通过数组来实现的,因为数组的大小在编译时确定,并且一旦确定就不能更改

即静态分配的内存空间在程序执行前就已经分配完毕,并且会在程序执行完毕后自动释放。

静态分配顺序表的主要优点在于其简单性和效率

由于数组的大小在编译时确定,因此编译器可以进行一些优化,提高程序的执行效率。

此外,静态分配的顺序表在访问元素时具有较快的速度,因为可以通过简单的计算(即基址加偏移量)直接定位到元素的存储位置。

然而,静态分配顺序表也存在一些局限性。最主要的问题是其大小固定,无法根据程序运行时的需求进行动态调整

如果预先分配的空间过大,会造成内存资源的浪费;

如果分配的空间过小,则可能导致程序在运行时出现数组越界等错误。

因此,在选择使用静态分配顺序表时,需要根据实际的应用场景和需求进行权衡

如果数据量固定且不大,静态分配是一个简单且高效的选择;

如果数据量可能动态变化,或者需要更灵活的内存管理,那么可能需要考虑使用动态分配或其他数据结构。

2.2 类比

现实中的例子可以类比为在图书馆中分配书架来存储书籍

假设图书馆决定为某个特定类别的书籍分配书架。这个决定是在图书馆规划阶段就做出的,并且书架的数量和位置在规划完成后就固定下来了。这就是类似于数据结构中顺序表的静态分配。

静态分配书架的类比

  1. 大小确定:图书馆根据预计的书籍数量和类别,确定需要多少个书架来存放这些书籍。这些书架的数量和大小在图书馆建设或重新规划时就已经确定,并且在之后的使用过程中不会改变

  2. 位置固定:书架在图书馆内有固定的位置,按照规划好的布局摆放。每个书架都有一个固定的编号或位置标识,方便读者和图书管理员查找和管理。

  3. 连续存储:书架上的格子或层数是连续的,用于存放同一类别的书籍。这种连续存储的方式使得查找和取放书籍变得相对容易,类似于顺序表在内存中的连续存储

  4. 无法动态调整:一旦书架的数量和位置确定后,图书馆就难以根据书籍数量的变化来动态调整书架的配置。如果书籍数量增多,超出了现有书架的容量,图书馆可能需要重新规划并增加书架,这涉及到较大的改动和成本。

类比到数据结构

  1. 大小确定:在编程时,当你静态分配一个顺序表(例如通过数组)时,你需要在声明时就确定顺序表的大小(即数组的长度)。这个大小在程序运行期间不会改变

  2. 位置固定:顺序表的元素在内存中有固定的位置,通过索引可以直接访问到特定的元素

  3. 连续存储:顺序表在内存中占用连续的内存空间,这使得访问元素时可以通过简单的计算来定位到元素的地址。

  4. 无法动态调整:一旦顺序表的大小确定后,如果在程序运行过程中需要增加或减少元素的数量,而原有空间不足或过多,那么就需要进行额外的处理,如重新分配内存或浪费空间

通过这个类比,我们可以看到静态分配书架与静态分配顺序表在概念上有很多相似之处。

它们都是在规划或声明时就确定了大小和位置,并且在之后的使用过程中保持不变

然而,这种固定性也带来了一定的局限性,特别是在需要应对变化或增长的情况时。

因此,在现实中,图书馆可能会根据实际需求进行灵活调整,而在编程中,我们也有动态内存分配等方法来应对类似的问题。

三 顺序表静态分配的实现方式

顺序表静态分配的实现步骤主要涉及以下几个方面:

3.1 定义顺序表结构体

首先,需要定义一个结构体来表示顺序表。这个结构体通常包含两个主要部分:一个是用于存储元素的数组,另一个是用于记录顺序表当前长度的变量。例如,在C语言中,可以这样定义:

#define MAXSIZE 100 // 假设顺序表的最大长度为100typedef struct {int data[MAXSIZE]; // 用于存储元素的数组int length;        // 记录顺序表当前长度
} SeqList;

在这个例子中,MAXSIZE 是静态分配的顺序表的最大容量,而 data 数组用于存储顺序表中的元素,length 则记录顺序表当前已存储的元素个数。

具体代码分析:

  1. #define MAXSIZE 100:这行代码定义了一个宏MAXSIZE,其值为100。这个宏在后续的代码中将被用作顺序表的最大长度,也就是数组data的大小。通过宏定义,可以在不修改源代码的情况下,方便地调整顺序表的最大长度。

  2. typedef struct {...} SeqList;:这行代码定义了一个结构体类型SeqList。结构体包含两个成员:

    • int data[MAXSIZE];:这是一个整型数组,用于存储顺序表中的元素。数组的大小由前面定义的宏MAXSIZE确定,即最大可以存储100个整数
    • int length;:这是一个整型变量,用于记录顺序表当前的长度,即当前顺序表中存储的元素的数量。这个长度在初始化时为0,随着元素的插入和删除操作而变化

整个代码段定义了一个简单的顺序表结构,其中使用了静态分配的方式来确定数组的大小。

3.2 初始化顺序表:

在创建顺序表时,需要对其进行初始化。初始化通常包括将顺序表的长度设置为0,以确保它是一个空表

void InitList(SeqList *L) {L->length = 0; // 将顺序表长度初始化为0
}

具体代码分析:

这段代码定义了一个名为InitList的函数,它接受一个指向SeqList结构体的指针L作为参数。该函数的主要目的是初始化顺序表,使其处于一个空表的状态。以下是对代码每个步骤的分析:

  1. void InitList(SeqList *L) {:定义了一个返回类型为void的函数InitList,它接受一个指向SeqList结构体的指针L作为参数。通过指针,函数能够访问和修改传入的顺序表实例

  2. L->length = 0;:这行代码通过指针L访问顺序表结构体中的length成员,并将其值设置为0。这个操作表示初始化顺序表,将其长度设置为0,即表示顺序表当前没有任何元素

  3. }:函数体结束。

综上,InitList函数的整个步骤就是接收一个顺序表的指针,然后将其长度初始化为0,从而实现顺序表的初始化。这样的初始化操作是创建新顺序表或重置现有顺序表为空表时的常见步骤。

3.3 插入元素:

向顺序表中插入元素时,需要检查顺序表是否已满(即当前长度是否已经达到最大容量)。如果未满,则将新元素添加到顺序表的末尾,并更新顺序表的长度。

int InsertList(SeqList *L, int elem) {if (L->length >= MAXSIZE) {// 顺序表已满,无法插入新元素return 0; // 返回失败}L->data[L->length] = elem; // 将新元素添加到顺序表末尾L->length++;              // 更新顺序表长度return 1;                  // 返回成功
}

具体代码分析:

这段代码定义了一个名为InsertList的函数,用于向顺序表SeqList中插入一个元素。以下是对代码每个步骤的分析:

首先,函数接受两个参数:一个指向SeqList结构体的指针L,以及一个待插入的整数元素elem

接着,函数检查顺序表是否已满,即检查L->length(顺序表的当前长度)是否大于等于MAXSIZE(顺序表的最大容量)。

如果是,说明顺序表已满,无法再插入新元素,因此函数返回0,表示插入失败。

如果顺序表未满,函数执行下一步,将新元素elem插入到顺序表的末尾,具体做法是将elem赋值给L->data[L->length],即顺序表数组中当前长度对应的位置。

然后,函数将顺序表的长度L->length加1,以反映新元素的插入。

最后,函数返回1,表示元素插入成功

整个函数通过检查顺序表是否已满、插入新元素、更新顺序表长度和返回操作结果等步骤,实现了向顺序表中插入新元素的功能。

3.4 删除元素:

从顺序表中删除元素时,通常需要指定要删除元素的位置。删除操作包括将指定位置后的所有元素前移一位,并更新顺序表的长度。

int DeleteList(SeqList *L, int pos) {if (pos < 1 || pos > L->length) {// 删除位置不合法return 0; // 返回失败}for (int i = pos; i < L->length; i++) {L->data[i - 1] = L->data[i]; // 将后续元素前移}L->length--; // 更新顺序表长度return 1;    // 返回成功
}

具体代码分析:

这段代码定义了一个名为DeleteList的函数,用于从顺序表SeqList中删除指定位置的元素。以下是对代码每个步骤的分析:

首先,函数接受两个参数:一个指向SeqList结构体的指针L,以及一个整数pos表示要删除元素的位置。

接着,函数检查删除位置pos是否合法

如果pos小于1或者大于顺序表的当前长度L->length,说明删除位置不合法,因此函数直接返回0,表示删除操作失败。

如果删除位置合法,函数进入循环,从pos位置开始,将顺序表中该位置及之后的每个元素都向前移动一位覆盖掉前一个元素的位置。这样,原来pos位置上的元素就被后续的元素所替代,从而实现了删除操作。

循环结束后,函数将顺序表的长度L->length减1,以反映元素被删除的情况。

最后,函数返回1,表示元素删除成功。

整个函数通过检查删除位置、移动元素和更新顺序表长度等步骤,实现了从顺序表中删除指定位置元素的功能。

在顺序表中,元素是按照数组的形式连续存储的。因此,当要删除某个位置的元素时,我们不能简单地移除那个元素,因为这会导致数组中出现一个“空洞”,即不连续的内存空间。为了维持顺序表的连续性,我们需要将删除位置之后的所有元素都向前移动一位,覆盖掉被删除元素的位置。

在这段代码中,for循环负责执行这个元素前移的操作。它从要删除的位置pos开始,将每个位置的元素值赋给前一个位置,直到到达顺序表的末尾。这样,原来pos位置上的元素就被后面的元素所覆盖,实现了删除的效果。

因此,虽然代码中并没有直接执行一个显式的“删除”操作(比如将某个元素的值设置为一个特殊值或NULL),但通过移动元素和更新长度,已经间接地实现了删除指定位置元素的功能。

3.5 查找元素:

顺序表的查找操作通常通过遍历数组来实现,比较目标值与顺序表中每个元素的值,直到找到目标值或遍历完整个顺序表。

int GetElem(SeqList L, int pos, int *elem) {if (pos < 1 || pos > L.length) {// 查找位置不合法return 0; // 返回失败}*elem = L.data[pos - 1]; // 返回查找位置的元素值return 1;                 // 返回成功
}

具体代码分析:

这段代码定义了一个名为GetElem的函数,用于从顺序表SeqList中获取指定位置的元素值。以下是对代码每个步骤的分析:

首先,函数接受三个参数:

一个SeqList类型的顺序表L,一个整数pos表示要查找的元素位置,以及一个整数指针elem用于返回查找到的元素值。

接着,函数检查查找位置pos是否合法。

如果pos小于1或者大于顺序表的当前长度L.length,说明位置不合法,因此函数直接返回0,表示查找失败。

如果查找位置合法,函数通过指针elem返回顺序表中对应位置的元素值。

这里使用了数组下标pos - 1来访问数组元素,因为数组下标是从0开始的,而位置是从1开始计数的。

最后,函数返回1,表示查找成功,并且已经将查找到的元素值通过指针elem返回给了调用者。

整个函数通过检查位置合法性、返回元素值和返回操作结果等步骤,实现了从顺序表中获取指定位置元素的功能。

3.6 修改元素:

修改顺序表中的元素只需要指定位置和新值,然后直接替换原有元素即可。

int UpdateElem(SeqList *L, int pos, int newElem) {if (pos < 1 || pos > L->length) {// 修改位置不合法return 0; // 返回失败}L->data[pos - 1] = newElem; // 修改指定位置的元素值return 1;                    // 返回成功
}

具体代码分析:

这段代码定义了一个名为UpdateElem的函数,用于更新顺序表SeqList中指定位置的元素值。以下是对代码每个步骤的分析:

首先,函数接受三个参数:

一个指向SeqList结构体的指针L,表示要更新的顺序表;一个整数pos,表示要更新的元素位置;以及一个整数newElem,表示新的元素值。

接着,函数检查更新位置pos是否合法。

如果pos小于1或者大于顺序表的当前长度L->length,说明位置不合法,因此函数直接返回0,表示更新失败。

如果更新位置合法,函数将新元素值newElem赋值给顺序表中对应位置的元素。

这里使用了数组下标pos - 1来访问数组元素,因为数组下标是从0开始的,而位置是从1开始计数的。

最后,函数返回1,表示更新成功。

整个函数通过检查位置合法性、更新元素值和返回操作结果等步骤,实现了顺序表中指定位置元素的更新功能。

这些步骤涵盖了顺序表静态分配的基本操作。

需要注意的是,由于静态分配的顺序表大小在初始化时就已经确定,因此在插入元素时需要检查是否已满,以避免数组越界错误。

同时,由于顺序表在内存中占用的是连续空间,因此插入和删除操作可能会涉及到大量元素的移动,这在某些情况下可能会影响性能。

在实际应用中,如果数据量较大或需要频繁进行插入和删除操作,可能需要考虑使用动态分配或其他数据结构来优化性能。

四 静态分配顺序表的优缺点分析

静态分配顺序表是数据结构中的一种常见形式,它基于数组实现,具有固定的存储空间大小。以下是对其优缺点的详细分析:

4.1 优点:

  1. 存储连续:静态分配顺序表的元素在物理存储上是连续的,这意味着通过下标访问元素的速度非常快,因为可以直接通过计算得出元素的存储位置。

  2. 空间利用率高:因为顺序表是基于数组实现的,其空间利用率通常比链表等结构要高。数组在内存中占用的是一块连续的空间,没有像链表那样的指针占用额外的空间。

  3. 随机访问:顺序表支持随机访问,即可以通过任意位置的索引直接访问该位置的元素,这在某些应用中是非常有用的,如快速查找特定位置的元素。

  4. 操作简单:对于顺序表,插入和删除操作通常只需要移动少量元素即可完成,这使得操作相对简单和高效。

4.2 缺点:

  1. 空间限制:静态分配顺序表的最大缺点是它的空间大小是固定的,一旦初始化后就不能改变。这意味着如果数据量超过了初始分配的空间,就会导致空间溢出,无法继续存储新的数据。

  2. 插入和删除效率:尽管顺序表的插入和删除操作在某些情况下可以高效完成,但在某些特定位置(如头部或中间位置)插入或删除元素时,可能需要移动大量的元素,这会导致效率降低。

  3. 扩展性差:由于静态分配顺序表的空间大小是固定的,因此在面对不断增长的数据量时,需要重新分配更大的空间并复制原有的数据,这不仅增加了操作的复杂性,还可能导致数据丢失或不一致。

  4. 灵活性不足:与链表等动态数据结构相比,静态分配顺序表的灵活性较差。链表可以根据需要动态地分配和释放内存,而顺序表则需要在初始化时就确定空间大小,这在某些应用中可能不够灵活。

综上所述,静态分配顺序表在访问速度快、空间利用率高等方面具有优势,但在空间限制、插入和删除效率、扩展性和灵活性等方面存在不足。因此,在选择使用静态分配顺序表时,需要根据具体的应用场景和需求进行权衡和选择。

五 示例代码

以下是一个静态分配顺序表的简单示例代码,包括初始化、插入、删除、查找和更新元素等基本操作的实现。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>#define MAXSIZE 100 // 假设顺序表的最大长度为100typedef struct {int data[MAXSIZE]; // 存储元素的数组int length;        // 当前顺序表的长度
} SeqList;// 初始化顺序表
void InitList(SeqList *L) {L->length = 0;
}// 插入元素
bool InsertList(SeqList *L, int elem) {if (L->length >= MAXSIZE) {// 顺序表已满,无法插入新元素return false;}L->data[L->length] = elem; // 将新元素添加到顺序表末尾L->length++;              // 更新顺序表长度return true;
}// 删除指定位置的元素
bool DeleteList(SeqList *L, int pos) {if (pos < 1 || pos > L->length) {// 删除位置不合法return false;}for (int i = pos; i < L->length; i++) {L->data[i - 1] = L->data[i]; // 将后续元素前移}L->length--; // 更新顺序表长度return true;
}// 查找元素
int GetElem(SeqList L, int pos, int *elem) {if (pos < 1 || pos > L.length) {// 查找位置不合法return 0;}*elem = L.data[pos - 1]; // 返回查找位置的元素值return 1;
}// 更新指定位置的元素值
bool UpdateElem(SeqList *L, int pos, int newElem) {if (pos < 1 || pos > L->length) {// 修改位置不合法return false;}L->data[pos - 1] = newElem; // 修改指定位置的元素值return true;
}// 打印顺序表
void PrintList(SeqList L) {for (int i = 0; i < L.length; i++) {printf("%d ", L.data[i]);}printf("\n");
}int main() {SeqList L;InitList(&L);// 插入元素InsertList(&L, 10);InsertList(&L, 20);InsertList(&L, 30);// 打印顺序表printf("List after insertion: ");PrintList(L);// 更新元素UpdateElem(&L, 2, 25);// 打印顺序表printf("List after update: ");PrintList(L);// 删除元素DeleteList(&L, 2);// 打印顺序表printf("List after deletion: ");PrintList(L);// 查找元素int elem;if (GetElem(L, 1, &elem)) {printf("Element at position 1: %d\n", elem);} else {printf("Invalid position for element retrieval.\n");}return 0;
}

以下是该代码在main函数中执行后的输出样子:

List after insertion: 10 20 30 
List after update: 10 25 30 
List after deletion: 10 30 
Element at position 1: 10

解释:

  1. InsertList 函数被调用了三次,将元素 10、20 和 30 插入到顺序表 L 中。

  2. PrintList 函数被调用,输出顺序表的内容,显示 10 20 30

  3. UpdateElem 函数被调用,将顺序表中位置 2(注意位置是从 1 开始的)的元素从 20 更新为 25。

  4. 再次调用 PrintList 函数,输出更新后的顺序表内容,显示 10 25 30

  5. DeleteList 函数被调用,删除顺序表中位置 2 的元素(现在是 25)。

  6. 第三次调用 PrintList 函数,输出删除元素后的顺序表内容,显示 10 30

  7. GetElem 函数被调用,尝试获取位置 1 的元素。因为位置合法,所以函数返回 1,并且通过指针 elem 返回了元素值 10。

  8. 输出通过 GetElem 函数获取到的元素值,显示 Element at position 1: 10

注意,这段代码假设了静态顺序表的最大长度为 MAXSIZE,定义为 100。在实际应用中,这个值可能需要根据具体的应用场景进行调整。此外,这个简单的例子没有包含错误处理,例如当尝试插入超过顺序表最大长度的元素时,InsertList 函数只是简单地返回 false,并没有给出明确的错误信息。在实际应用中,通常会添加更详细的错误处理逻辑。

总结

通过对顺序表静态分配实现方式的详细探讨,我们深入了解了其概念、实现过程以及优缺点。

静态分配顺序表具有存储密度高、空间利用率好等优点,适用于数据元素数量确定且不易发生变化的场景。

然而,其缺点也不容忽视,如空间扩展性差、插入和删除操作效率较低等。

因此,在实际应用中,我们需要根据具体需求和数据特点来选择合适的顺序表实现方式。

示例代码部分展示了静态分配顺序表的基本操作,包括初始化、插入、删除、查找和修改元素等。

这些操作的实现方式简单明了,为读者提供了实践操作的参考。

综上所述,顺序表静态分配实现方式在数据结构领域中具有重要地位。通过本文的学习,相信读者已经对顺序表有了更深入的理解和掌握,能够在实际应用中灵活运用。

这篇文章到这里就结束了

谢谢大家的阅读!

如果觉得这篇博客对你有用的话,别忘记三连哦。

我是豌豆射手^,让我们我们下次再见

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_1027010.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux manim安装

简介 根据文档可知, manim目前分为两个版本, 一个是由3Blue1Brown维护更新的最新版本的manimgl, 另一个是稳定的社区版本manim or manimce. 两个版本在安装和使用上都有些不同, 不要搞混. Linux manim ERROR No package ‘pangocairo’ found Getting requirements to buil…

使用 .NET 和 Teams Toolkit 构建 AI 机器人、扩展 Copilot for Microsoft 365 以及更多

作者&#xff1a;Ayca Bas 排版&#xff1a;Alan Wang Teams Toolkit for Visual Studio 帮助 .NET 开发人员为 Microsoft Teams 构建、调试和发布应用程序。我们很高兴向大家宣布&#xff0c;Teams Toolkit for Visual Studio 2022 17.9 版本为 .NET 开发人员提供了许多令人兴…

【Qt】使用Qt实现Web服务器(六):QtWebApp用户名密码登录

1、示例 1)演示 2)登录 3)显示 2、源码 示例源码Demo1->LoginController void LoginController::service(HttpRequest& request, HttpResponse& response) {

Wagtail-基于Python Django的内容管理系统CMS实现公网访问

目录 前言 1. 安装并运行Wagtail 1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具 3. 实现Wagtail公网访问 4. 固定Wagtail公网地址 前言 Wagtail是一个用Python编写的开源CMS&#xff0c;建立在Django Web框架上。Wagtail 是一个基于 Django 的开源内容管理系统&…

鸿蒙开发实战-如何开发一个字符串加解密应用程序

介绍 本Codelab针对用户隐私安全&#xff0c;使用加密算法API对密码进行加密存储&#xff0c;模拟开发一个用户注册登录应用。实现如下功能&#xff1a; 实现登录、注册、登录成功页面。注册的用户数据保存到关系型数据库。登录时通过查询数据库校验用户是否存在、密码是否正…

如何高效系统地自学 Python?

导言&#xff1a; Python作为一门流行的编程语言&#xff0c;被广泛运用于数据分析、人工智能、网络应用等领域。想要系统地自学Python&#xff0c;并掌握其核心概念和编程技能&#xff0c;需要一定的方法和步骤。本文将介绍如何高效系统地自学Python&#xff0c;让你能够快速…

docker推拉时的数据交换详解

前言 docker用了这么久了, 有没有想过, 在执行docker push 和 docker pull命令的时候, 数据是如何传递的呢? 换句话说, 如果要实现一个镜像仓库, 针对推拉的服务, 如何实现接口呢? 根据OCI 分发规范文档 的描述, 已经对整个推拉过程中要调用的接口有描述了. 但是, 纸上学来…

Linux升级GCC

文章目录 一、安装 EPEL 仓库二、更新yum三、安装 CentOS 开发工具组四、安装scl五、安装gcc 11六、启用gcc 11七、设置永久使用 一、安装 EPEL 仓库 命令&#xff1a; yum install epel-release -y二、更新yum 命令&#xff1a; yum update -y三、安装 CentOS 开发工具组 …

蓝桥杯练习题总结(三)线性dp题(摆花、数字三角形加强版)

目录 一、摆花 思路一&#xff1a; 确定状态&#xff1a; 初始化&#xff1a; 思路二&#xff1a; 确定状态&#xff1a; 初始化&#xff1a; 循环遍历&#xff1a; 状态转移方程&#xff1a; 二、数字三角形加强版 一、摆花 题目描述 小明的花店新开张&#xff0c;为了吸…

python知识点总结(十)

python知识点总结十 1、装饰器的理解、并实现一个计时器记录执行性能&#xff0c;并且将执行结果写入日志文件中2、队列和栈的区别&#xff0c;并且用python实现3、设计实现遍历目录与子目录4、CPU处理进程最慢的情况通常发生在以下几种情况下&#xff1a;5、CPU处理线程最慢的…

删除数组中的指定元素(了解如何删除数组中的指定元素,并返回一个新的数组,看这一篇就足够了!)

前言&#xff1a;有时候我们会遇到要在数组中删除指定元素&#xff0c;但是不能创建新的数组&#xff0c;那么这个时候应该如何操作呢&#xff1f; ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 废话不多讲&#xff0c;让我们…

脚本实现Ubuntu设置屏幕无人操作,自动黑屏

使用 xrandr 命令可以实现对屏幕的控制&#xff0c;包括调整分辨率、旋转屏幕以及关闭屏幕等。要实现 Ubuntu 设置屏幕在无人操作一段时间后自动黑屏&#xff0c;非待机&#xff0c;并黑屏后点击触摸屏可以唤醒屏幕&#xff0c;可以借助 xrandr 命令来实现。 首先&#xff0c;…

基于ssm在线云音乐系统的设计与实现论文

摘 要 随着移动互联网时代的发展&#xff0c;网络的使用越来越普及&#xff0c;用户在获取和存储信息方面也会有激动人心的时刻。音乐也将慢慢融入人们的生活中。影响和改变我们的生活。随着当今各种流行音乐的流行&#xff0c;人们在日常生活中经常会用到的就是在线云音乐系统…

macos配置maven

Mac Maven 安装及配置 - 知乎 官网上下载一个zip 配置环境变量vim ~/.bash_profile 我打开来看到之前配过conda的&#xff0c;和教程里不一样。那就在之前的配置下方添加就好了。 既然你的.bash_profile文件中已经有了一些配置&#xff0c;特别是Anaconda的初始化脚本&#…

鸿蒙HarmonyOS应用开发之Rawfile开发指导

场景介绍 开发者可以通过本指导了解在OpenHarmony应用中&#xff0c;如何使用Native Rawfile接口操作Rawfile目录和文件。功能包括文件列表遍历、文件打开、搜索、读取和关闭Rawfile。 接口说明 接口名描述NativeResourceManager *OH_ResourceManager_InitNativeResourceMan…

哪些属于“法律、行政法规另有规定,依照其规定进行评估/批准”的情况?

哪些属于“法律、行政法规另有规定&#xff0c;依照其规定进行评估/批准”的情况&#xff1f; 除《网络安全法》《数据安全法》和《个人信息保护法》确立的数据和网络安全整体体系外&#xff0c;企业还应当考虑其他相关法律法规的要求。 例如&#xff1a; ✮如根据《中华人民…

OpenHarmony实战开发-滑动容器组件Swiper的使用

介绍 本篇Codelab主要介绍了滑动容器组件Swiper的几种常见的应用场景&#xff0c;包括顶部导航、轮播图以及视频滑动播放。 相关概念 Swiper&#xff1a;滑动容器&#xff0c;提供子组件切换滑动的能力。Stack&#xff1a;堆叠容器&#xff0c;子组件按照顺序依次入栈&#x…

训练svm并部署树莓派

训练svm并部署树莓派 开发环境1. 准备数据集2. 训练模型3. 部署模型开发环境 vscode python 3.8 用到的库: scikit-learn==1.3.2 pickle torch pandas matplotlib 1. 准备数据集 数据为xls文件,如下格式 2. 训练模型 文件结构 执行训练 python代码 import pickle &…

【计算机网络】IP 协议

网络层IP协议 一、认识 IP 地址二、IP 协议报头格式三、网段划分1. 初识子网划分2. 理解子网划分3. 子网掩码4. 特殊的 IP 地址5. IP 地址的数量限制6. 私有 IP 地址和公网 IP 地址7. 理解全球网络&#xff08;1&#xff09;理解公网&#xff08;2&#xff09;理解私网&#xf…

Git 常用命令速查

Git 是一个分布式版本控制系统&#xff0c;用于管理代码和其他文件。它允许您跟踪代码的更改&#xff0c;并在必要时回滚到以前的版本。 本文将介绍一些 Git 常用命令&#xff0c;帮助您快速上手 Git。 初始化 Git 仓库 git init添加文件到暂存区 git add <file_name>…