追梦之旅【数据结构篇】——详解C语言动态实现顺序表

news2024/12/24 11:44:46

详解C语言动态实现顺序表~😎

  • 前言🙌
  • 顺序表概念及结构🙌
  • 功能函数的具体实现分析:🙌
    • 尾插函数具体实现:
    • 尾删函数具体实现:
    • 头插函数具体实现:
    • 头删插函数具体实现:
    • 任意插函数具体实现:
    • 任意删函数具体实现:
    • 销毁顺序表函数具体实现:
    • 查找函数具体实现:
    • 检查容量函数具体实现:
    • 初始化函数具体实现:
    • 打印函数具体实现:
  • 头文件全部源码分享🙌
  • 功能文件全部源码分享🙌
  • 测试文件代码🙌
  • 总结撒花💞

追梦之旅,你我同行

   
😎博客昵称:博客小梦
😊最喜欢的座右铭:全神贯注的上吧!!!
😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主!

😘博主小留言:哈喽!😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不多说,文章推上!欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘
在这里插入图片描述

前言🙌

    哈喽各位友友们😊,我今天又学到了很多有趣的知识现在迫不及待的想和大家分享一下!😘我仅已此文,手把手带领大家学习C语言动态实现顺序表~ 都是精华内容,可不要错过哟!!!😍😍😍

顺序表概念及结构🙌

   在实现顺序表之前,我们先要了解一下什么是顺序表,它的大概结构是怎么样的?其实顺序表是用一段物理地址连续的存储单元依次存储数据元素线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
在这里插入图片描述

顺序表一般可以分为:

  1. 静态顺序表:使用定长数组存储元素。
  2. 动态顺序表:使用动态开辟的数组存储。

其实静态实现和动态实现的方法都差不多,但是相比而言动态实现的顺序表的性能更优,实际应用的价值更大,比较灵活。

实现大概思路分析:

首先在头文件先定义结构体和各个功能函数的声明,并把有关的头文件包含上去。各个函数如何实现的,主要是对各个函数的实现,用到realloc动态开辟新节点的空间,用assert断言确保指针有效,通过画图来帮助理清代码实现的思路,指针的指向如何,要考虑哪些情况。然后再测试代码中,将上述代码都进行测试,显示结果。

功能函数的具体实现分析:🙌

尾插函数具体实现:

设计思路分析:

  • 首先设计一个检查容量的函数,保证有空间才能进行插入操作。
  • 将size为下标的元素改为x,别忘了将size++。
  • 或者实现任意插函数之后,而尾插作为其一种特殊情况,可以通过调用任意插函数来实现尾插的功能
//尾插
void SeqListPushBack(SL* p, DataSeqList x)
{
	/*SeqListCheckCapacity(p);
	p->arr[p->size] = x;
	p->size++;*/
	SeqListInsert(p, p->size, x);
}

尾删函数具体实现:

设计思路分析:

  • 先assert检查顺序表的元素个数,如果没有元素就不用再删了
  • 直接将size减减即可。这样其有效个数就少了一个,十分简单。
  • 或者实现任意删函数之后,而尾删作为其一种特殊情况,可以通过调用任意删函数来实现尾删的功能
//尾删
void SeqListPopBack(SL* p)
{
	/*assert(p->size);
	p->size--;*/
	SeqListEraes(p, p->size - 1);
}

头插函数具体实现:

设计思路分析:

  • 首先设计一个检查容量的函数,保证有空间才能进行插入操作。
  • 注意挪动数据如何挪,将控制条件控制好即可。
  • 将首元素改为x,别忘了将size++。
  • 或者实现任意插函数之后,而头插作为其一种特殊情况,可以通过调用任意插函数来实现头插的功能
//头插
void SeqListPushFront(SL* p, DataSeqList x)
{
	//SeqListCheckCapacity(p);
	挪动数据
	//int end = p->size - 1;
	//while (end >= 0)
	//{
	//	p->arr[end + 1] = p->arr[end];
	//	end--;
	//}
	//p->arr[0] = x;
	//p->size++;
	SeqListInsert(p,0, x);
}

头删插函数具体实现:

设计思路分析:

  • 先assert检查顺序表的元素个数,如果没有元素就不用再删了。
  • 注意数据挪动,可以采用画图分析的方法控制挪动数据的控制条件。
  • 不要忘了将size-减减
  • 或者实现任意删函数之后,而头删作为其一种特殊情况,可以通过调用任意删函数来实现头删的功能
//头删
void SeqListPopFront(SL* p)
{
	删完就不用删了
	//assert(p->size);
	//int begin = 1;
	//while (begin < p->size)
	//{
	//	p->arr[begin - 1] = p->arr[begin];
	//	begin++;
	//}
	//p->size--;
	SeqListEraes(p, 0);
}

任意插函数具体实现:

设计思路分析:

  • 先判断容量,有空间才进行插入操作。
  • 检查插入的合法性,在pos >= 0 && pos <= p->size 的范围才能进行插入
  • 注意数据挪动,可以采用画图分析的方法控制挪动数据的控制条件。
  • 别忘了将size加加
//任意插
void SeqListInsert(SL* p,int pos ,DataSeqList x)
{
	SeqListCheckCapacity(p);
	assert(pos >= 0 && pos <= p->size);
	int end = p->size - 1;
	while (end >= pos)
	{
		p->arr[end + 1] = p->arr[end];
		end--;
	}
	p->arr[pos] = x;
	p->size++;

}

任意删函数具体实现:

设计思路分析:

  • 先判断顺序表有没有数据,没有就不用删了。
  • 检查删的位置的合法性,在pos >= 0 && pos < p->size的范围才能进行删除。
  • 注意数据挪动,可以采用画图分析的方法控制挪动数据的控制条件。
  • 别忘了将size减减。
//任意删
void SeqListEraes(SL* p, int pos)
{
	//删完就不用删了
	assert(p->size);
	//删的合法性判断
	assert(pos >= 0 && pos < p->size);
	int begin = pos+1;
	while (begin < p->size)
	{
		p->arr[begin - 1] = p->arr[begin];
		begin++;
	}
	p->size--;
}

销毁顺序表函数具体实现:

设计思路分析:
因为顺序表的空间建立是动态开辟的,动态开辟的空间需要手动free释放

/销毁
void SeqListDestory(SL* p)
{
	free(p->arr);
	p->arr = NULL;
	p->capacity = p->size = 0;
}

查找函数具体实现:

设计思路分析:
这个比较简单,直接写个循环遍历一遍,找到了x就返回它的下标,找不到返回-1.

//查找
int SeqListFind(SL* p, DataSeqList x)
{
	assert(p);
	for (int i = 0; i < p->size; i++)
	{
		if (p->arr[i] == x)
		{
			return i;
		}
	}
	return -1;
}

检查容量函数具体实现:

设计思路分析:

  • 分为没有空间和空间满了两种情况进行。
  • 如果没有空间,就显动态分配四个数据大小的空间。
  • 如果空间存储满了,就动态扩容到原来的2倍空间
//检查容量
void SeqListCheckCapacity(SL* p)
{
	if (p->size == p->capacity)
	{
		int newcapacity = p->capacity == 0 ? 4 : p->capacity * 2;
		DataSeqList* tem = realloc(p->arr, newcapacity * sizeof(DataSeqList));
		assert(tem);
		p->arr = tem;
		p->capacity = newcapacity;
	}
}

初始化函数具体实现:

设计思路分析:
将p->arr = NULL;p->capacity = p->size = 0;

//初始化
void SeqListInit(SL* p)
{
	assert(p);
	p->arr = NULL;
	p->capacity = p->size = 0;
}

打印函数具体实现:

设计思路分析:
这个比较简单,直接写个循环遍历一遍打印即可。

//打印
void SeqListPrintf(SL* p)
{
	int i = 0;
	for (i = 0; i < p->size; i++)
	{
		printf("%d ", p->arr[i]);
	}
	printf("\n");
}

头文件全部源码分享🙌

这里负责函数功能的声明和库函数头文件的包含,写任何一个项目时,可以先把头文件编写好,也就是理清一下项目需要实现哪些功能函数,整理一下项目的整体思路。

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

#define DataSeqList int

typedef struct SeqList
{
	DataSeqList* arr;
	int size;
	int capacity;
}SL;

//初始化
void SeqListInit(SL* p);
//尾插
void SeqListPushBack(SL* p, DataSeqList x);
//尾删
void SeqListPopBack(SL* p);
//头插
void SeqListPushFront(SL* p, DataSeqList x);
//头删
void SeqListPopFront(SL* p);
//任意插
void SeqListInsert(SL* p, int pos, DataSeqList x);
//任意删
void SeqListEraes(SL* p, int pos);
//打印
void SeqListPrintf(SL* p);
//销毁
void SeqListDestory(SL* p);
//查找
int SeqListFind(SL* p, DataSeqList x);
//检查容量
void SeqListCheckCapacity(SL* p);

功能文件全部源码分享🙌


#include"SeqList.h"

//初始化
void SeqListInit(SL* p)
{
	assert(p);
	p->arr = NULL;
	p->capacity = p->size = 0;
}

//尾插- 会遇到三种情况
// 1 - 没有空间    2 - 空间不足,要扩容(查容量)  3 - 空间足够,插入数据

//检查容量
void SeqListCheckCapacity(SL* p)
{
	if (p->size == p->capacity)
	{
		int newcapacity = p->capacity == 0 ? 4 : p->capacity * 2;
		DataSeqList* tem = realloc(p->arr, newcapacity * sizeof(DataSeqList));
		assert(tem);
		p->arr = tem;
		p->capacity = newcapacity;
	}
}

//打印
void SeqListPrintf(SL* p)
{
	int i = 0;
	for (i = 0; i < p->size; i++)
	{
		printf("%d ", p->arr[i]);
	}
	printf("\n");
}

//尾插
void SeqListPushBack(SL* p, DataSeqList x)
{
	/*SeqListCheckCapacity(p);
	p->arr[p->size] = x;
	p->size++;*/
	SeqListInsert(p, p->size, x);
}

//尾删
void SeqListPopBack(SL* p)
{
	/*assert(p->size);
	p->size--;*/
	SeqListEraes(p, p->size - 1);
}
//头插
void SeqListPushFront(SL* p, DataSeqList x)
{
	//SeqListCheckCapacity(p);
	挪动数据
	//int end = p->size - 1;
	//while (end >= 0)
	//{
	//	p->arr[end + 1] = p->arr[end];
	//	end--;
	//}
	//p->arr[0] = x;
	//p->size++;
	SeqListInsert(p,0, x);
}
//头删
void SeqListPopFront(SL* p)
{
	删完就不用删了
	//assert(p->size);
	//int begin = 1;
	//while (begin < p->size)
	//{
	//	p->arr[begin - 1] = p->arr[begin];
	//	begin++;
	//}
	//p->size--;
	SeqListEraes(p, 0);
}

//任意插
void SeqListInsert(SL* p,int pos ,DataSeqList x)
{
	SeqListCheckCapacity(p);
	assert(pos >= 0 && pos <= p->size);
	int end = p->size - 1;
	while (end >= pos)
	{
		p->arr[end + 1] = p->arr[end];
		end--;
	}
	p->arr[pos] = x;
	p->size++;

}
//任意删
void SeqListEraes(SL* p, int pos)
{
	//删完就不用删了
	assert(p->size);
	//删的合法性判断
	assert(pos >= 0 && pos < p->size);
	int begin = pos+1;
	while (begin < p->size)
	{
		p->arr[begin - 1] = p->arr[begin];
		begin++;
	}
	p->size--;
}

//销毁
void SeqListDestory(SL* p)
{
	free(p->arr);
	p->arr = NULL;
	p->capacity = p->size = 0;
}

//查找
int SeqListFind(SL* p, DataSeqList x)
{
	assert(p);
	for (int i = 0; i < p->size; i++)
	{
		if (p->arr[i] == x)
		{
			return i;
		}
	}
	return -1;
}

测试文件代码🙌

#define _CRT_SECURE_NO_WARNINGS 1

#include"SeqList.h"

void test1()
{
	SL s;
	SeqListInit(&s);
	SeqListPushBack(&s, 1);
	SeqListPushBack(&s, 2);
	SeqListPushBack(&s, 3);
	SeqListPushBack(&s, 4);
	SeqListPushBack(&s, 5);
	SeqListPrintf(&s);
	SeqListPopBack(&s);
	SeqListPopBack(&s);
	SeqListPrintf(&s);

	SeqListPushFront(&s, 10);
	SeqListPushFront(&s, 20);
	SeqListPushFront(&s, 30);
	SeqListPushFront(&s, 40);
	SeqListPrintf(&s);

	SeqListPopFront(&s);
	SeqListPopFront(&s);
	SeqListPrintf(&s);
	SeqListDestory(&s);



}

void test2()
{
	SL s;
	SeqListInit(&s);
	SeqListPushBack(&s, 1);
	SeqListPushBack(&s, 2);
	SeqListPushBack(&s, 3);
	SeqListPushBack(&s, 4);
	SeqListPushBack(&s, 5);
	SeqListPrintf(&s);
	SeqListInsert(&s, 3, 30);
	SeqListPrintf(&s);
	SeqListEraes(&s, 3);
	SeqListEraes(&s, 2);
	SeqListPrintf(&s);

	SeqListDestory(&s);
}
void test3()
{
	SL s;
	SeqListInit(&s);
	SeqListPushBack(&s, 1);
	SeqListPushBack(&s, 2);
	SeqListPushBack(&s, 3);
	SeqListPushBack(&s, 4);
	SeqListPushBack(&s, 5);
	SeqListPrintf(&s);
	SeqListInsert(&s, 3, 30);
	SeqListEraes(&s, 2);
	SeqListPrintf(&s);
	SeqListDestory(&s);
}

void test4()
{
	SL s;
	printf("尾插数据1,2,3,4,5\n");
	SeqListInit(&s);
	SeqListPushBack(&s, 1);
	SeqListPushBack(&s, 2);
	SeqListPushBack(&s, 3);
	SeqListPushBack(&s, 4);
	SeqListPushBack(&s, 5);
	SeqListPrintf(&s);
	printf("头插数据10, 20 , 30\n");
	SeqListPushFront(&s, 10);
	SeqListPushFront(&s, 20);
	SeqListPushFront(&s, 30);
	SeqListPrintf(&s);
	SeqListDestory(&s);
}

int main()
{

	//test1();
	//test2();
	//test3();
	test4();
	return 0;
}

部分功能测试结果图:
在这里插入图片描述

总结撒花💞

   本篇文章旨在分享详解C语言动态实现顺序表。希望大家通过阅读此文有所收获!😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

EM算法总结

目录 一。Jensen不等式&#xff1a;若f是凸函数 二。最大似然估计 三。二项分布的最大似然估计 四。进一步考察 1.按照MLE的过程分析 2.化简对数似然函数 3.参数估计的结论 4.符合直观想象 五。从直观理解猜测GMM的参数估计 1.问题&#xff1a;随机变量无法直接…

SQL90 纠错3

描述OrderItems表含有order_num订单号order_numa002a002a002a004a007【问题】将下面代码修改正确后执行SELECT order_num, COUNT(*) AS items FROM OrderItems GROUP BY items HAVING COUNT(*) > 3 ORDER BY items, order_num;【示例结果】返回订单号order_num和出现的次数i…

数据结构之算法的时间复杂度和空间复杂度

本章重点&#xff1a; 1.算法效率 2.时间复杂度 3.空间复杂度 4. 常见时间复杂度以及复杂度oj练习 目录 1.算法效率 1.2算法的复杂度 2.时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 2.3常见时间复杂度计算举例 3.空间复杂度 4. 常见复杂度对比 5.复杂度…

在VMware Workstation中配置固定IP、在VMware Fusion中配置固定IP

1、在VMware Workstation中配置固定IP 配置固定IP需要2个大步骤&#xff1a; 1.在VMware Workstation&#xff08;或Fusion&#xff09;中配置IP地址网关和网段&#xff08;IP地址的范围&#xff09; 首先让我们&#xff0c;先进行第一步&#xff0c;跟随图片进行操作 现在进…

Pthreads实验

实验一&#xff1a;主线程与子线程 pthread_create函数&#xff1a; 1、简介&#xff1a;pthread_create是UNIX环境创建线程的函数 2、头文件&#xff1a;#include <pthread.h> 3、函数声明&#xff1a; int pthread_create(pthread_t* restrict tidp , const pthread_a…

java面试题-JUC锁

1.介绍下LockSupport&#xff1f;LockSupport 是 Java 并发包中的一个工具类&#xff0c;用于创建锁和其他同步类的基本线程阻塞原语。它也是 J.U.C 中的一个核心基础类。相较于 Object.wait() 和 Object.notify()&#xff0c;LockSupport 可以更加灵活地对线程进行阻塞和唤醒操…

以学校数据模型为例,掌握在DAS下使用GaussDB

文章目录题目具体操作一、表的创建二、表数据的插入三、数据查询目的&#xff1a; 这里以学校数据库模型为例&#xff0c;介绍GaussDB数据库、表等常见操作&#xff0c;以及SQL语法使用的介绍。题目 假设A市B学校为了加强对学校的管理&#xff0c;引入了华为GaussDB数据库。 在…

如何利用ChatGPT学习量化投资?

引言最近&#xff0c;ChatGPT持续火了很长时间&#xff0c;占领各大热点和头版头条&#xff0c;成为A股开年以来最大的热点之一。ChatGPT是OpenAI开发的一种语言生成模型&#xff0c;可以理解为智能问答机器人。最近围绕量化投资在上面试了很多问题&#xff0c;大部分回答还是很…

基于DSP+FPGA的机载雷达伺服控制系统的硬件设计与开发

机载雷达是以飞机为载体的各种雷达天线的总称&#xff0c;主要用于空中侦察、警戒、保 证航行准确与安全[1]。随着航空航天技术的飞速发展&#xff0c;以及微电子、计算机和高速集 成电路等新型技术在军事领域的广泛应用[2]&#xff0c;各国都研制出了许多新型战机和导弹,机 载…

docsify在线文档支持pdf查看

目录 步骤一&#xff1a;添加插件 步骤二&#xff1a;添加pdf地址 步骤三&#xff1a;成果展示 docsify是一个在github上很好用的文档转换网页的工具&#xff0c;但是大部分情况我们都是使用的markdown文件。最近想把pdf文档也能支持在这上面展示&#xff0c;研究后总结一下…

零信任-微软零信任概念补充(13)

​零信任是一种安全策略。 它不是产品或服务&#xff0c;而是设计和实现以下一组安全原则的方法&#xff1a; 显式验证使用最小特权访问假定数据泄露 零信任的指导原则 显式验证 使用最小特权 访问假定数据泄露 始终根据所有可用的数据点进行身份验证和授权。 使用实时和恰…

内网渗透(四十五)之横向移动篇-WinRM远程执行命令横向移动

系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…

代码随想录【Day20】| 654. 最大二叉树、617. 合并二叉树、700. 二叉搜索树中的搜索、98. 验证二叉搜索树

654. 最大二叉树 题目链接 题目描述&#xff1a; 给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下&#xff1a; 二叉树的根是数组中的最大元素。 左子树是通过数组中最大值左边部分构造出的最大二叉树。 右子树是通过数组中最大值右边部分构造出的最…

leaflet 根据一组点的值生成凹包,并在地图上显示(081)

第081个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中根据提供的多个点,利用turf生成凹包。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共88行)安装插件相关API参考:专栏目标示例效果 配置…

1631_MIT 6.828 lab1 HW的部分尝试与总结

全部学习汇总&#xff1a; GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 其实很多尝试我之前自己都做过了&#xff0c;这里就可以直接跳过或者简单提一下。 这个环境的搭建已经完成了&#xff0c;而且早就做了很多尝试了。之前的笔记中记…

设计模式-第3章(设计原则)

设计原则单一职责原则开放-封闭原则依赖倒转原则单一职责原则 设计模式中有一个非常重要的原则 — 单一职责。 单一职责原则&#xff08;SRP&#xff09;&#xff1a;就一个类而言&#xff0c;应该仅有一个引起它变化的原因。 我们在做编程的时候&#xff0c;很自然地就会给一…

「TCG 规范解读」第七章 TPM工作组 TPM 总结

可信计算组织&#xff08;Ttrusted Computing Group,TCG&#xff09;是一个非盈利的工业标准组织&#xff0c;它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立&#xff0c;并采纳了由可信计算平台联盟&#xff08;the Trusted Computing Platform Alli…

异步执行结果-Callable、Future、FutureTask

Callable 实现Runnable接口的任务执行没有返回值&#xff0c;如果我们希望线程运算后将结果返回&#xff0c;应该使用Callable。Callable代表有返回值的任务。 class CallTask implements Callable<String> {Overridepublic String call() throws Exception {return Th…

Python基于遥感影像的文件名称将不同文件复制到对应的文件夹中

本文介绍基于Python语言&#xff0c;针对一个文件夹下的大量栅格遥感影像文件&#xff0c;基于其各自的文件名&#xff0c;分别创建指定名称的新文件夹&#xff0c;并将对应的栅格遥感影像文件复制到不同的新文件夹下的方法。 首先&#xff0c;我们来看一下本文需要实现的需求。…

RPC(1)------Java BIO + JDK原生序列化 + JDK动态代理实现

本文跟着MY-RPC-FRamework的代码&#xff0c;根据自己的理解做的笔记&#xff0c;先理解&#xff0c;再学习。 RPC原理 客户端和服务端都可以访问到通用的接口,但是只有服务端有这个接口的实现类&#xff0c;客户端调用这个接口的方式&#xff0c;是通过网络传输&#xff0c;告…