顺序表的C语言实现与解析

目录

引言

作者主页:共享家9527-CSDN博客

​编辑代码结构概览

[头文件( ST.h )要点](#头文件( ST.h )要点)

源文件要点

[1. 顺序表初始化( SeqListInit ):](#1. 顺序表初始化( SeqListInit ):)

[2. 顺序表销毁( SeqListDestroy ):](#2. 顺序表销毁( SeqListDestroy ):)

[3. 顺序表打印( SeqListPrint ):](#3. 顺序表打印( SeqListPrint ):)

[4. 检查并增容( cheakfull ):](#4. 检查并增容( cheakfull ):)

[5. 尾插法( SeqListPushBack ):](#5. 尾插法( SeqListPushBack ):)

[6. 头插法( SeqListPushFront ):](#6. 头插法( SeqListPushFront ):)

[7. 头删法( SeqListPopFront ):](#7. 头删法( SeqListPopFront ):)

[8. 尾删法( SeqListPopBack ):](#8. 尾删法( SeqListPopBack ):)

[9. 顺序表查找( SeqListFind ):](#9. 顺序表查找( SeqListFind ):)

[10. 在指定位置插入元素( SeqListInsert ):](#10. 在指定位置插入元素( SeqListInsert ):)

​编辑注意事项


引言

顺序表是一种线性数据结构,它使用一组连续的内存单元来存储数据元素。在C语言中,我们可以通过数组和一些辅助变量来实现顺序表。本文将详细解析上述提供的C语言代码,涵盖顺序表的初始化、销毁、插入、删除、查找等基本操作。

作者主页:共享家9527-CSDN博客

代码结构概览

整个代码分为两部分:头文件( .h )和源文件( .c )。头文件定义了顺序表的数据结构以及函数声明,源文件则包含了函数的具体实现。

头文件( ST.h )要点

cpp 复制代码
c
  
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int SLDateType;
typedef struct SeqList
{
    SLDateType* a;
    int size;
    int capacity;
}SeqList;

// 对数据的管理:增删查改 
void SeqListInit(SeqList* ps);
void SeqListDestroy(SeqList* ps);

void SeqListPrint(SeqList* ps);
void SeqListPushBack(SeqList* ps, SLDateType x);
void SeqListPushFront(SeqList* ps, SLDateType x);
void SeqListPopFront(SeqList* ps);
void SeqListPopBack(SeqList* ps);

// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);

1. 数据类型定义: SLDateType 被定义为 int ,这是顺序表中元素的数据类型。如果需要存储其他类型的数据,只需修改这一处定义。

2. 顺序表结构体: SeqList 结构体包含三个成员:

++- a 是一个指向 SLDateType 类型的指针,用于动态分配内存来存储顺序表的元素。

  • size 表示当前顺序表中已存储的元素个数。
  • capacity 表示顺序表当前分配的内存容量,即最多能存储的元素个数。++

**3. 函数声明:**声明了一系列对顺序表进行操作的函数,包括初始化、销毁、打印、插入、删除、查找等。这些函数的实现将在源文件中给出。

源文件要点

cpp 复制代码
c
  
#define _CRT_SECURE_NO_WARNINGS
#include"ST.h"

void SeqListInit(SeqList* ps)
{
    assert(ps);
    ps->a = (SLDateType*)malloc(sizeof(SLDateType));
    if (ps->a == NULL)
    {
        perror("malloc false");
        return;
    }
    ps->size = 0;
    ps->capacity = 4;
}
 

1. 顺序表初始化( SeqListInit ):

  • 使用 assert(ps) 来确保传入的顺序表指针不为空。这是一种防御性编程,有助于在开发阶段发现潜在的空指针引用错误。

  • 使用 malloc 函数为顺序表分配初始内存,大小为一个 SLDateType 类型的空间。如果 malloc 失败(返回 NULL ),使用 perror 打印错误信息并返回。

  • 将 size 初始化为0,表示顺序表中还没有元素, capacity 初始化为4,表示初始分配的内存可以容纳4个元素。

cpp 复制代码
 
c
  
void SeqListDestroy(SeqList* ps)
{
    assert(ps);
    free(ps->a);
    ps->a = NULL;
    ps->size = 0;
    ps->capacity = 0;
    ps = NULL;
}
 

2. 顺序表销毁( SeqListDestroy ):

  • 同样使用 assert(ps) 确保指针有效。

  • 使用 free 释放顺序表分配的内存,防止内存泄漏。

  • 将 ps->a 置为 NULL ,避免悬空指针。同时将 size 和 capacity 置为0,并尝试将 ps 指针也置为 NULL (不过这在函数外部不会生效,因为函数参数是值传递)。

cpp 复制代码
 
c
  
void SeqListPrint(SeqList* ps)
{
    assert(ps);
    for (int i = 0;i < ps->size;i++)
    {
        printf("%d ", ps->a[i]);
    }
    printf("\n");
}
 

3. 顺序表打印( SeqListPrint ):

  • 通过遍历顺序表,从索引0到 size - 1 ,打印每个元素的值,最后换行。
cpp 复制代码
 
c
  
void cheakfull(SeqList* ps)
{
    assert(ps);
    if (ps->capacity == ps->size)
    {
        SLDateType* tmp = (SeqList*)realloc(ps->a, ps->capacity * 2);
        if (tmp == NULL)
        {
            perror("realloc false");
            return;
        }
        ps->a = tmp;
        ps->capacity *= 2;
        printf("增容成功\n");
    }
}
 

4. 检查并增容( cheakfull ):

  • 检查顺序表当前元素个数 size 是否等于容量 capacity ,如果相等则表示顺序表已满,需要增容。

  • 使用 realloc 函数将顺序表的内存容量扩大为原来的2倍。如果 realloc 失败,打印错误信息并返回。

  • 更新 ps->a 指向新分配的内存,并将 capacity 更新为原来的2倍。

cpp 复制代码
 
c
  
void SeqListPushBack(SeqList* ps, SLDateType x)
{
    cheakfull(ps);
    assert(ps);
    ps->a[ps->size] = x;
    ps->size++;
}
 

5. 尾插法( SeqListPushBack ):

  • 首先调用 cheakfull 函数检查顺序表是否已满并进行增容。

  • 将元素 x 插入到顺序表的末尾(索引为 size 的位置),然后 size 加1。

cpp 复制代码
 
c
  
void SeqListPushFront(SeqList* ps, SLDateType x) 
{
    assert(ps);
    cheakfull(ps);
    for (int i = ps->size;i > 0;i--)
    {
        ps->a[i] = ps->a[i - 1];
    }
    ps->a[0] = x;
    ps->size++;
}
 
 

6. 头插法( SeqListPushFront ):

  • 检查顺序表是否需要增容。

  • 通过循环将顺序表中已有的元素从后往前依次向后移动一位,然后将新元素 x 插入到索引0的位置,最后 size 加1。注意这里循环条件是 i > 0 ,而不是 i >= 0 ,否则会导致数组越界。

cpp 复制代码
 
c
  
void SeqListPopFront(SeqList* ps) {
    assert(ps);
    for (int i = 0;i < ps->size - 1;i++)
    {
        ps->a[i] = ps->a[i + 1];
    }
    ps->size--;
}
 
 

7. 头删法( SeqListPopFront ):

  • 通过循环将顺序表中从索引1开始的元素依次向前移动一位,覆盖掉原来索引0的元素,然后 size 减1。注意这里循环条件是 i < ps->size - 1 ,防止数组越界。
cpp 复制代码
 
c
  
void SeqListPopBack(SeqList* ps) {
    assert(ps);
    assert(ps->size>0);
    ps->size--;
}
 

8. 尾删法( SeqListPopBack ):

  • 首先检查顺序表中是否有元素( size > 0 ),然后直接将 size 减1,相当于逻辑上删除了最后一个元素,而不需要实际修改数组中的元素值。
cpp 复制代码
 
c
  
// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x) {
    assert(ps);
    assert(ps->size > 0);
    for (int i = 0;i < ps->size;i++)
    {
        if (ps->a[i] == x)
        {
            return i;
        }
    }
    return -1;
}
 

9. 顺序表查找( SeqListFind ):

  • 遍历顺序表,从索引0到 size - 1 ,检查每个元素是否等于要查找的元素 x 。如果找到,返回该元素的索引;如果遍历完整个顺序表都没有找到,则返回 -1。
cpp 复制代码
 
c
  
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x) {
    assert(ps);
    assert(ps->size >= pos);
    cheakfull(ps);
    for (int i = ps->size;i > pos;i--)
    {
        ps->a[i] = ps->a[i - 1];
    }
    ps->a[pos] = x;
    ps->size++;
}
 
 

10. 在指定位置插入元素( SeqListInsert ):

  • 检查传入的位置 pos 是否合法( pos 小于等于当前 size )。

  • 检查顺序表是否需要增容。

  • 通过循环将从索引 size 到 pos + 1 的元素依次向后移动一位,然后将新元素 x 插入到索引 pos 的位置,最后 size 加1。

注意事项

  1. **内存管理:**在使用 malloc 和 realloc 分配内存时,一定要检查返回值是否为 NULL ,以防止内存操作错误。使用完内存后,要及时调用 free 释放内存,避免内存泄漏。

  2. 边界检查:在进行插入、删除、查找等操作时,要仔细检查数组索引是否越界。使用 assert 进行参数合法性检查是一个很好的习惯,可以帮助在开发阶段发现潜在的错误。

  3. 函数参数传递:注意C语言函数参数是值传递,如果需要修改传入的指针本身(如在 SeqListDestroy 中尝试将 ps 置为 NULL ),需要使用指针的指针或者返回修改后的指针。

通过上述对顺序表实现代码的详细解析,希望读者能够更好地理解顺序表这种数据结构在C语言中的实现方式以及相关操作的要点和注意事项。

相关推荐
SomeB1oody4 分钟前
【Python机器学习】3.2. 决策树理论(进阶):ID3算法、信息熵原理、信息增益
python·算法·决策树·机器学习
维齐洛波奇特利(male)16 分钟前
(暴力枚举 水题 长度为3的不同回文子序列)leetcode 1930
算法·leetcode·职场和发展
每次的天空18 分钟前
Android第四次面试总结(基础算法篇)
android·算法·面试
知舟不叙30 分钟前
机器学习——深入浅出理解朴素贝叶斯算法
人工智能·python·算法·机器学习
MelonTe39 分钟前
Raft学习笔记
算法·后端开发
CodeJourney.1 小时前
AI赋能办公:开启高效职场新时代
数据库·人工智能·算法
小成喝橙汁补维C1 小时前
C语言:基于链表实现栈
c语言·数据结构·算法
mochensage1 小时前
第16讲- 插入排序
数据结构·算法·排序算法
舔甜歌姬的EGUMI LEGACY1 小时前
【算法day13】整数转罗马数字&&罗马数字转整数
算法
平平无奇我要摘星星1 小时前
1.排序算法(学习自用)
python·算法·排序算法