初阶数据结构之顺序表的增删查改(二)

news2024/12/24 3:09:10

文章目录

    • @[TOC](文章目录)
  • 前言
  • 一、顺序表
    • 1.1顺序表的概念
    • 1.2顺序表的分类
    • 1.3、顺序表的接口定义
  • 二.顺序表的完整实现
    • 2.1代码的完成实现
  • 总结

前言

线性表的含义:

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

在这里插入图片描述


一、顺序表

1.1顺序表的概念

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

1.2顺序表的分类

静态的顺序表:使用定长数组存储元素

typedef int SLDatatype;
#define N 10
typedef int SLDatatype;
struct SeqList
{
	SLDatatype a[N];
	int size;
};

动态的顺序表:使用动态开辟的数组存储

typedef int SLDatatype;
typedef struct SeqList
{
	SLDatatype* a;
	int size;		//存储的有效数据个数
	int capacity;	//容量
}SL;

1.3、顺序表的接口定义

1、顺序表的初始化

void SLInit(SL* psl)
{
	psl->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);
	if (psl->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	psl->capacity = 4;
	psl->size = 0;
}

首先我们在内存中,动态开辟一块空间,并且把初始的存储容量设置为4个,psl->size其实就是下标的意思啦!

2、顺序表的销毁

void SLDestroy(SL* psl)
{
	free(psl->a);
	psl->a = NULL;
	psl->capacity = psl->size = 0;
}

首先开辟在堆上的数据,我们采用c语言中的free语句来释放,并且再让capacity和size都变为0,这样就算销毁成功啦!

3、顺序表的打印

void SLPrint(SL* psl)
{
	int i = 0;
	for (i = 0; i < psl->size; i++)
	{
		printf("%d ", psl->a[i]);
	}
	printf("\n");
}

首先顺序表的原理其实跟数组挺像的,其是物理地址连续的存储单元依次存储数据元素,所以在打印的时候我们可以想象数组的遍历,psl->size就是数组的元素个数,我们只需要利用一个for循环即可打印出来。

4、数组中的动态增容

void SLCheckCapacity(SL* psl)
{
	assert(psl);
	if (psl->capacity == psl->size)
	{
		SLDatatype* tmp = (SLDatatype*)realloc(psl->a, sizeof(SLDatatype) * 2 * psl->capacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		psl->a = tmp;
		psl->capacity *= 2;
	}
}

首先,当元素个数与数组大小相同的时候,我们可以给psl->a realloc动态增容,首先realloc有两个参数,一个是要增容的地址处,一个是增容大小。我们增容完毕之后在把增容的值赋给原来的psl->a这块地址处,并且在让数组大小变成原来的两倍。

5、顺序表的尾插

void SLPushBack(SL* psl, SLDatatype x)
{
	SLCheckCapacity(psl);//检查是否需要扩容
	psl->a[psl->size] = x;
	psl->size++;
}

从图中我们可以看出,顺序表的尾插只需要找到psl->size中处于何位置时,在该位置上,我们把相应的数插入进去即可

在这里插入图片描述

6、顺序表的头插

void SLPushFront(SL* psl, SLDatatype x)
{
	assert(psl->size);
	SLCheckCapacity(psl);
	int end = psl->size - 1;
	while (end >= 0)
	{
		psl->a[end + 1] = psl->a[end];
		end--;
	}
	psl->a[0] = x;
	psl->size++;
}

首先,头插如果从前面开始往后移的话,就会覆盖后面的数,那么我们应该怎么办呢?我们应该从后向前挪动,这样就不会影响到各个位置的数了。我们先找到最后一个数的下标,然后从后往前挪动,就如下图所示,此时最前头的一个位置就是空着了,我们把想插入的数插入进去即可,记住我们数据加一之后,我们size也会随之加一,所以最后要psl->size++噢!


7、顺序表的尾删

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

尾删的话,我们直接暴力一点直接删除psl->size就行啦!

8、顺序表的头删

void SLPopFront(SL* psl)
{
	assert(psl->size > 0);
	int start = 0;
	while (start < psl->size - 1)
	{
		psl->a[start] = psl->a[start + 1];
		start++;
	}
	psl->size--;
}

头删的话我们就从头开始往前挪动,最后记得我们已经少了一个数据了,记得psl->size–噢!

9、顺序表的插入

void SLInsert(SL* psl, int pos, SLDatatype x)
{
	assert(pos >= 0 && pos <= psl->size);
	SLCheckCapacity(psl);
	int cur = psl->size - 1;
	while (pos <= cur)
	{
		psl->a[cur + 1] = psl->a[cur];
		cur--;
	}
	psl->a[pos] = x;
	psl->size++;
}

10、顺序表的删除

void SLErase(SL* psl, int  pos)
{
	assert(pos >= 0 && pos < psl->size);
	int end = pos + 1;
	while (pos <= psl->size)
	{
		psl->a[pos] = psl->a[pos + 1];
		pos++;
	}
	psl->size--;
}

11、顺序表的查找

int SLFind(SL* psl, SLDatatype x)
{
	assert(psl);
	for (int i = 0; i < psl->size; i++)
	{
		if (psl->a[i] == x)
			return i;
	}
	return -1;
}

12、顺序表的修改

void Modify(SL* psl, int pos, SLDatatype x)
{
	assert(psl);
	psl->a[pos] = x;
}

二.顺序表的完整实现

2.1代码的完成实现

seqlist.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Seqlist.h"
//void SLInit(SL* psl)
//{
//	psl->a = NULL;
//	psl->capacity = 0;
//	psl->size = 0;
//}
void SLInit(SL* psl)
{
	psl->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);
	if (psl->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	psl->capacity = 4;
	psl->size = 0;
}
void SLDestroy(SL* psl)
{
	free(psl->a);
	psl->a = NULL;
	psl->capacity = psl->size = 0;
}

void SLCheckCapacity(SL* psl)
{
	assert(psl);
	if (psl->capacity == psl->size)
	{
		SLDatatype* tmp = (SLDatatype*)realloc(psl->a, sizeof(SLDatatype) * 2 * psl->capacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		psl->a = tmp;
		psl->capacity *= 2;
	}
}

void SLPrint(SL* psl)
{
	int i = 0;
	for (i = 0; i < psl->size; i++)
	{
		printf("%d ", psl->a[i]);
	}
	printf("\n");
}

void SLPushBack(SL* psl, SLDatatype x)
{
	SLCheckCapacity(psl);
	psl->a[psl->size] = x;
	psl->size++;
}
void SLPushFront(SL* psl, SLDatatype x)
{
	assert(psl->size);
	SLCheckCapacity(psl);
	int end = psl->size - 1;
	while (end >= 0)
	{
		psl->a[end + 1] = psl->a[end];
		end--;
	}
	psl->a[0] = x;
	psl->size++;
}
void SLPopBack(SL* psl)
{
	assert(psl->size > 0);
	psl->size--;
}
void SLPopFront(SL* psl)
{
	assert(psl->size > 0);
	int start = 0;
	while (start < psl->size - 1)
	{
		psl->a[start] = psl->a[start + 1];
		start++;
	}
	psl->size--;
}

void SLInsert(SL* psl, int pos, SLDatatype x)
{
	assert(pos >= 0 && pos <= psl->size);
	SLCheckCapacity(psl);
	int cur = psl->size - 1;
	while (pos <= cur)
	{
		psl->a[cur + 1] = psl->a[cur];
		cur--;
	}
	psl->a[pos] = x;
	psl->size++;
}
void SLErase(SL* psl, int  pos)
{
	assert(pos >= 0 && pos < psl->size);
	int end = pos + 1;
	while (pos <= psl->size)
	{
		psl->a[pos] = psl->a[pos + 1];
		pos++;
	}
	psl->size--;
}

int SLFind(SL* psl, SLDatatype x)
{
	assert(psl);
	for (int i = 0; i < psl->size; i++)
	{
		if (psl->a[i] == x)
			return i;
	}
	return -1;
}
void Modify(SL* psl, int pos, SLDatatype x)
{
	assert(psl);
	psl->a[pos] = x;
}

seqlist.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//#define N 10
//typedef int SLDatatype;
//struct SeqList
//{
//	SLDatatype a[N];
//	int size;
//};
typedef int SLDatatype;
typedef struct SeqList
{
	SLDatatype* a;
	int size;		//存储的有效数据个数
	int capacity;	//容量
}SL;

void SLInit(SL* psl);
void SLDestroy(SL* psl);

void SLPrint(SL* psl);

void SLPushBack(SL* psl, SLDatatype x);
void SLPushFront(SL* psl, SLDatatype x);
void SLPopBack(SL* psl);
void SLPopFront(SL* psl);

void SLInsert(SL* psl, int pos, SLDatatype x);
void SLErase(SL* psl, int  pos);

int SLFind(SL* psl, SLDatatype x);
void Modify(SL * psl, int pos, SLDatatype x); 

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
//#define INT_PTR int*
//typedef int* int_ptr;
//
//#define N 4
//#define Y(n) ((N+2)*n) ((6) * 5 + 1)
//
//INT_PTR a, b;
//int_ptr c, d;
//int main()
//{
//	int z = 2 * (N + Y(5 + 1));
//	return 0;
//}
//
//#include<stddef.h>
struct S
{
	int a;
	char c;
	double d;
};

#define OFFSETOF(type,name)   (size_t)&(((type*)0)->name) 

int main()
{
	struct S s;
	printf("%d\n", OFFSETOF(struct S, a));
	printf("%d\n", OFFSETOF(struct S, c));
	printf("%d\n", OFFSETOF(struct S, d));
	return 0;
}
//
#define SWAP_BIT(x)  (x = (((x & 0x55555555) << 1) + ((x & 0xaaaaaaaa) >> 1)))

int main()
{
	int a = 5;
	SWAP_BIT(a);
	printf("%d", a);
	return 0;
}
//
//void Func1()
//{
//	int a = 0;
//	printf("%p\n", &a);
//}
//
//void Func2()
//{
//	int b = 0;
//	printf("%p\n", &b);
//}
//
//int main()
//{
//	Func1();
//	Func2();
//
//
//	return 0;
//}


#include"Seqlist.h"

void test1()
{
	SL s;
	SLInit(&s);
	SLPushBack(&s, 1);
	SLPushBack(&s, 2);
	SLPushBack(&s, 3);
	SLPushBack(&s, 4);
	SLPrint(&s);
	SLPushFront(&s, 5);
	SLPushFront(&s, 4);
	SLPushFront(&s, 3);
	SLPushFront(&s, 2);
	SLPrint(&s);
	SLDestroy(&s);
}
void test2()
{
	SL s;
	SLInit(&s);
	SLPushBack(&s, 1);
	SLPushBack(&s, 2);
	SLPushBack(&s, 3);
	SLPushBack(&s, 4);
	SLPrint(&s);
	SLInsert(&s, 3, 6);
	SLInsert(&s, 2, 4);
	SLPrint(&s);
	SLErase(&s, 2);
	SLPrint(&s);
	SLDestroy(&s);
}

void test3()
{
	SL s;
	SLInit(&s);
	SLPushBack(&s, 1);
	SLPushBack(&s, 2);
	SLPushBack(&s, 3);
	SLPushBack(&s, 4);
	/*int pos = SLFind(&s, 2);
	printf("%d\n", pos);*/
	Modify(&s, 1, 5);
	SLPrint(&s);
	SLDestroy(&s);
}
int main()
{
	test3();
	return 0;
}

总结

本次的顺序表实现就到此为止啦,这是刚开始的分享哦!请大家持续关注我!

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

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

相关文章

CSAPP第五章 面向编译器的优化(2)

回顾 先复习一下之前的东西。 练习5.7 我们可以看到&#xff0c;相比combine4生成的基于指针的代码&#xff0c;GCC使用了C代码中数组引 用的更加直接的转换。循环索引i在寄存器rdx中&#xff0c;data的地址在寄存器rax中。和 前面一样&#xff0c;累积值acc在向量寄存器xm…

bthome协议分析及esp32上的实现

前言 最近自己搞了些智能家居的小节点&#xff0c;但由于wifi入网方式功耗太高&#xff0c;于是关注起了蓝牙 bthome是一种灵活的低功耗BLE数据格式协议&#xff0c;用于广播传感器数据&#xff0c;此协议支持数据加密&#xff0c;目前最新为v2版本。在home assistant中也支持…

( “树” 之 BST) 108. 将有序数组转换为二叉搜索树 ——【Leetcode每日一题】

108. 将有序数组转换为二叉搜索树 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 示例 1&#xff1a; 输入…

【pytorch函数笔记】torch.split

官方文档&#xff1a;https://pytorch.org/docs/stable/generated/torch.split.html?highlightsplit torch.split(tensor, split_size_or_sections, dim0) Splits the tensor into chunks. Each chunk is a view of the original tensor. If split_size_or_sections is an in…

栈的基本操作(C语言实现)创建,销毁,入栈,出栈

前言 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈&#xff1a;栈的…

Linux网络编程服务端的创建

文章目录 前言一、编程前的准备1.相关函数的了解二、accept函数特别注意点三、具体函数的实现四、运行客户端和服务端进行通信验证总结前言 上篇文章讲解了如何创建一个客户端,这篇文章将创建一个服务端用来和上篇文章的客户端进行通信。 一、编程前的准备 1.相关函数的了解…

服务(第九篇)tomcat的部署和优化

tomcat的介绍&#xff1a; 免费的、开放源代码的Web应用服务器&#xff08;用java开发的&#xff09; Apache软件基金会(Apache Software Foundation)Jakarta项目中的一个核心项目 由Apache、Sun和一些公司及个人共同开发而成 深受Java爱好者的喜爱&#xff0c;并得到部分软…

干货|实验操作难入门?快来看JoVE视频网站!

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐~ 当导师要求我们学习、模仿一些学术大神所做的心理学实验&#xff0c;尤其是采用脑影像、脑电技术等高端仪器的实验时&#xff0c;我们往往会因为缺少对具体操作细节的了解而感到困惑或困难。…

【python视图2】基于networkx的10个绘图技巧

一、说明 networkx在02年5月产生&#xff0c;是用python语言编写的软件包&#xff0c;便于用户对复杂网络进行创建、操作和学习。利用networkx可以以标准化和非标准化的数据格式存储网络、生成多种随机网络和经典网络、分析网络结构、建立网络模型、设计新的网络算法、进行网络…

MIPI摄像头工程=7系列FPGA + OV5640(MIPI) + 15 分钟 + VITIS

项目使用东西 硬件 Spartan-7 SP701 FPGA 7系列FPGA电阻网络实现的MIPI接口 OV5640 MIPI接口 软件 AMD Vivado 2020 版本以上 AMD Vitis 2020 介绍 MIPI 接口现在非常流行&#xff0c;国产FPGA目前基本都带MIPI接口&#xff0c;而AMD-Xilinx是从U系列开始支持MIPI电平&#x…

使用CMake的CPack工具打包项目

为了介绍如何使用CMake的CPack工具进行项目打包&#xff0c;这里使用了前文CMake项目使用ctestgtest进行单元测试中的示例。 为了更接近实际开发中项目的情况&#xff0c;自行下载gtest并进行源码编译来模拟实际项目中的依赖项&#xff1b;在实际的开发中&#xff0c;可能会有…

chatgpt智能提效职场办公-ppt怎么压缩文件大小

作者&#xff1a;虚坏叔叔 博客&#xff1a;https://xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; 压缩PPT文件大小有以下几种方法&#xff1a; 压缩图片大小&#xff1a;在PPT当中&#xff0c;图片是占用存储空间最大的部分&#xff0…

物联网多协议、多场景自定义测试|XMeter Cloud 更新

近日&#xff0c;全球首个物联网 MQTT 负载测试云服务 XMeter Cloud 推出了自定义场景测试功能。 该功能将满足用户自主定义测试场景和测试更广泛协议的需求&#xff0c;实现对除 MQTT 以外的 TCP、WebSocket、HTTP 等其他网络协议的测试&#xff0c;帮助用户构建更复杂的测试…

mybatis模糊查询以及结果封装详解

mybatis模糊查询以及结果封装详解 创建maven项目&#xff1a;项目结构如图所示 准备数据库表&#xff1a; 准备pom.xml所需的依赖&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0…

程序地址空间(下)

目录 &#xff1a; 1.接上部分内容再谈谈地址空间是什么&#xff1f;&#xff1f; 2.页表MMU&#xff08;硬件设备&#xff09; 3.为什么要搞个虚拟地址映射到物理地址 4.解释为什么最开始的问题&#xff1f;&#xff1f;&#xff1f; ---------------------------------------…

Spring 的 IoC(控制反转)

IoC 是 Inversion of Control 的简写&#xff0c;译为“控制反转”&#xff0c;它不是一门技术&#xff0c;而是一种设计思想&#xff0c;也是一个概念&#xff0c;同时是一个重要的面向对象编程法则&#xff0c;能够指导我们如何设计出松耦合、更优良的程序。 在这里说 IoC 之…

Java ---包装类

&#xff08;一&#xff09;包装类概念 官方说法&#xff1a; Java是面向对象的语言&#xff0c;但是为了便于开发者的使用&#xff0c;Java中却沿用了C语言的基本数据类型&#xff0c;在进行基本的数据计算时&#xff0c;开发者可以直接使用基础类。但是当需要和Java其他对象…

如何理解ThreadLocal

ThreadLocal的基本概念 在并发编程中&#xff0c;多个线程访问同一个变量&#xff0c;可能会出现线程安全问题、为了保证在多线程环境下访问共享变量的安全性&#xff0c;通常在访问共享变量的时候加锁&#xff0c;以实现线程同步的效果。 使用同步锁机制保证多线程访问共享变…

ChatGPT | 一文详解ChatGPT(学习必备)

本文概要 本篇文章主要介绍ChatGPT的产生和使用体验&#xff0c;适合不了解ChatGPT或者了解不够透彻的小伙伴&#xff0c;文中的描述非常详细&#xff0c;干货满满&#xff0c;感兴趣的小伙伴快来一起学习吧&#xff01; &#x1f31f;个人简介 ☀️大家好&#xff01;我是新人…

信息的相关性和冗余度:信息在整个文明中的作用

文章目录 I 古埃及的象形文字1.1 罗塞塔石碑1.2 古埃及文字音节和希腊字母的对应表1.3 破解古埃及文字 I 古埃及的象形文字 1.1 罗塞塔石碑 这个石碑是在公元前196年埃及国王托勒密五世加冕一周年的诏书。 在此前大约一百年&#xff0c;埃及已经被来自希腊北方城邦的亚历山大…