数据结构-->线性表-->顺序表

对我个人来说,C语言基础相关的知识基本学完了,随后就该学数据结构了,希望以后自己复习能够用上今天自己写的哈哈。

如果你不理解什么是物理结构和逻辑结构,这里附上一个链接:逻辑结构和物理结构:逻辑结构与物理结构_逻辑结构和物理结构-CSDN博客

 

看见我的备注了吗,一位不帅的帅哥。

数据结构的相关介绍

我们将数据结构拆分为两个词来理解
数据就是存储的信息,结构是组织数据的方式。
官方定义的数据结构的概念为:数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。数据结构反应数据的内部构成,即数据有哪部分构成,以什么方式构成,以及数据元素之间呈现的结构。
总结:

(1)能够存储数据(顺序表,链表等结构)
(2)存储的数据能够方便查找

数组是最基础的数据结构,我们除了数组还要学习更多数据结构的原因是:最基础的数据结构能够提供的操作已经不能完全满足复杂算法实现。

对数据结构中线性表的认识

线性表:

线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列

线性表在逻辑上是线性结构,也就是说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常是以数组和链式结构的形式存储。

从顺序表开始启航

顺序表和数组的区别:顺序表的底层结构是数组,对数组的封装,实现了常用的增删查改等接口。

顺序表分为静态顺序表和动态顺序表。

对静态顺序表来说:空间给少了不够用,给多了造成空间浪费。

也就是说老年机的通讯录就是静态顺序表。

这里附上老年机,商标就打码了,怕吃官司。

 因此我们就写动态版本的顺序表了

对学校数据结构方面的忠告

 好的,其实到这里呢,我就去手搓动态顺序表了,哈哈,幸运的是我完全写出来了,没看别人的,老师说过数据结构这块呢,就是要熟悉,重要的是代码,其实我觉得呢也没有别的办法,多写才是解药。

顺序表头文件

代码的头文件

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;
	int capacity;
}SL;

//初始化
void SLInit(SL* ps);
//销毁
void SLDestroy(SL* ps);
//打印
void SLPrint(SL* ps);
//扩容
void SLCheck(SL* ps);
//尾插
void SLPushBack(SL* ps, SLDataType x);
//尾删
void SLPopBack(SL* ps);
//头插
void SLPushFront(SL* ps, SLDataType x);
//头删
void SLPopFront(SL* ps);
//查找
int FindData(SL* ps, SLDataType x);
//指定位置插入
void InsertPush(SL* ps, int pos, SLDataType x);
//指定位置删除
void ErasePop(SL* ps, int pos);

初始化

这里没什么难度,就直接写就ok

//初始化
void SLInit(SL* ps)
{
    ps->a = NULL;
    ps->capacity = ps->size = 0;
}

 销毁

程序结束记得销毁,否则会发生内存泄漏,切记、切记、切记。

//销毁
void SLDestroy(SL* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

打印

对于打印,其实就直接遍历就ok

//打印
void SLPrint(SL* ps)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
}

扩容

这里的扩容,顾名思义就是扩大空间,他的作用是为了提供足够的空间

//扩容
void SLCheck(SL* ps)
{
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* new = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
		if (new == NULL)
		{
			perror("REALL0C FAIL");
			return;
		}
		ps->a = new;
		ps->capacity = newcapacity;
	}
}

尾插

尾插我们先检查我们的空间大小够不够,对于需要插入的接口来说,我们都要检查空间是否足够,

只要空间足够,就直接插入就ok了。

//尾插
void SLPushBack(SL* ps,SLDataType x)
{
	assert(ps);
	SLCheck(ps);
	ps->a[ps->size++] = x;
}

尾删 

直接把size减去1就ok

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

头插

头插就是要把原来的数据往后挪动,但是不能从前往后挪动,因为这样会覆盖之后还没挪动的数据,因此我们需要把数据从后往前开始往后挪动 

//头插
void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheck(ps);
	for (int i = ps->size; i > 0; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}
	ps->a[0] = x;
	ps->size++;
}

头删

头删跟头插正好相反,额这算不算相当于没说

就是把数据从前往后开始往前面移动 

//头删
void SLPopFront(SL* ps)
{
	assert(ps);
	for (int i = 1; i < ps->size; i++)
	{
		ps->a[i-1] = ps->a[i];
	}
	ps->size--;
}

 查找

查找就是遍历再加一层比较,值相等就返回下标

//查找
int FindData(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

指定位置插入

其实就是类似头插,注意for循环范围别搞错了,如果你怕搞错,这里提供一种方法,就是你只比较带入for循环的最大和最小情况,如果成立,那就是正确的。

//指定位置插入
void InsertPush(SL* ps, int pos, SLDataType x)
{
    assert(ps);
    assert(ps->size);
    assert(pos >= 0 && pos <= ps->size);
    for (int i = ps->size; i > pos; i--)
    {
        ps->a[i] = ps->a[i - 1];
    }
    ps->a[pos] = x;
    ps->size++;
}

指定位置删除

 类似头删

//指定位置删除
void ErasePop(SL* ps, int pos)
{
	assert(ps);
	assert(ps->size);
	assert(pos >= 0 && pos < ps->size);
	for (int i = pos + 1; i < ps->size; i++)
	{
		ps->a[i - 1] = ps->a[i];
	}
	ps->size--;
}

最后附上最终代码 

总代码

SeqList.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;
	int capacity;
}SL;

//初始化
void SLInit(SL* ps);
//销毁
void SLDestroy(SL* ps);
//打印
void SLPrint(SL* ps);
//扩容
void SLCheck(SL* ps);
//尾插
void SLPushBack(SL* ps, SLDataType x);
//尾删
void SLPopBack(SL* ps);
//头插
void SLPushFront(SL* ps, SLDataType x);
//头删
void SLPopFront(SL* ps);
//查找
int FindData(SL* ps, SLDataType x);
//指定位置插入
void InsertPush(SL* ps, int pos, SLDataType x);
//指定位置删除
void ErasePop(SL* ps, int pos);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
//初始化
void SLInit(SL* ps)
{
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}
//销毁
void SLDestroy(SL* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}
//打印
void SLPrint(SL* ps)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
}
//扩容
void SLCheck(SL* ps)
{
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* new = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
		if (new == NULL)
		{
			perror("REALL0C FAIL");
			return;
		}
		ps->a = new;
		ps->capacity = newcapacity;
	}
}
//尾插
void SLPushBack(SL* ps,SLDataType x)
{
	assert(ps);
	SLCheck(ps);
	ps->a[ps->size++] = x;
}
//尾删
void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size);
	ps->size--;
}
//头插
void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheck(ps);
	for (int i = ps->size; i > 0; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}
	ps->a[0] = x;
	ps->size++;
}
//头删
void SLPopFront(SL* ps)
{
	assert(ps);
	for (int i = 1; i < ps->size; i++)
	{
		ps->a[i-1] = ps->a[i];
	}
	ps->size--;
}
//查找
int FindData(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}
//指定位置插入
void InsertPush(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(ps->size);
	assert(pos >= 0 && pos <= ps->size);
	for (int i = ps->size; i > pos; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}
	ps->a[pos] = x;
	ps->size++;
}
//指定位置删除
void ErasePop(SL* ps, int pos)
{
	assert(ps);
	assert(ps->size);
	assert(pos >= 0 && pos < ps->size);
	for (int i = pos + 1; i < ps->size; i++)
	{
		ps->a[i - 1] = ps->a[i];
	}
	ps->size--;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
int main()
{
	SL s;
	SLInit(&s);
	SLPushBack(&s, 1);
	SLPushBack(&s, 2);//1 2
	SLPrint(&s);
	printf("\n");
	SLPopBack(&s);//1
	SLPrint(&s);
	printf("\n");
	SLPushFront(&s,2);//2 1
	SLPrint(&s);
	printf("\n");
	SLPopFront(&s);//1
	SLPrint(&s);
	SLDestroy(&s);
	return 0;
}

 运行test函数,测试各接口是否正确

运行一下test函数,检查一下

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从Unity到Three.js(安装启动)

发现在3D数字孪生或模拟仿真方向&#xff0c;越来越多的公司倾向使用Web端程序&#xff0c;目前一直都是使用的Unity进行的Web程序开发&#xff0c;但是存在不少问题&#xff0c;比如内存释放、shader差异化、UI控件不支持复制或输入中文等。虽然大多数问题都可以找到解决方案&…

MySQL:从基础到实践(简单操作实例)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 下载前言一、MySQL是什么&#xff1f;二、使用步骤1.引入库2.读入数据 提交事务查询数据获取查询结果总结 下载 点击下载提取码888999 前言 在现代信息技术的世界…

RabbitMQ-6.延迟消息

延迟消息 6.延迟消息6.1.死信交换机和延迟消息6.1.1.死信交换机6.1.2.延迟消息6.1.3.总结 6.2.DelayExchange插件6.2.1.下载6.2.2.安装6.2.3.声明延迟交换机6.2.4.发送延迟消息 6.延迟消息 在电商的支付业务中&#xff0c;对于一些库存有限的商品&#xff0c;为了更好的用户体…

SpringBoot:web开发

web开发demo&#xff1a;点击查看 LearnSpringBoot05Web 点击查看更多的SpringBoot教程 技术摘要 webjarsBootstrap模板引擎thymeleaf嵌入式Servlet容器注册web三大组件 一、webjars webjars官网 简介 简介翻译 WebJars 是打包到 JAR&#xff08;Java Archive&#xff09;…

2024.02 国内认知大模型汇总

概述 大模型&#xff0c;又称为大规模机器学习模型&#xff0c;是一种基于大数据的人工智能技术。它通过深度学习和机器学习的方法&#xff0c;对大量数据进行训练&#xff0c;以实现对复杂问题的高效解决。大模型技术在语音识别、图像识别、自然语言处理等领域有着广泛的应用…

常用对象和常用成员函数

常量对象与常量成员函数来防止修改对象&#xff0c;实现最低权限原则。 在Obj被定义为常量对象的情况下&#xff0c;下面这条语句是错误的。 错误的原因是常量对象一旦初始化后&#xff0c;其值就再也不能改变。因此&#xff0c;不能通过常量对象调用普通成员函数&#xff0c;因…

ArcGIS学习(五)坐标系-2

3.不同基准面坐标系之间的转换 在上一关中,我们学习了ArcGIS中的投影(投影栅格)工具,并以"WGS1984地理坐标系与WGS1984的UTM投影坐标系的转换”为例进行讲解。 "WGS1984地理坐标系与WGS1984的UTM投影坐标系的转换”代表的是同一个基准面下的两个坐标的转换。 …

【力扣】查找总价格为目标值的两个商品,双指针法

查找总价格为目标值的两个商品原题地址 方法一&#xff1a;双指针 这道题和力扣第一题“两数之和”非常像&#xff0c;区别是这道题已经把数组排好序了&#xff0c;所以不考虑暴力枚举和哈希集合的方法&#xff0c;而是利用单调性&#xff0c;使用双指针求解。 考虑数组pric…

洛希极限

L1-3 洛希极限 分数 10 作者 陈越 单位 浙江大学 科幻电影《流浪地球》中一个重要的情节是地球距离木星太近时&#xff0c;大气开始被木星吸走&#xff0c;而随着不断接近地木“…

【数据结构】链表OJ面试题2《分割小于x并排序链表、回文结构、相交链表》+解析

1.前言 前五题在这http://t.csdnimg.cn/UeggB 休息一天&#xff0c;今天继续刷题&#xff01; 2.OJ题目训练 1. 编写代码&#xff0c;以给定值x为基准将链表分割成两部分&#xff0c;所有小于x的结点排在大于或等于x的结点之前 。链表分割_牛客题霸_牛客网 思路 既然涉及…

春节回家坐飞机后助听器就不好用了?如何过安检、拖运?

春节即将来临&#xff0c;很多人都要乘坐飞机回家或者出游。如果你是一位助听器使用者&#xff0c;你可能会有一些疑问&#xff1a;坐飞机能戴助听器吗&#xff1f;助听器会不会受到安检设备的影响&#xff1f;直接将助听器放在传送带上可以吗&#xff1f;……别担心&#xff0…

Harbor介绍、整体架构和安装

Harbor介绍、整体架构和安装 文章目录 Harbor介绍、整体架构和安装1.Harbor介绍2.Harbor 整体架构3.安装Harbor3.1 主机初始化3.1.1 设置ip地址3.1.2 配置镜像源3.1.3 关闭防火墙3.1.4 禁用SELinux3.1.5 禁用swap3.1.6 设置时区 3.2 安装docker3.3 安装docker compose3.4 下载H…

【JS逆向一】逆向某站的 加密参数算法--仅供学习参考

逆向日期&#xff1a;2024.02.06 使用工具&#xff1a;Node.js 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 可使用AES进行解密处理&#xff08;直接解密即可&#xff09;&#xff1a;在线AES加解密工具 1、打开某某网站(请使用文章开头的…

记录 | linux下切换python版本

查看系统中存在的 python 版本 ls /usr/bin/python* 查看系统默认的 python 版本 python --version

金融信贷风控特征计算详解

特征的含义&#xff1f; 特征可以说是风控系统中的最小单元&#xff0c;是风控工具的重要组成部分&#xff0c;我们也可以理解成变量。不过叫什么问题不大&#xff0c;团队内有相同的共识就行。 风控特征是我们做数字化线上风控中的重要组成部分&#xff0c;几乎可以说没有风…

【Flink入门修炼】1-2 Mac 搭建 Flink 源码阅读环境

在后面学习 Flink 相关知识时&#xff0c;会深入源码探究其实现机制。因此&#xff0c;需要现在本地配置好源码阅读环境。 本文搭建环境&#xff1a; Mac M1&#xff08;Apple Silicon&#xff09;Java 8IDEAFlink 官方源码 一、 下载 Flink 源码 github 地址&#xff1a;h…

[每周一更]-(第85期):NLP-实战操作-文本分类

NLP文本分类的应用场景 医疗领域 - 病历自动摘要&#xff1a; 应用&#xff1a; 利用NLP技术从医疗文档中自动生成病历摘要&#xff0c;以帮助医生更快速地了解患者的状况。 法律领域 - 法律文件分类&#xff1a; 应用&#xff1a; 使用文本分类技术自动分类法律文件&#xf…

Mysql的sql优化

一.查询优化 我们都知道&#xff0c;在建立索引的时候&#xff0c;要考虑where后面的查询条件字段、order by 排序后面的字段 、group by 分组排序后面的字段&#xff0c;对他们的字段建立合适的索引&#xff0c;但是我们需要思考怎么建立合适的索引&#xff0c;或者建立索引之…

计算机网络-华为无线网络配置

前面已经大致了解了无线通信的原理和无线组网的概念&#xff0c;今天来学习无线的配置过程与步骤。 一、无线组网配置流程 在开始配置前复习下前面讲过无线组网有涉及几个设备&#xff0c;AC无线控制器、AP无线接入点、POE交换机。无线组网与有线组网是相对独立的&#xff0c;不…