【C项目】顺序表

news2024/11/13 4:22:07

简介:本系列博客为C项目系列内容,通过代码来具体实现某个经典简单项目
适宜人群:已大体了解C语法同学
作者留言:本博客相关内容如需转载请注明出处,本人学疏才浅,难免存在些许错误,望留言指正
作者博客链接:睡觉待开机

下面是本项目的大体思路梳理:
在这里插入图片描述

引言:

一般来说,顺序表作为基本的数据结构类型是不需要我们进行实现的,因为一些高级语言比如C++或者java直接具备的这样的内置数据结构,但是为了深入了解顺序表的底层,这里也是建议自己动手用C写一下,一是便于复习C学到的知识,二是更加深入了解顺序表的实现底层逻辑。


1.顺序表思路

为了明晰顺序表的实现思路,我们首先来铺垫一下我到底要在怎么写一个顺序表。

首先啥是顺序表?
一种线性表,底层是数组,只不过这个顺序表所谓的数组不单单可以放各种类型的数据,还可以有各种接口,包括增删查改操作的接口等等。

注:线性表的概念:逻辑结构上是连续的,物理结构不一定连续的数据结构称为线性表。

顺序表的概念:逻辑结构上是连续的,物理结构上也是连续的,底层是以数组为实现,有着增删查改各种接口的基本数据组织结构。
在这里插入图片描述


那么我就可以大致明白了我要写一个顺序表,这个顺序表实现了一些功能。

首先我要写一个顺序表的话,要有一个顺序表的大体类型吧,所以我就写了一个动态顺序表的类型

typedef int SLDateType;

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

在这里插入图片描述

然后我想要在这个顺序表中实现各种功能(接口),那这个顺序表首先得初始化吧,有初始化顺序表了那肯定对应着销毁这个接口,自然也需要顺序表销毁,然后还要有头插尾插任意插入这个”增“的功能,还有有头删尾删任意删的这个”删“的共能,然后还要有查找功能,还要修改功能,那么我针对该顺序表的每个接口专门搞一个函数

为了便于代码书写,我将各种接口以及顺序表类型本身定义在SeqList.h头文件中进行声明与定义:

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

typedef int SLDateType;

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


//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);

//顺序表的头部输入/尾部输入
void SLPushBack(SL* ps,SLDateType x);
void SLPushFront(SL* ps, SLDateType x);

//顺序表的头部删除/尾部删除
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);

//指定位置放入/删除数据
void SLInsert(SL* ps, int pos, SLDateType x);
void SLErase(SL* ps, int pos);

//查找数据
int SLFind(SL* ps, SLDateType x);

//修改数据
void SLModify(SL* ps, int pos, SLDateType x);


2.具体实现各种接口

顺序表初始化接口:

void SLInit(SL* ps)
{
	assert(ps);

	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}

顺序表初始化插图:
在这里插入图片描述

顺序表销毁接口:

void SLDestroy(SL* ps)
{
	assert(ps);

	if (ps->arr)
	{
		free(ps->arr);
	}

	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}

顺序表销毁插图:
在这里插入图片描述

顺序表扩容接口:

void SLCheckCapacity(SL* ps)
{
	assert(ps);

	if (ps->capacity == ps->size)
	{
		//小问题:刚开始的时候,sl->capacity是0值
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDateType* temp = realloc(ps->arr,sizeof(SLDateType)*newcapacity);
		if (!temp)
		{
			perror("realloc fail!");
			return;
		}

		ps->arr = temp;
		ps->capacity = newcapacity;
	}
}

顺序表扩容插图:
在这里插入图片描述

顺序表插入接口

void SLPushBack(SL* ps,SLDateType x)
{
	assert(ps);
	//1.空间不足需要扩大容量
	//2.空间足够直接放入数据
	SLCheckCapacity(ps);

	ps->arr[ps->size] = x;
	ps->size++;
}

void SLPushFront(SL* ps, SLDateType x)
{
	assert(ps);

	SLCheckCapacity(ps);

	//挪动数据
	int i = 0;
	for (i = ps->size - 1; i >= 0; i--)
	{
		ps->arr[i+1] = ps->arr[i];
	}
	//放入数据
	*(ps->arr) = x;
	ps->size++;
}
void SLInsert(SL* ps, int pos, SLDateType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	
	SLCheckCapacity(ps);

	int i = 0;
	for (i = ps->size - 1; i >= pos; i--)
	{
		ps->arr[i+1] = ps->arr[i];
	}
	
	ps->arr[pos] = x;
	ps->size++;
}

头插的插图:
在这里插入图片描述
尾插的插图:
在这里插入图片描述
任意插入的插图:
在这里插入图片描述

顺序表删除接口:

void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size);
	
	ps->size--;
}

void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);

	int i = 0;
	for (i = 1; i < ps->size; i++)
	{
		ps->arr[i-1] = ps->arr[i];
	}

	ps->size--;
}
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);

	int i = 0;
	for (i = pos + 1; i < ps->size; i++)
	{
		ps->arr[i-1] = ps->arr[i];
	}

	ps->size--;
}

头删插图:
在这里插入图片描述
尾删插图:
在这里插入图片描述
任意删插图:
在这里插入图片描述

顺序表查找接口:

int SLFind(SL* ps, SLDateType x)
{
	assert(ps);
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (x == ps->arr[i])
		{
			printf("%d找到了:",x);
			return i;
		}
	}
	printf("没有找到\n");
	return -1;
}

在这里插入图片描述
顺序表修改接口:

void SLModify(SL* ps, int pos, SLDateType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size - 1);

	ps->arr[pos] = x;
	printf("修改成功\n");
}

修改插图:
在这里插入图片描述

3.全部接口代码实现:

#include"SeqList.h"


void SLCheckCapacity(SL* ps)
{
	assert(ps);

	if (ps->capacity == ps->size)
	{
		//小问题:刚开始的时候,sl->capacity是0值
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDateType* temp = realloc(ps->arr,sizeof(SLDateType)*newcapacity);
		if (!temp)
		{
			perror("realloc fail!");
			return;
		}

		ps->arr = temp;
		ps->capacity = newcapacity;
	}
}


void SLInit(SL* ps)
{
	assert(ps);

	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}

void SLDestroy(SL* ps)
{
	assert(ps);

	if (ps->arr)
	{
		free(ps->arr);
	}

	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}

void SLPrint(SL* ps)
{
	assert(ps);

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

void SLPushBack(SL* ps,SLDateType x)
{
	assert(ps);
	//1.空间不足需要扩大容量
	//2.空间足够直接放入数据
	SLCheckCapacity(ps);

	ps->arr[ps->size] = x;
	ps->size++;
}

void SLPushFront(SL* ps, SLDateType x)
{
	assert(ps);

	SLCheckCapacity(ps);

	//挪动数据
	int i = 0;
	for (i = ps->size - 1; i >= 0; i--)
	{
		ps->arr[i+1] = ps->arr[i];
	}
	//放入数据
	*(ps->arr) = x;
	ps->size++;
}

void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size);
	
	ps->size--;
}

void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);

	int i = 0;
	for (i = 1; i < ps->size; i++)
	{
		ps->arr[i-1] = ps->arr[i];
	}

	ps->size--;
}

void SLInsert(SL* ps, int pos, SLDateType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	
	SLCheckCapacity(ps);

	int i = 0;
	for (i = ps->size - 1; i >= pos; i--)
	{
		ps->arr[i+1] = ps->arr[i];
	}
	
	ps->arr[pos] = x;
	ps->size++;
}

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

	int i = 0;
	for (i = pos + 1; i < ps->size; i++)
	{
		ps->arr[i-1] = ps->arr[i];
	}

	ps->size--;
}

int SLFind(SL* ps, SLDateType x)
{
	assert(ps);
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (x == ps->arr[i])
		{
			printf("%d找到了:",x);
			return i;
		}
	}
	printf("没有找到\n");
	return -1;
}

void SLModify(SL* ps, int pos, SLDateType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size - 1);

	ps->arr[pos] = x;
	printf("修改成功\n");
}


完。

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

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

相关文章

k8s的operator基石:controller-runtime源码解析

写在之前 今天开始开更controller-runtime的源码阅读&#xff0c;笔者建议大家在阅读前了解以下知识&#xff0c;可能会帮助大家更好的理解源码逻辑。 1.client-go的基础使用 2. 使用kubebuilder搭建一个简单的controller-runtime环境 3.informer的基本思想 1.源码环境搭建 参…

UE5/UE4中3D汉字字体文字的创建与实现

本案例工程下载位置&#xff1a;https://mbd.pub/o/bread/ZZqVmJ9v 在虚幻引擎5&#xff08;UE5&#xff09;和虚幻引擎4&#xff08;UE4&#xff09;中&#xff0c;实现3D汉字字体的创建是一项常见的需求。 本文将详细介绍两种有效的方法&#xff1a; 1.通过TextRender配合Of…

【javase】——类和对象

莫道桑榆晚&#xff0c;为霞尚满天。文章目录 面向对象的初步认识面向对象与面向过程什么是面向对象 类的定义和使用类的定义格式 类的实例化什么是实例化类和对象的使用 this引用什么是this引用this 引用的特性。 对象的构造以及初始化如何初始化对象构造方法首先第一&#xf…

Win10如何开启适用于 Linux 的 Windows 子系统WSL

环境&#xff1a; Win10专业版19041 问题描述&#xff1a; Win10如何开启适用于 Linux 的 Windows 子系统 什么是适用于 Linux 的 Windows 子系统 (WSL)&#xff1f;适用于 Linux 的 Windows 子系统 (WSL) 是 Windows 操作系统的一项功能&#xff0c;通过它可以直接在 Wind…

常用芯片学习——ULIN2803芯片

ULIN2803 高压大电流达林顿晶体管阵列 使用说明 ULN2803为高压大电流达林顿晶体管阵列&#xff0c;每个阵列包含7 个集电极开路共发射极对。每对的额定电流为500mA。抑制包括用于感性负载驱动的二极管&#xff0c;输入和输出是相反的。这些器件能够驱动宽范围的负载范围&…

2024.1.30 GNSS 学习笔记

站星双差Kalman滤波伪距差分定位流程 1. RTK定位技术&#xff08;实时载波相位差分技术&#xff09;原理-站间单差浮点解 1.RTK技术其实就是在RTD技术的基础上增加载波观测值的使用。由于伪距的噪声在分米量级&#xff0c;即使我们通过站间单差消除了绝大部分的误差影响&…

对于this.$nextTick代码的理解

我们都知道DOM的更新是异步的,Vue的绑定原理就是用数据区驱动视图,视图也能驱动数据&#xff0c;两者是双向绑定的。 如何立马获取到更新之后的DOM呢&#xff1f; 可以使用: <template><div class"" ref"aa">{{ a }}<button click"f…

openssl3.2 - .pod文件的查看方法

文章目录 .pod文件的查看方法概述笔记初步的解决方法备注 - pod2html.bat的详细用法好像Perl就自带这个BATEND .pod文件的查看方法 概述 看到openssl源码目录下有很多.pod文件, 软件发布的帮助内容都在里面. 当make install后, 大部分的.pod都会转成html文件, 但是有一部分…

DSP系统时钟总结

一、stm32中断偏移向量介绍 1.1 为什么要设置中断向量偏移 上图可以看出程序上电先进入0x08000000开始运行&#xff0c;紧接着执行复位中断向量&#xff0c;然后执行复位中断程序&#xff0c;然后进入main函数。 如果想要app的中断正常运行&#xff0c;那就必须手动设置中断向…

【读点论文】SPTS Single-Point Text Spotting

SPTS Single-Point Text Spotting ABSTRACT 现有的场景文本识别(即&#xff0c;端到端文本检测和识别)方法依赖于昂贵的边界框注释(例如&#xff0c;文本行&#xff0c;词级或字符级边界框)。我们首次证明&#xff0c;训练场景文本识别模型可以通过对每个实例的单点进行极低成…

推特账号被冻结怎么办?检查IP是否正常

Twitter 拥有庞大的用户群和日常内容流&#xff0c;是沟通、网络和营销的重要平台。然而&#xff0c;处理其限制和潜在的帐户问题可能很棘手。有许多跨境社媒小伙伴反馈&#xff0c;账号无故被冻结&#xff0c;导致内容与客户尽失&#xff01;其实除了账户养号、被举报、广告信…

C语言基础13

今天是学习嵌入式相关内容的第十四天&#xff0c;以下是今日所学内容 1.结构体: 1.结构体类型定义 2.结构体变量的定义 3.结构体元素的访问 4.结构体的存储 内存对齐 结构体整体的大小必须为最大基本类型长度的整数倍 5.结构体作为函数参数 值传递 练习:定…

freeRTOS的第一个任务是如何跑起来的?(以RISC-V架构分析)

1、前言 要理解第一个任务是如何跑起来&#xff0c;必须先能理解下面的概念 freeRTOS的任务创建、任务切换机制架构规定的函数调用规范了解基础的汇编指令 可以参考的资料&#xff1a; 《freertos任务切换的现场保存、恢复&#xff08;任务栈空间&#xff09;深度分析&#xf…

Arduino开发实例-DRV8833电机驱动器控制直流电机

DRV8833电机驱动器控制直流电机 文章目录 DRV8833电机驱动器控制直流电机1、DRV8833电机驱动器介绍2、硬件接线图3、代码实现DRV8833 使用 MOSFET,而不是 BJT。 MOSFET 的压降几乎可以忽略不计,这意味着几乎所有来自电源的电压都会传递到电机。 这就是为什么 DRV8833 不仅比基…

【Matplotlib】科研绘图——折线图

文章目录 1、导入2、定义Font及Style3、设置图像大小及坐标刻度4、数据准备5、自定义draw6、其他设置7、效果图 1、导入 import matplotlib import matplotlib.pyplot as plt from matplotlib.backends.backend_pdf import PdfPages import numpy as np import pandas as pd %…

合肥工业大学计算机试卷和笔记

总结了一些试卷和笔记&#xff0c;但是csdn上不方便上传pdf&#xff0c;所以上传到github了&#xff0c;欢迎Issue和fork 地址&#xff1a; https://github.com/Martin-share/hfut-cs-final-exams-and-note 持续更新-------2024-01-30

企业做新媒体矩阵不可忽视的四大问题

互联网进入下半场&#xff0c;存量市场竞争日益加剧&#xff0c;获客成本不断增加&#xff0c;越来越多的品牌开始数字化转型&#xff0c;而布局社交媒体矩阵则成为了大多数品牌的必然选择。 通过社交媒体的图文、短视频、直播等形式营销推广&#xff0c;不断做深、做透、做细&…

如何override已经存在的约束

文章目录 前言一、如何override已经存在的约束总结 前言 在验证过程中&#xff0c;我们基本都是基于spec&#xff0c;做正常的约束&#xff0c;当我们测特定corner场景的时候&#xff0c;希望能够用新的约束&#xff0c;去override已经存在的约束。 一、如何override已经存在的…

windows下postgresql的安装使用

一、安装 1、安装包安装 1.1 下载exe安装包 选择安装包&#xff1a;官网 或者点击下载&#xff1a;postgresql-12.12-1-windows-x64.exe Tip&#xff1a;此时若报错&#xff1a;There has been an error.An error occured executing the Microsoft VC runtime installer。 参…

性价比之王,65W 2C1A降功率方案隆重推出

随着电子市场发展&#xff0c;现在越来越多的设备都具有快充功能&#xff0c;快充设备越来越普及&#xff1b;单口快充已经很难满足人们的需求&#xff0c;市场对多口快充配件的需求量日益增加。同时随着氮化镓的普及&#xff0c;适配器功率越做越大&#xff0c;功率的合理利用…