【数据结构】顺序表的C语言实现-入门必看(上)

简介: 【数据结构】顺序表的C语言实现-入门必看(上)

1.线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。是广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串……

线性表逻辑上线性结构,但在物理结构上并不一定连续,通常以数组和链式结构形式存储。

2.顺序表

2.1概念及结构

顺序表是一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改

分类:

1.静态顺序表:使用定长数组存储

缺点:不能灵活控制存储大小

#pragma once//防止头文件被重复包含
//等价于
//ifndef _SEQLIST_H_
//define _SEQLIST_H_
#include<stdio.h>
#include<string.h>
//增强程序可维护性
#define MAX_SIZE 100
typedef int SQDataType;
//静态的
struct SeqList
{
  SQDataType a[MAX_SIZE];
  int size;
};
/*typedef struct SeqList
{
  SQDataType a[MAX_SIZE];
  int size;
}SL;
*/
//动态的
typedef struct SeqList
{
  SQDataType*a;
  int size;//有效数据的个数
  int capacity;//容量
}SL;
typedef struct SeqList SL;
//初始化接口函数
void SeqListInit(SL*ps);
//endif

2.动态顺序表:使用动态开辟的数组存储

2.2接口实现

3.实现动态顺序表

1.SeqList.h:头文件,结构、常量的定义,接口函数的申明

2.test.c:用于动态顺序表功能的测试

3.SeqList.c:接口函数的实现

3.1结构的定义

1.data指针:指向动态开辟空间

2.size变量:记录当前有效数据的个数

3.capacity变量:记录当前容量

typedef struct SeqList
{
  SLDataType* a;
  int sz;// 表示数组中存储了多少个数据
  int capacity;// 数组实际能存数据的空间容量是多大
}SL;

当有效数据个数size和capacity相等时,说明当前顺序表空间已满,需要进行扩容。

3.2 接口函数

增删查改等功能我们会封装成函数,而当我们调用时,就会对接到对应函数,所以我们称这些函数为接口函数。

void SeqListInit(SL* ps);// 初始化
void SeqListCheckCapacity(SL* ps);// 检查增容
void SeqListPushBack(SL* ps, SLDataType x);// 尾插
void SeqListPopBack(SL* ps);// 尾删
void SeqListPushFront(SL* ps, SLDataType x);// 头插
void SeqListPopFront(SL* ps);// 头删
void SeqListPrint(SL* ps);// 打印
void SeqListDestory(SL* ps);// 销毁
int SeqListFind(SL* ps, SLDataType x);// 查找
void SeqListInsert(SL* ps, int pos, SLDataType x);// 指定下标位置插入
void SeqListErase(SL* ps, int pos);// 指定下标位置删除
void SeqListModify(SL* ps, int pos, int x);// 修改

命名风格与C++标准库类似

3.2.1 初始化

顺序表在进行操作之前,需要先将其内容进行初始化,防止之后操作时出错。

void SeqListInit(SL* ps);

void SeqListInit(SL* ps)
{
  assert(ps);
  ps->a = NULL;// 置空
  ps->sz = 0;
  ps->capacity = 0;// 初始大小和容量设定为0
}

注意参数不能为结构体SL s1),因为实参传参时会形成一份临时拷贝,叫做形参。当我们在函数中对形参的内容进行修改时,不会影响到实参,所以需要传地址(SL *ps)。

3.2.2 检查增容

当顺序表插入数据时:

1.顺序表没有空间

2.空间不够,需要扩容

3.空间足够,插入数据

void SeqListCheckCapacity(SL* ps)
{
  assert(ps);
  // 顺序表没有空间or顺序表空间不足
  if (ps->sz == ps->capacity)
  {
    int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
    // realloc在起始地址为空指针时,和malloc一样效果
    //空间不足,扩两倍
    SLDataType* tmp = (SLDataType*)realloc(ps->a, capacity *2* sizeof(SLDataType));
    //如果扩容失败,打印扩容失败
    if (tmp == NULL)
    {
      printf("realloc fail\n");
      exit(-1);//结束程序
    }
    else
    {
      ps->a = tmp;
      ps->capacity = newcapacity;
    }
  }
}

3.2.3 打印

在每次操作后,可以打印出顺序表,观察操作情况:

void SeqListPrint(SL* ps);// 打印

void SeqListPrint(SL* ps)
{
  assert(ps);
  for (int i = 0; i < ps->sz; i++)
  {
    printf("%d ", ps->a[i]);
  }
}

3.2.3 尾插

void SeqListPushBack(SL* ps, SLDataType x)

void SeqListPushBack(SL* ps, SLDataType x)
{
  assert(ps);
  SeqListCheckCapacity(ps);// 检查增容
  ps->a[ps->sz] = x;// 在尾部插入
  ps->sz++;
}

3.2.5 头插

void SeqListPushBack(SL* ps, SLDataType x)

void SeqListPushFront(SL* ps, SLDataType x)
{
  assert(ps);
  SeqListCheckCapacity(ps);// 检查增容
  //挪动数据.保证原来数据不被覆盖
  int end=ps->sz-1;
  while(end>=0)//一直挪动0下标
  {
  ps->a[end+1]=ps->a[end];
  end--;
  }
  ps->a[0]=x;
  ps->sz++;
}

3.2.6 头删

void SeqListPopFront(SL* ps);

void SeqListPopFront(SL* ps)
{
  assert(ps->sz > 0);// 暴力处理,sz为0时,不能头删
  // 挪动数据
  int start = 1;
  while (start <= ps->sz - 1)
  {
    ps->a[start - 1] = ps->a[start];
    start++;
  }
    // memmove(ps->a, ps->a + 1, (ps->sz - 1) * sizeof(SLDataType));
    // 这样也可以,将1下标开始的元素,向前移动sz-1个单位
    // 但是并不推荐,还是自己动手实现比较好
  ps->sz--;
}
相关文章
|
2月前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
55 1
|
2月前
|
存储 算法 搜索推荐
【趣学C语言和数据结构100例】91-95
本文涵盖多个经典算法问题的C语言实现,包括堆排序、归并排序、从长整型变量中提取偶数位数、工人信息排序及无向图是否为树的判断。通过这些问题,读者可以深入了解排序算法、数据处理方法和图论基础知识,提升编程能力和算法理解。
56 4
|
2月前
|
存储 机器学习/深度学习 搜索推荐
【趣学C语言和数据结构100例】86-90
本文介绍并用C语言实现了五种经典排序算法:直接插入排序、折半插入排序、冒泡排序、快速排序和简单选择排序。每种算法都有其特点和适用场景,如直接插入排序适合小规模或基本有序的数据,快速排序则适用于大规模数据集,具有较高的效率。通过学习这些算法,读者可以加深对数据结构和算法设计的理解,提升解决实际问题的能力。
49 4
|
2月前
|
存储 算法 数据处理
【趣学C语言和数据结构100例】81-85
本文介绍了五个经典算法问题及其C语言实现,涵盖图论与树结构的基础知识。包括使用BFS求解单源最短路径、统计有向图中入度或出度为0的点数、统计无向无权图各顶点的度、折半查找及二叉排序树的查找。这些算法不仅理论意义重大,且在实际应用中极为广泛,有助于提升编程能力和数据结构理解。
54 4
|
1月前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
92 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
12天前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
74 5
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
67 1
|
C语言
C语言顺序表,合并并排序(代码注释讲解)
C语言顺序表,合并并排序(代码注释讲解)
369 0
|
1月前
|
存储 C语言 开发者
【C语言】字符串操作函数详解
这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
69 10