数据结构之顺序表详尽教程

顺序表的定义

顺序表是一种常见的线性数据结构,用于存储一组元素,这些元素按照一定的顺序排列在一起。顺序表的特点是元素在内存中是连续存储的,因此可以通过索引位置快速访问和修改元素。顺序表通常用于需要频繁随机访问元素的情况。

顺序表有两种主要实现方式:

  1. 静态顺序表:静态顺序表的大小在创建时就固定了,不能动态扩展或缩小。这种实现方式在空间要求明确、不需要频繁插入和删除元素的情况下非常有效。

  2. 动态顺序表:动态顺序表的大小可以根据需要动态调整,以适应元素的增加或减少。这种实现方式通常使用动态数组或类似的数据结构来实现,提供了更灵活的存储管理。

顺序表的常见操作包括插入、删除、查找、遍历等,这些操作都可以在常数时间复杂度或线性时间复杂度内完成,取决于具体实现方式。因此,顺序表在许多应用中都具有高效的性能。

顺序表和其他数据结构之间的比较

顺序表是一种常见的线性数据结构,与其他数据结构相比具有各自的优点和适用场景。以下是顺序表与其他数据结构的比较:

1. **链表 vs. 顺序表:**
   - 顺序表的元素在内存中是连续存储的,而链表的元素是分散存储的,因此顺序表支持快速的随机访问,而链表需要遍历查找。
   - 链表可以方便地进行插入和删除操作,而不需要像顺序表那样搬移元素。顺序表在插入和删除操作中可能需要移动大量元素。
   - 顺序表需要预分配内存空间,而链表的内存分配更加动态,可以根据需要分配和释放内存。

2. **栈和队列 vs. 顺序表:**
   - 栈和队列是特殊类型的线性数据结构,它们可以使用顺序表或链表来实现。在顺序表中,它们通常需要维护指向栈顶或队列头部的指针,以便在常数时间内进行入栈、出栈、入队和出队操作。

3. **动态数组 vs. 顺序表:**
   - 动态数组可以自动调整大小以适应元素的增加或减少,而顺序表的大小通常在创建时固定。因此,动态数组更灵活,但可能会引入一些额外的空间和性能开销。
   - 顺序表在元素访问方面通常更快,因为它们的元素是连续存储的,而动态数组可能需要重新分配内存来调整大小。

4. **哈希表 vs. 顺序表:**
   - 哈希表是一种键值对存储结构,用于快速查找和插入数据。顺序表通常不适用于键值对的存储,而哈希表可以在平均情况下以常数时间复杂度执行这些操作。
   - 哈希表的内存消耗通常比顺序表高,因为它需要额外的哈希表存储和冲突处理机制。

总之,选择使用哪种数据结构取决于问题的需求和性能要求。顺序表在需要频繁随机访问元素且元素数量相对稳定的情况下表现良好,但在需要频繁插入和删除元素、或者需要动态调整大小以适应变化的情况下,其他数据结构如链表或动态数组可能更合适。

数据表的基本操作

定义顺序表结构

typedef struct {
    int length;
    int capacity;
    int *data;
} Seqlist;

这段代码定义了一个名为 Seqlist 的结构体,用于表示顺序表(Sequential List)。顺序表是一种线性数据结构,它存储一组元素,并且这些元素在内存中是连续存储的。让我们来解释这段代码的各个部分:

  1. int length;: 这是一个整数字段,用于表示顺序表中当前存储的元素数量。在初始化时,通常会将它设置为0,然后随着元素的插入和删除操作而逐渐增加或减少。

  2. int capacity;: 这是另一个整数字段,表示顺序表的容量,即它可以存储的元素数量上限。容量是在创建顺序表时分配的内存大小,通常在初始化时设定,并且通常大于等于 length。当元素数量接近容量时,可能需要进行扩容操作。

  3. int *data;: 这是一个整型指针,它指向存储顺序表元素的内存块。实际的元素数据存储在这个内存块中,通常是一个整数数组。指针的使用允许顺序表动态分配内存以适应不同的容量需求。

通过这个结构体定义,我们可以创建 Seqlist 类型的对象,用于表示和操作顺序表的相关信息,包括元素数量、容量以及元素数据的存储。这个结构体提供了一种灵活的方式来管理顺序表,并可以根据需要进行动态调整大小,以适应元素的增加或减少。

定义顺序表的基本操作(增删改查等)

Seqlist* create(int capacity);
void set_value(Seqlist* seqlist, int data);
int get_value(Seqlist* seqlist, int index);
void insert(Seqlist* seqlist, int index, int data);
void delete_value(Seqlist* seqlist, int index);
void destroy(Seqlist* seqlist);

顺序表的初始化

Seqlist* create(int capacity) {
    Seqlist* seqlist = (Seqlist*)malloc(sizeof(Seqlist));
    if (!seqlist) {
        printf("Create error in line %d!\n", __LINE__);
        return NULL;
    }
    memset(seqlist, 0, sizeof(Seqlist));
    seqlist->capacity = capacity;
    seqlist->data = (int*)malloc(sizeof(int) * capacity);
    if (!seqlist->data) {
        printf("Create error in line %d!\n", __LINE__);
        free(seqlist);
        return NULL;
    }
    printf("Init!\n");
    return seqlist;
}

这段代码是用来创建并初始化一个顺序表(Seqlist)的函数,以下是对这段代码的详细解释:

  1. Seqlist* create(int capacity) {: 这是一个函数定义,它接受一个整数参数 capacity,用来指定顺序表的容量。函数返回一个指向顺序表结构体 Seqlist 的指针。

  2. Seqlist* seqlist = (Seqlist*)malloc(sizeof(Seqlist));: 在函数内部,首先使用 malloc 分配了一块内存,大小足够容纳一个 Seqlist 结构体,并将其地址赋给 seqlist。这个内存用于存储顺序表的控制信息,如长度、容量等。

  3. if (!seqlist) { ... }: 接着,代码检查是否成功分配了内存。如果分配失败(即 seqlistNULL),则打印一条错误信息,并返回 NULL 表示创建失败。

  4. memset(seqlist, 0, sizeof(Seqlist));: 使用 memset 函数将分配的内存块初始化为零,以确保所有字段的初始值为0,包括长度、容量和数据指针。这是一种常见的初始化操作。

  5. seqlist->capacity = capacity;: 设置顺序表的容量为传入的参数 capacity

  6. seqlist->data = (int*)malloc(sizeof(int) * capacity);: 接下来,分配另一块内存,用于存储顺序表的元素数据。这里的数据类型是整数(int),并且分配的内存大小为 sizeof(int) * capacity 字节,以确保足够的空间来存储指定容量的整数元素。

  7. if (!seqlist->data) { ... }: 再次检查是否成功分配了元素数据的内存。如果分配失败,打印错误信息,释放之前分配的控制信息内存,并返回 NULL 表示创建失败。

  8. 最后,如果成功完成上述步骤,函数会打印 "Init!" 表示初始化成功,并返回指向新创建顺序表的指针 seqlist

这个函数的作用是动态创建一个顺序表,并为其分配足够的内存以存储元素和控制信息。如果内存分配失败,函数会进行错误处理并返回 NULL。否则,它返回指向初始化后的顺序表的指针,以便在后续操作中使用。

顺序表存入数据

void set_value(Seqlist* seqlist, int data) {
    if (!seqlist || !seqlist->data) {
        printf("Set error in line %d\n", __LINE__);
        return;
    }
    if (seqlist->length == seqlist->capacity) {
        printf("Error: List is full. Cannot add more elements.\n");
        return;
    }
    seqlist->data[seqlist->length] = data;
    seqlist->length++;
}

这段代码是一个函数,用于向顺序表(Seqlist)中设置元素的值。下面是对这段代码的详细解释:

  1. void set_value(Seqlist* seqlist, int data) {: 这是一个函数定义,它接受两个参数,第一个参数是指向顺序表结构体的指针 seqlist,第二个参数是要设置的整数值 data

  2. if (!seqlist || !seqlist->data) { ... }: 函数的第一部分是错误检查。首先,它检查传入的 seqlist 指针是否为 NULL 或者 seqlist->data 是否为 NULL。如果其中任何一个条件成立,表示顺序表未正确初始化或者内存分配失败,就会打印一条错误信息,并返回,不执行后续的设置操作。

  3. if (seqlist->length == seqlist->capacity) { ... }: 接下来,代码检查顺序表的长度是否已经等于容量。如果长度等于容量,说明顺序表已满,无法再添加更多的元素,因此会打印一条错误信息,并返回,不执行设置操作。

  4. seqlist->data[seqlist->length] = data;: 如果前面的检查都通过,说明可以将元素 data 添加到顺序表中。这行代码将 data 存储到顺序表的 data 数组中,位置为 seqlist->length,即当前顺序表的末尾。

  5. seqlist->length++;: 最后,函数递增了顺序表的长度字段 seqlist->length,以表示新元素已经成功添加到了顺序表中。

总之,这个函数的主要功能是将一个整数值添加到顺序表中,前提是顺序表已正确初始化、未满,否则会进行错误处理。这样,顺序表就可以逐渐填充元素,而且在超过容量限制时能够防止继续添加。

顺序表获取数据

int get_value(Seqlist* seqlist, int index) {
    if (!seqlist || index > seqlist->length || index <= 0) {
        printf("Get error in line %d\n", __LINE__);
        return -1;
    }
    return (seqlist->data[index-1]);
}

这段代码定义了一个函数 `get_value`,其作用是从顺序表中获取指定索引位置的元素值。以下是对这段代码的详细解释:

1. `int get_value(Seqlist* seqlist, int index) {`: 这是一个函数定义,它接受两个参数。第一个参数是指向顺序表结构体的指针 `seqlist`,用于表示要操作的顺序表。第二个参数是整数 `index`,表示要获取的元素的索引位置。

2. `if (!seqlist || index > seqlist->length || index <= 0) { ... }`: 函数的第一部分是错误检查。它首先检查传入的 `seqlist` 指针是否为 `NULL`,以确保顺序表已正确初始化。然后,它检查 `index` 是否超出了有效的范围。`index` 必须大于0(因为索引是从1开始的)且小于等于顺序表的长度 `seqlist->length`。如果任何一个条件不满足,函数会打印一条错误信息,并返回-1表示获取操作失败。

3. `return (seqlist->data[index-1]);`: 如果前面的错误检查都通过,表示可以安全地获取指定索引位置的元素。这行代码使用 `index-1` 来访问顺序表的 `data` 数组,因为索引从1开始,而数组索引从0开始。然后,它返回这个位置的元素值。

总结起来,这个函数的主要功能是获取顺序表中指定索引位置的元素值。在执行之前,它会进行一系列的错误检查,以确保顺序表已正确初始化并且索引在有效范围内。如果检查失败,函数会返回-1表示获取失败,否则返回指定索引位置的元素值。

顺序表删除数据

void delete_value(Seqlist* seqlist, int index) {
    if (!seqlist || index > seqlist->length || index <= 0) {
        printf("Delete error in line %d\n", __LINE__);
        return;
    }
    for (int i = index-1; i < seqlist->length - 1; i++) {
        seqlist->data[i] = seqlist->data[i+1];
    }
    seqlist->length--;
}

这段代码定义了一个名为 delete_value 的函数,其目的是从顺序表中删除指定索引位置的元素。以下是对这段代码的详细解释:

  1. void delete_value(Seqlist* seqlist, int index) {: 这是一个函数定义,它接受两个参数。第一个参数是指向顺序表结构体的指针 seqlist,用于表示要操作的顺序表。第二个参数是整数 index,表示要删除的元素的索引位置。

  2. if (!seqlist || index > seqlist->length || index <= 0) { ... }: 函数的第一部分是错误检查,与前面的函数类似。它首先检查传入的 seqlist 指针是否为 NULL,以确保顺序表已正确初始化。然后,它检查 index 是否超出了有效的范围。index 必须大于0(因为索引是从1开始的)且小于等于顺序表的长度 seqlist->length。如果任何一个条件不满足,函数会打印一条错误信息,并返回,不执行删除操作。

  3. for (int i = index-1; i < seqlist->length - 1; i++) { ... }: 如果前面的错误检查都通过,表示可以安全地执行删除操作。这部分代码使用一个循环,从指定的 index 开始,将后续元素逐个向前移动一个位置,以覆盖要删除的元素。循环从 index-1 开始,因为数组索引是从0开始的。

  4. seqlist->length--;: 最后,函数递减了顺序表的长度字段 seqlist->length,表示成功删除了一个元素。

总结起来,这个函数的主要功能是从顺序表中删除指定索引位置的元素。在执行之前,它会进行一系列的错误检查,以确保顺序表已正确初始化并且索引在有效范围内。如果检查失败,函数会返回,不执行删除操作。如果检查通过,函数会通过循环将后续元素向前移动,然后递减顺序表的长度字段,表示删除成功。

顺序表插入数据

void insert(Seqlist* seqlist, int index, int data) {
    if (!seqlist || index > seqlist->length+1 || index <= 0) {
        printf("Insert error in line %d\n", __LINE__);
        return;
    }
    if (seqlist->length == seqlist->capacity) {
        printf("Insertion error: The list is full.\n");
        return;
    }
    for (int i = seqlist->length-1; i >= index - 1; i--) {
        seqlist->data[i+1] = seqlist->data[i];
    }
    seqlist->data[index-1] = data;
    seqlist->length++;
}

这段代码定义了一个函数 insert,其功能是在顺序表中的指定索引位置插入一个新的元素。以下是对这段代码的详细解释:

  1. void insert(Seqlist* seqlist, int index, int data) {: 这是一个函数定义,它接受三个参数。第一个参数是指向顺序表结构体的指针 seqlist,用于表示要操作的顺序表。第二个参数是整数 index,表示要插入的位置的索引。第三个参数是整数 data,表示要插入的新元素的值。

  2. if (!seqlist || index > seqlist->length+1 || index <= 0) { ... }: 函数的第一部分是错误检查。它首先检查传入的 seqlist 指针是否为 NULL,以确保顺序表已正确初始化。然后,它检查 index 是否在有效范围内。index 必须大于0(因为索引是从1开始的)且小于等于顺序表的长度 seqlist->length + 1,因为插入操作可以在表的末尾进行。如果任何一个条件不满足,函数会打印一条错误信息,并返回,不执行插入操作。

  3. if (seqlist->length == seqlist->capacity) { ... }: 接下来,代码检查顺序表是否已满,即长度是否等于容量。如果长度等于容量,说明顺序表已满,无法再插入更多的元素,因此会打印一条错误信息,并返回,不执行插入操作。

  4. for (int i = seqlist->length-1; i >= index - 1; i--) { ... }: 如果前面的错误检查都通过,表示可以安全地执行插入操作。这部分代码使用一个循环,从顺序表的最后一个元素开始,逐个向后移动元素,以为新元素腾出空间。循环的终止条件是达到了指定的插入位置 index - 1。循环中,每个元素都向后移动一个位置。

  5. seqlist->data[index-1] = data;: 在腾出空间后,代码将新元素的值 data 插入到指定的索引位置 index - 1

  6. seqlist->length++;: 最后,函数递增了顺序表的长度字段 seqlist->length,表示成功执行了插入操作。

总结起来,这个函数的主要功能是在顺序表中的指定索引位置插入一个新的元素。在执行之前,它会进行一系列的错误检查,以确保顺序表已正确初始化、未满,而且插入位置在有效范围内。如果检查失败,函数会返回,不执行插入操作。如果检查通过,函数会通过循环将后续元素向后移动,然后在指定位置插入新元素,并递增顺序表的长度字段,表示插入成功。

顺序表的销毁(防止内存泄漏)

void destroy(Seqlist* seqlist) {
    if (!seqlist) {
        printf("Destroy error in line %d\n", __LINE__);
        return;
    }
    free(seqlist->data);
    free(seqlist);
    printf("Destroyed!\n");
}

这段代码定义了一个函数 destroy,其目的是销毁(释放内存)一个已经创建的顺序表,并清理相关资源。以下是对这段代码的详细解释:

  1. void destroy(Seqlist* seqlist) {: 这是一个函数定义,它接受一个参数,即指向顺序表结构体的指针 seqlist,用于表示要销毁的顺序表。

  2. if (!seqlist) { ... }: 函数的第一部分是错误检查。它检查传入的 seqlist 指针是否为 NULL,以确保顺序表已正确初始化。如果 seqlistNULL,表示顺序表尚未分配内存或已经被销毁,函数会打印一条错误信息并返回,不执行销毁操作。

  3. free(seqlist->data);: 如果 seqlist 不为 NULL,则表示顺序表已经初始化。这部分代码使用 free 函数释放存储顺序表元素的内存块 seqlist->data。这是为了防止内存泄漏,将之前动态分配的元素数据内存释放。

  4. free(seqlist);: 接着,函数使用 free 函数释放存储顺序表控制信息的内存块 seqlist,这样可以释放整个顺序表的内存。

  5. printf("Destroyed!\n");: 最后,函数打印一条消息表示销毁操作已完成。

总结起来,这个函数的主要功能是销毁一个已经创建的顺序表,并释放相应的内存资源,以防止内存泄漏。在执行之前,它会进行一次错误检查,以确保顺序表已正确初始化。如果检查通过,函数会释放元素数据的内存和顺序表控制信息的内存,并打印销毁完成的消息。这个函数在不再需要使用顺序表时非常有用。

在main函数中的测试

int main() {
    Seqlist* seqlist = create(5);
    int a = 999, b = 2, c = 3, d = 4, e = 5;
    set_value(seqlist, a);
    set_value(seqlist, b);
    set_value(seqlist, c);
    set_value(seqlist, d);
    set_value(seqlist, e);
    int i = 0, data = 0;
    while (i < seqlist->length) {
        data = get_value(seqlist, i+1);
        printf("%d data is %d\n", i, seqlist->data[i]);
        i++;
    }
    printf("this length is %d\n", seqlist->length);
    printf("this capacity is %d\n", seqlist->capacity);
    destroy(seqlist);
    return 0;	
}

运行结果

这段代码演示了如何使用你之前定义的顺序表相关函数来创建、初始化、插入、获取元素、打印元素值,最后销毁顺序表。让我解释一下代码的执行流程:

  1. Seqlist* seqlist = create(5);: 首先,代码调用 create 函数来创建一个容量为5的顺序表,并将返回的顺序表指针赋给 seqlist。此时,顺序表被初始化为空,长度为0。

  2. int a = 1, b = 2, c = 3, d = 4, e = 5;: 然后,代码定义了五个整数变量 abcde,分别赋予它们不同的整数值。

  3. set_value(seqlist, a);: 使用 set_value 函数将整数 a 添加到顺序表中。

  4. 类似地,通过调用 set_value 函数,将整数 bcde 逐个添加到顺序表中。

  5. int i = 0, data = 0;: 定义了两个整数变量 idatai 用于迭代访问顺序表的元素,data 用于存储获取的元素值。

  6. while (i < seqlist->length) { ... }: 这是一个循环,它会迭代访问顺序表的元素,从索引0开始,一直到索引 seqlist->length - 1

  7. data = get_value(seqlist, i+1);: 在循环中,代码调用 get_value 函数获取顺序表中索引 i+1 处的元素值,并将其存储在 data 变量中。

  8. printf("%d data is %d\n", i, seqlist->data[i]);: 然后,代码使用 printf 函数打印索引 i 和对应的元素值,以展示顺序表的内容。

  9. i++;: 循环迭代变量 i 递增,继续下一个元素的访问。

  10. 循环会一直执行,直到遍历完所有的元素。

  11. printf("this length is %d\n", seqlist->length);: 最后,代码打印顺序表的长度和容量信息。

  12. destroy(seqlist);: 最后,代码调用 destroy 函数销毁顺序表,释放相应的内存资源。

总的来说,这段代码演示了如何创建、初始化、插入元素、获取元素值、打印元素值和销毁顺序表。在循环中,它遍历了整个顺序表,打印出了每个元素的值。在程序结束时,顺序表的内存也被正确地释放,以防止内存泄漏。

delete函数测试

 int a = 1, b = 2, c = 3, d = 4,e = 5;
    set_value(seqlist, a);
    set_value(seqlist, b);
    set_value(seqlist, c);
    set_value(seqlist, d);
    set_value(seqlist, e);
    delete_value(seqlist,1);

insert函数测试

int a = 1, b = 2, c = 3, d = 4;
    set_value(seqlist, a);
    set_value(seqlist, b);
    set_value(seqlist, c);
    set_value(seqlist, d);
    insert(seqlist, 1,1000);

运行结果

顺序表的应用场景

顺序表是一种常见的线性数据结构,适用于许多应用场景。以下是一些顺序表的应用场景:

  1. 数组的模拟: 顺序表可以用于模拟数组,因为它们在内存中连续存储数据。这种情况下,顺序表提供了动态大小、方便的插入和删除等操作,相比原始数组更加灵活。

  2. 数据库系统: 数据库中的表通常使用顺序表的形式进行存储。每个表的行可以视为顺序表中的元素,每列对应于表中的字段。

  3. 图形图像处理: 顺序表可用于存储像素值或颜色信息。图像的每一行或每一列可以表示为顺序表的一个元素,便于图像处理和分析。

  4. 嵌入式系统: 在嵌入式系统中,顺序表可以用于存储传感器数据、控制状态信息等。它们通常用于在资源受限的环境中高效管理数据。

  5. 日程安排和日历应用: 顺序表可以用于管理日程安排和日历事件。每个事件可以表示为顺序表中的一个元素,便于对事件的添加、删除和查询。

  6. 文件系统: 文件系统通常使用顺序表来管理磁盘上的文件和目录。每个文件或目录可以表示为顺序表中的一个元素,用于高效的文件访问。

  7. 音频处理: 音频数据可以存储在顺序表中,每个采样点或音频帧对应于一个顺序表元素。这有助于音频录制、编辑和处理。

  8. 图书管理系统: 图书管理系统可以使用顺序表来存储图书信息,每本书可以表示为顺序表中的一个元素,包括书名、作者、ISBN 等信息。

  9. 学生成绩管理: 学生成绩可以存储在顺序表中,每个学生的成绩记录可以表示为顺序表中的一个元素,方便成绩查询和统计。

  10. 缓存管理: 缓存中的数据可以使用顺序表进行存储,缓存的大小和替换策略可以通过顺序表来控制。

总之,顺序表是一种通用的数据结构,适用于各种需要管理和操作线性数据集合的应用场景。它的优点包括内存连续性、高效的随机访问和简单的实现,但也需要考虑动态扩展和收缩、插入和删除元素的性能等方面的问题,具体应用时需要根据需求权衡利弊。

总结:

顺序表(Sequential List)是一种经典的线性数据结构,它在内存中以连续的方式存储元素,通常以数组的形式实现。以下是对顺序表的总结:

1. **连续存储结构**:顺序表中的元素在内存中是连续存储的,这使得随机访问非常高效,可以根据索引直接访问任何元素。

2. **固定或动态容量**:顺序表可以具有固定容量,也可以动态扩展。如果容量不够,需要进行扩容操作,通常会分配更大的内存块,并将原有数据复制到新内存中。

3. **适用场景**:顺序表适用于需要频繁随机访问元素的场景,例如模拟数组、数据库表、图形图像处理、文件系统、音频处理等。

4. **插入和删除的复杂度**:在顺序表中插入和删除元素通常需要移动其他元素,因此其复杂度是 O(n),其中 n 是元素数量。这导致在大量插入和删除操作的情况下,性能可能不如链表。

5. **元素的索引**:顺序表的元素索引通常从1开始或从0开始,具体取决于编程语言或实现。

6. **内存占用**:顺序表可能会浪费一些内存空间,因为容量需要预先分配。但相对于链表等数据结构,其额外开销相对较小。

7. **动态数组**:动态数组是一种常见的顺序表实现,它可以动态调整大小以适应元素的增加或减少,是许多编程语言中的标准数据结构之一。

8. **操作方法**:顺序表通常提供插入、删除、查找、获取长度、获取容量等操作方法,这些方法使得对数据的操作更加方便。

总的来说,顺序表是一种重要的数据结构,适用于许多不同的应用场景。在使用顺序表时,需要权衡其高效的随机访问能力与插入删除操作的性能,并根据具体的需求选择合适的数据结构。

另附源码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct {
    int length;
    int capacity;
    int *data;
} Seqlist;

Seqlist* create(int capacity);
void set_value(Seqlist* seqlist, int data);
int get_value(Seqlist* seqlist, int index);
void insert(Seqlist* seqlist, int index, int data);
void delete_value(Seqlist* seqlist, int index);
void destroy(Seqlist* seqlist);

int main() {
    Seqlist* seqlist = create(5);
    int a = 1, b = 2, c = 3, d = 4,e = 5;
    set_value(seqlist, a);
    set_value(seqlist, b);
    set_value(seqlist, c);
    set_value(seqlist, d);
    set_value(seqlist, e);
    delete_value(seqlist,1);
    int i = 0, data = 0;
    while (i < seqlist->length) {
        data = get_value(seqlist, i+1);
        printf("%d data is %d\n", i, seqlist->data[i]);
        i++;
    }
    printf("this length is %d\n", seqlist->length);
    printf("this capacity is %d\n", seqlist->capacity);
    destroy(seqlist);
    return 0;	
}

Seqlist* create(int capacity) {
    Seqlist* seqlist = (Seqlist*)malloc(sizeof(Seqlist));
    if (!seqlist) {
        printf("Create error in line %d!\n", __LINE__);
        return NULL;
    }
    memset(seqlist, 0, sizeof(Seqlist));
    seqlist->capacity = capacity;
    seqlist->data = (int*)malloc(sizeof(int) * capacity);
    if (!seqlist->data) {
        printf("Create error in line %d!\n", __LINE__);
        free(seqlist);
        return NULL;
    }
    printf("Init!\n");
    return seqlist;
}

void set_value(Seqlist* seqlist, int data) {
    if (!seqlist || !seqlist->data) {
        printf("Set error in line %d\n", __LINE__);
        return;
    }
    if (seqlist->length == seqlist->capacity) {
        printf("Error: List is full. Cannot add more elements.\n");
        return;
    }
    seqlist->data[seqlist->length] = data;
    seqlist->length++;
}

int get_value(Seqlist* seqlist, int index) {
    if (!seqlist || index > seqlist->length || index <= 0) {
        printf("Get error in line %d\n", __LINE__);
        return -1;
    }
    return (seqlist->data[index-1]);
}

void delete_value(Seqlist* seqlist, int index) {
    if (!seqlist || index > seqlist->length || index <= 0) {
        printf("Delete error in line %d\n", __LINE__);
        return;
    }
    for (int i = index-1; i < seqlist->length - 1; i++) {
        seqlist->data[i] = seqlist->data[i+1];
    }
    seqlist->length--;
}

void insert(Seqlist* seqlist, int index, int data) {
    if (!seqlist || index > seqlist->length+1 || index <= 0) {
        printf("Insert error in line %d\n", __LINE__);
        return;
    }
    if (seqlist->length == seqlist->capacity) {
        printf("Insertion error: The list is full.\n");
        return;
    }
    for (int i = seqlist->length-1; i >= index - 1; i--) {
        seqlist->data[i+1] = seqlist->data[i];
    }
    seqlist->data[index-1] = data;
    seqlist->length++;
}

void destroy(Seqlist* seqlist) {
    if (!seqlist) {
        printf("Destroy error in line %d\n", __LINE__);
        return;
    }
    free(seqlist->data);
    free(seqlist);
    printf("Destroyed!\n");
}

编者的话:

该文章文案部分由Gpt参与编写,但代码设计,逻辑设计均为作者独有编写,转载请标明出处!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值