纯C语言实现数据结构顺序表

2023-10-26

一、顺序表的概念及结构

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

顺序表一般可以分为:

  1. 静态顺序表:使用定长数组存储。
  2. 动态顺序表:使用动态开辟的数组存储。
// 顺序表的静态存储
#define N 7
typedef int DataType;
typedef struct SeqList
{
	DataType array[N]; // 定长数组
 	size_t size; 	   // 有效数据的个数
}SeqList;
// 顺序表的动态存储
typedef struct SeqList
{
	DataType* array;  // 指向动态开辟的数组
	size_t size ; 	  // 有效数据个数
	size_t capicity ; // 容量空间的大小
}SeqList;

image-20220504112349543

二、顺序表的实现

1.顺序表的创建

typedef int DateType;	//为了方便的改变数据的类型

typedef struct SeqList
{
	DateType* array;	//指向动态开辟的数组
	int size;			//有效数据个数
	int capacity;		//容量空间的大小
}SeqList;

2.顺序表初始化

void SeqListInit(SeqList* ps)
{
	ps->array = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

3.顺序表销毁

void SeqListDestory(SeqList* ps)
{
	assert(ps);				//判断指针是否为空
	assert(ps->capacity);	//判断容量空间大小是否为0

	free(ps->array);
	ps->array = NULL;//使用free后,随时置空,养成好习惯
	ps->size = 0;
	ps->capacity = 0;
}

4.顺序表打印

void SeqListPrint(SeqList* ps)
{
	assert(ps);			//判断指针是否为空
	assert(ps->size);	//判断有效数据个数是否为0

	for (int i = 0; i < ps->size; ++i)
	{
		printf("%d ", ps->array[i]);
	}
	printf("\n");
}

5.检查空间,如果满了,进行增容

void SeqListCheckCapacity(SeqList* ps)//不作为接口,在函数内部调用
{
	assert(ps);//判断指针是否为空

	if (ps->size == ps->capacity)//当有效数据个数==容量空间大小时,进行增容
	{
        //新容量大小一般扩大为二倍,当容量为0时,设置大小为4个结构体,当容量不为0时,扩大二倍。
		int newCapacity = (ps->capacity == 0) ? 4 : (ps->capacity * 2);
        //使用realloc在原数组后增容,即使没有原数组,realloc也会新创建一个数组
		DateType* newArray = (DateType*)realloc(ps->array, sizeof(DateType) * newCapacity);
		if (newArray == NULL)//使用realloc后判断指针是否为空,增容是否成功
		{
			printf("realloc fail!\n");
			exit(-1);
		}
		ps->array = newArray;//更新数组地址
		ps->capacity = newCapacity;//更新容量空间大小
	}
}

6.尾部插入一个数据

void SeqListPushBack(SeqList* ps, DateType x)
{
	assert(ps);//判断指针是否为空

	SeqListCheckCapacity(ps);//判断是否增容
	//由于数组的下标是由0开始,则size为下标处的位置就是插入数据的位置
	ps->array[ps->size] = x;//在尾部插入数据
	++ps->size;//插入数据后,有效数据个数增大1
}

7.头部插入一个数据

void SeqListPushFront(SeqList* ps, DateType x)
{
	assert(ps);//判断指针是否为空

	SeqListCheckCapacity(ps);//判断是否增容
	//在头部插入一个数据,需要把数组的内容整体往后移动一个位置
	int end = ps->size - 1;
	while (end >= 0)
	{
		ps->array[end + 1] = ps->array[end];
		--end;
	}
	ps->array[0] = x;//在头部插入数据
	++ps->size;//插入数据后,有效数据个数增大1
}

8.尾部删除一个数据

void SeqListPopBack(SeqList* ps)
{
	assert(ps);			//判断指针是否为空
	assert(ps->size);	//判断有效数据个数是否为0

	--ps->size;//删除一个数据,直接让有效数据个数减1,即(减小下标,使无法访问)。
}

9.头部删除一个数据

void SeqListPopFront(SeqList* ps)
{
	assert(ps);			//判断指针是否为空
	assert(ps->size);	//判断有效数据个数是否为0
	//在头部删除一个数据,需要把数组中下标为0向后的内容整体往前移动一个位置
	int begin = 1;
	while (begin < ps->size)
	{
		ps->array[begin - 1] = ps->array[begin];
		++begin;
	}
	--ps->size;//删除一个数据,直接让有效数据个数减1,即(减小下标,使无法访问)。
}

10.顺序表的查找

int SeqListFind(SeqList* ps, DateType x)
{
	assert(ps);			//判断指针是否为空
	assert(ps->size);	//判断有效数据个数是否为0
	//遍历数组,找到了返回下标,找不到返回-1
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->array[i] == x)
		{
			return i;
		}
	}
	return -1;
}

11.顺序表在pos位置插入一个数据

void SeqListInsert(SeqList* ps, int pos, DateType x)
{
	assert(ps);//判断指针是否为空
	assert(pos >= 0 && pos <= ps->size);//需要插入的位置必须在[0,size]

	SeqListCheckCapacity(ps);//判断是否增容
	//在pos位置插入一个数据,需要把数组中pos位置及向后位置的内容整体往后移动一个位置
	int end = ps->size - 1;
	while (end >= pos)
	{
		ps->array[end + 1] = ps->array[end];
		--end;
	}
	ps->array[pos] = x;//在pos位置插入数据
	++ps->size;//插入数据后,有效数据个数增大1
}

注意:

当pos为0时,完全可以充当头部插入一个数据

当pos为size时,完全可以充当尾部插入一个数据

12.顺序表删除pos位置的数据

void SeqListErase(SeqList* ps, int pos)
{
	assert(ps);//判断指针是否为空
	assert(ps->size);//判断有效数据个数是否为0
	assert(pos >= 0 && pos < ps->size);//需要插入的位置必须在[0,size)
	//删除pos位置的数据,需要把数组中pos位置向后的内容整体往前移动一个位置
	int begin = pos + 1;
	while (begin < ps->size)
	{
		ps->array[begin - 1] = ps->array[begin];
		++begin;
	}
	--ps->size;//删除一个数据,直接让有效数据个数减1,即(减小下标,使无法访问)。
}

注意:

当pos为0时,完全可以充当头部删除一个数据

当pos为size时,完全可以充当尾部删除一个数据

三、总结

  1. 每个接口,都要判断指针是否为空(除初始化接口,创建接口)
  2. 销毁时,需要判断容量空间大小是否为0
  3. 打印时,需要判断有效数据个数是否为0
  4. 查找时,需要判断有效数据个数是否为0
  5. 插入数据时,需要判断是否增容,插入位置向后位置整体向挪动一个位置,size + 1
  6. 删除数据时,需要判断有效数据个数是否为0,删除位置向后位置整体向挪动一个位置,size - 1
  7. 涉及到传入pos位置的函数,要判断pos的合法性
  8. free后,要置空,养成好习惯
  9. 每次扩容一般扩为二倍,在删除数据时,不会减小容量,只会减小有效数据个数
  10. 为了方便的改变数组的类型,将int重命名为DateType

四、完整代码

#SeqList.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int DateType;

typedef struct SeqList
{
	DateType* array;
	int size;
	int capacity;
}SeqList;

void SeqListInit(SeqList* ps);
void SeqListDestory(SeqList* ps);
void SeqListPrint(SeqList* ps);
void SeqListPushBack(SeqList* ps, DateType x);
void SeqListPushFront(SeqList* ps, DateType x);
void SeqListPopBack(SeqList* ps);
void SeqListPopFront(SeqList* ps);
int SeqListFind(SeqList* ps, DateType x);
void SeqListInsert(SeqList* ps, int pos, DateType x);
void SeqListErase(SeqList* ps, int pos);
//SeqList.c

#include "SeqList.h"

void SeqListInit(SeqList* ps)
{
	ps->array = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

void SeqListDestory(SeqList* ps)
{
	assert(ps);
	assert(ps->capacity);

	free(ps->array);
	ps->array = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

void SeqListPrint(SeqList* ps)
{
	assert(ps);
	assert(ps->size);

	for (int i = 0; i < ps->size; ++i)
	{
		printf("%d ", ps->array[i]);
	}
	printf("\n");
}

void SeqListCheckCapacity(SeqList* ps)
{
	assert(ps);

	if (ps->size == ps->capacity)
	{
		int newCapacity = (ps->capacity == 0) ? 4 : (ps->capacity * 2);
		DateType* newArray = (DateType*)realloc(ps->array, sizeof(DateType) * newCapacity);
		if (newArray == NULL)
		{
			printf("realloc fail!\n");
			exit(-1);
		}
		ps->array = newArray;
		ps->capacity = newCapacity;
	}
}

void SeqListPushBack(SeqList* ps, DateType x)
{
	assert(ps);

	SeqListCheckCapacity(ps);

	ps->array[ps->size] = x;
	++ps->size;

	//SeqListInsert(ps, ps->size, x);
}

void SeqListPushFront(SeqList* ps, DateType x)
{
	assert(ps);

	SeqListCheckCapacity(ps);

	int end = ps->size - 1;
	while (end >= 0)
	{
		ps->array[end + 1] = ps->array[end];
		--end;
	}
	ps->array[0] = x;
	++ps->size;

	//SeqListInsert(ps, 0, x);
}

void SeqListPopBack(SeqList* ps)
{
	assert(ps);
	assert(ps->size);

	--ps->size;

	//SeqListErase(ps, ps->size - 1);
}

void SeqListPopFront(SeqList* ps)
{
	assert(ps);
	assert(ps->size);

	int begin = 1;
	while (begin < ps->size)
	{
		ps->array[begin - 1] = ps->array[begin];
		++begin;
	}
	--ps->size;

	//SeqListErase(ps, 0);
}

int SeqListFind(SeqList* ps, DateType x)
{
	assert(ps);
	assert(ps->size);

	for (int i = 0; i < ps->size; i++)
	{
		if (ps->array[i] == x)
		{
			return i;
		}
	}
	return -1;
}

void SeqListInsert(SeqList* ps, int pos, DateType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);

	SeqListCheckCapacity(ps);

	int end = ps->size - 1;
	while (end >= pos)
	{
		ps->array[end + 1] = ps->array[end];
		--end;
	}
	ps->array[pos] = x;
	++ps->size;
}

void SeqListErase(SeqList* ps, int pos)
{
	assert(ps);
	assert(ps->size);
	assert(pos >= 0 && pos < ps->size);

	int begin = pos + 1;
	while (begin < ps->size)
	{
		ps->array[begin - 1] = ps->array[begin];
		++begin;
	}
	--ps->size;
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

纯C语言实现数据结构顺序表 的相关文章

  • 多个源的 makefile

    在学习 make 文件时 我试图为多个源目录编写一个 make 文件 似乎我在某个地方错了 这是我的代码结构 directory common fun2 c inc fun h src fun1 c main c 这是我的生成文件 CC c
  • 将 new 与 decltype 一起使用

    T t T is an implementation detail t new T want to avoid naming T to allow for flexibility t new decltype t error cannot
  • 删除是如何工作的? [复制]

    这个问题在这里已经有答案了 可能的重复 C 编程 free 如何知道要释放多少 https stackoverflow com questions 1518711 c programming how does free know how m
  • 检测wlan是否关闭

    任何人都可以给我一个提示 如何在 Windows Phone 上以编程方式检测 C 8 1 应用程序 不是 8 0 是否启用 禁用 WLAN 我不想更改这些设置 只是需要知道 该解决方案是一个 Windows 8 1 通用应用程序 Wind
  • 在现代 C++ 中,临时生命周期延长何时有用?

    在 C 中 您可以将函数的返回值 返回值 而不是引用 绑定到 const 引用 并且代码仍然有效 因为该临时对象的生命周期将延长到作用域末尾 例如 std string get string return abc void f const
  • 在 omp 并行 for 循环中使用 unique_ptr 会导致 SEG.FAULT

    采取以下代码 include
  • 增强精神、递归和堆栈溢出

    为什么下面的代码在运行时崩溃 它会给出堆栈溢出错误 include
  • MFC:如何设置CEdit框的焦点?

    我正在开发我的第一个简单的 MFC 项目 但我正在努力解决一个问题 想要设置所有的焦点CEdit其中一个对话框中的框 我的想法是 当打开对话框时 焦点位于第一个编辑框上 然后使用 选项卡 在它们之间交换 我看到了方法SetFocus 但我无
  • 将接口转换为其具体实现对象,反之亦然?

    在 C 中 当我有一个接口和几个具体实现时 我可以将接口强制转换为具体类型 还是将具体类型强制转换为接口 这种情况下的规则是什么 Java 和 C 中都允许这两个方向 向下转型需要显式转型 如果对象类型不正确 可能会抛出异常 然而 向上转换
  • 根据对象变量搜索对象列表

    我有一个对象列表 这些对象具有三个变量 ID 名称和值 这个列表中可能有很多对象 我需要根据ID或Name找到一个对象 并更改值 例子 class objec public string Name public int UID public
  • 如何对 NServiceBus.Configure.WithWeb() 进行单元测试?

    我正在构建一个 WCF 服务 该服务接收外部 IP 上的请求并将其转换为通过 NServiceBus 发送的消息 我的单元测试之一调用Global Application Start 它执行应用程序的配置 然后尝试将 Web 服务解析为 验
  • 为什么 Cdecl 调用在“标准”P/Invoke 约定中经常不匹配?

    我正在开发一个相当大的代码库 其中 C 功能是从 C P Invoked 的 我们的代码库中有很多调用 例如 C extern C int stdcall InvokedFunction int 使用相应的 C DllImport CPlu
  • 如何使用 NPOI 按地址(A1、A2)获取 Excel 单元格值

    我有一个 Excel 单元格地址 例如 A1 A2 如何使用 C 中的 NPOI 框架以编程方式访问此单元格 我找到的一些 Java POI 示例代码 CellReference cr new CellReference A1 row my
  • 使用 GCC 生成可读的程序集?

    我想知道如何使用GCC http en wikipedia org wiki GNU Compiler Collection在我的 C 源文件中转储机器代码的助记符版本 这样我就可以看到我的代码被编译成什么 你可以使用 Java 来做到这一
  • Linux mremap 不释放旧映射?

    我需要一种方法将页面从一个虚拟地址范围复制到另一个虚拟地址范围 而无需实际复制数据 范围很大 延迟很重要 mremap 可以做到这一点 但问题是它也会删除旧的映射 由于我需要在多线程环境中执行此操作 因此我需要旧映射能够同时使用 因此稍后当
  • .NET 4 的条件编译[重复]

    这个问题在这里已经有答案了 可能的重复 条件编译和框架目标 https stackoverflow com questions 2923210 c sharp conditional compilation and framework ta
  • 如何在 winforms 应用程序的主屏幕显示之前显示欢迎屏幕?

    我想在应用程序启动时加载欢迎屏幕 然后用户单击欢迎屏幕上的按钮 然后关闭欢迎屏幕 最后显示主屏幕 static void Main startup method being called Application EnableVisualSt
  • 通过 Tab 键浏览 XML 文档字段

    In VB NET you can move through the fields in the XML member documentation with the Tab key 这在 C 中不起作用 还有其他方法吗 除了用鼠标将光标放在
  • 使用 using 声明时,非限定名称查找如何工作?

    根据 C 标准 这是格式错误还是格式良好 namespace M struct i namespace N static int i 1 using M i using N i int main sizeof i Clang 拒绝它 GCC
  • 如何将 SQL“LIKE”与 LINQ to Entities 结合使用?

    我有一个文本框 允许用户指定搜索字符串 包括通配符 例如 Joh Johnson mit ack on 在使用 LINQ to Entities 之前 我有一个存储过程 该存储过程将该字符串作为参数并执行以下操作 SELECT FROM T

随机推荐

  • 基于bp神经网络的房价预测,房价预测 神经网络

    Python 与深度学习有哪些与建筑设计相接轨的可能性 关注这个问题快一周了 到目前来说还是没发现什么太大的惊喜 我感觉建筑设计界还是要学习一个 不要看到深度学习很火 就弄个大新闻 把这玩意往建筑设计上搬呀 其实深度学习这事儿到底怎么就能和
  • LightGBM 源码学习 (2022-5)

    之前在Linux系统上调试的博文 LightGBM源码学习 准备篇 系统 MacOS 软件 Clion 感觉最新的commit可能有坑 退回到2021年年初的commit code link git checkout 967b45c6866
  • 【爬虫自动生成代码】Playwright系列文章二

    Playwright系列文章 目录 Playwright系列文章 前言 一 Playwright录制功能 二 使用步骤 1 查看命令参数 help 2 命令启动浏览器 总结 前言 Playwright是类似于selenium Pyppete
  • android support design jar,错误:程序类型已存在:android.support.design...

    我在构建项目时遇到以下错误 在这个项目中没有使用CoordinatorLayout 刚刚在build gradle中添加为依赖项 我使用的是Android Studio 3 2 Canary 4 logcat的 AGPBI kind err
  • uv纹理坐标设定与贴图规则

    1 什么是UV 对于三维模型 有两个最重要的坐标系统 一是顶点的位置 X Y Z 坐标 另一个就是UV坐标 什么是UV 简单的说 就是贴图影射到模型表面的依据 完整的说 其实应该是UVW 因为XYZ已经用过了 所以另选三个字母表示 U和V分
  • VUE 时间转换的几种方式

    时间转换 做一个项目肯定会关系到很多的数据类型 数据类型之间都是可以转化的 前端有时候从后端拿到的时间不符合标准 此时就需要转换以后再去使用 转换有两种方式 看你个人比较喜欢哪一种 这里已时间转换为例子 过滤器filter 全局过滤器 在m
  • unity 发布webGl ISS发布

    推荐 https blog csdn net weixin 43926289 article details 122943814 其他的按照步骤配置就行了 主要是 一定要按图来 OVER 另外说一下本地浏览器直接打开index 有些项目要求
  • mysql服务器多线程参数_MySQL服务器的线程数查看方法

    MySQL的variables和status是管理维护的利器 就类似Oracle的spfile和v 表 MySQL通过系统变量记录很多配置信息 比如最大连接数max connections mysql gt show variables l
  • Java从零开始追大牛系列_0

    在此先做做我介绍 鄙人二流大学通信工程专业一名大三 即将大四 学生 由于并无志向在专业学术领域有所建树 因此并未涌入考研大军 只求毕业后Java编程技术过硬 可寻的一份喜欢的工作 特此准备写词系列博客 因为软件并非自己专业 只是兴趣使然 但
  • 【Transformer】18、ACMix:On the Integration of Self-Attention and Convolution

    文章目录 一 背景和动机 二 方法 三 效果 一 背景和动机 卷积核自注意机制是两个很有效的特征提取方法 但这两个方法通常被认为是两种不同机制的方法 卷积方法是对局部进行特征抽取 全局特征共享 自注意力方法是全局像素的权重提取 本文作者认为
  • verilog手撕代码7——固定优先级仲裁器和轮询仲裁器

    文章目录 前言 一 固定优先级仲裁器 Fixed Priority Arbiter 1 case if语句实现 2 for循环语句实现参数化结构 二 轮询仲裁器 Round Robin Arbiter 1 case语句实现 2 for循环实
  • 在R语言中使用text函数可以在可视化图像中添加样本标签

    在R语言中使用text函数可以在可视化图像中添加样本标签 text函数允许我们在图形中的指定位置添加文本元素 这对于标记数据点 添加注释或创建自定义标签非常有用 在本文中 我们将学习如何使用R语言的text函数在可视化图像中添加样本标签 首
  • 电源模块的降额曲线

    大家好 这里是大话硬件 今天想写这篇文章来分享在前段时间了解的一个知识点 电源模块的降额曲线 为什么要写这个呢 对于专门做电源的同学来说 肯定觉得很简单 但是对于一个非电源行业的人来说 曲线应该如何解读 业内是如何测试出来的 不一定十分完全
  • Java-网络原理

    目录 一 网络互连 局域网LAN 广域网WAN 二 网络通信基础 IP地址 端口号 认识协议 三 五元组 四 协议分层 五 OSI七层模型 六 TCP IP五层 或四层 模型 网络分层对应 七 封装和分用 一 网络互连 随着时代的发展 越来
  • (超详细!)【C语言】单链表的增删查改(附图解,源码)

    单链表学习导航 一 前言 二 准备工作 1 对单链表运行原理的简单理解 2 区域化编辑 三 SList h头文件引用区 1 单链表节点的创建 2 单链表功能函数的声明 四 SListTest c测试区 五 SList c功能实现区 1 动态
  • Python类型强制转换和字符串的操作

    Python类型强制转换和字符串的操作 类型强制转换 字符串的操作 name I Love The World The Dog print name 0 下标取值 print len name 字符串长度 print name 2 倒数第二
  • 自定义属性

    TypeArray 用来简化资源类型判断 declare styleable 用来生成资源 ID 数组和对应的索引值 自定义属性的声明文件 values attrs xml
  • Eclipse SpringBoot jsp打包部署

    第一步 导入jar包依赖 a 打包方式设置为war b spring boot starter web内嵌tomcat c servlet api支持必须要 第二步 编写tom启动方式 把springBoot默认启动方式交给tomcat方式
  • AsyncTask使用总结

    概述 AsyncTask是由Android封装的一个轻量级异步抽象类 可以在线程池中执行后台任务 然后把执行的进度和最终结果传递给主线程并在主线程中更新UI AsynTask的源码如下 public abstract class Async
  • 纯C语言实现数据结构顺序表

    文章目录 一 顺序表的概念及结构 二 顺序表的实现 1 顺序表的创建 2 顺序表初始化 3 顺序表销毁 4 顺序表打印 5 检查空间 如果满了 进行增容 6 尾部插入一个数据 7 头部插入一个数据 8 尾部删除一个数据 9 头部删除一个数据