顺序表的增、删、改、查

news2024/11/16 14:24:36

小伙伴们好,学完C语言,就要开始学数据结构了,数据结构也是非常重要的,今天我们主要来学习在数据结构中最常用的增删改查操作。话不多说,一起来学习吧

1.数据结构相关概念

1.什么是数据结构?

数据结构是由“数据”和“结构”两词组合⽽来。
什么是数据?常⻅的数值1、2、3、4.....、教务系统⾥保存的⽤⼾信息(姓名、性别、年龄、学历等等)、⽹⻚⾥⾁眼可以看到的信息(⽂字、图⽚、视频等等),这些都是数据。
什么是结构?
当我们想要使⽤⼤量使⽤同⼀类型的数据时,通过⼿动定义⼤量的独⽴的变量对于程序来说,可读性⾮常差,我们可以借助数组这样的数据结构将⼤量的数据组织在⼀起,结构也可以理解为组织数据的⽅式。
想要找到草原上名叫“咩咩”的⽺很难,但是从⽺圈⾥找到1号⽺就很简单,⽺圈这样的结构有效将
⽺群组织起来。
概念:数据结构是计算机存储、组织数据的⽅式。数据结构是指相互之间存在⼀种或多种特定关系
的数据元素的集合。数据结构反映数据的内部构成,即数据由那部分构成,以什么⽅式构成,以及数据元素之间呈现的结构。
总结:
1)能够存储数据(如顺序表、链表等结构)
2)存储的数据能够⽅便查找
2、为什么需要数据结构?
如图中所⽰,不借助排队的⽅式来管理客⼾,会导致客⼾就餐感受差、等餐时间⻓、餐厅营业混乱等情况。同理,程序中如果不对数据进⾏管理,可能会导致数据丢失、操作数据困难、野指针等情况。通过数据结构,能够有效将数据组织和管理在⼀起。按照我们的⽅式任意对数据进⾏增删改查等操作。
最基础的数据结构:数组。
【思考】有了数组,为什么还要学习其他的数据结构?
假定数组有10个空间,已经使⽤了5个,向数组中插⼊数据步骤:
求数组的⻓度,求数组的有效数据个数,向下标为数据有效个数的位置插⼊数据(注意:这⾥是
否要判断数组是否满了,满了还能继续插⼊吗).....
假设数据量⾮常庞⼤,频繁的获取数组有效数据个数会影响程序执⾏效率。
结论:最基础的数据结构能够提供的操作已经不能完全满⾜复杂算法实现。

2.顺序表

2.1 顺序表的概念及结构

1.线性表

线性表( linear list )是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中⼴泛使
⽤的数据结构,常⻅的线性表:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的,
线性表在物理上存储时,通常以数组和链式结构的形式存储。
案例:蔬菜分为绿叶类、⽠类、菌菇类。线性表指的是具有部分相同特性的⼀类数据结构的集合
顺序表:逻辑结构是线性的,物理结构是连续的
2.2顺序表分类
顺序表和数组的区别
        ◦ 顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝
顺序表分类
        ◦ 静态顺序表
                概念:使用定长数组存储元素
静态顺序表缺陷:空间给少了不够⽤,给多了造成空间浪费
动态顺序表

3.动态顺序表的实现

首先我们要创建3个文件,分别是1个头文件SeqList.h,2个源文件SeqList.c和test.c.它们的作用分别是:

SeqList.h:头文件的作用是定义顺序表的结构,顺序表要实现的接口/方法

SeqList.c:具体实现顺序表里定义的接口/方法

test.c:测试动作:测试顺序表

OK,文件准备好了,现在就开始写代码了

首先我们要给数据类型起一个别名,为什么呢?假设我们写了1000行代码,里面使用到了非常多的数据类型,假定全是int类型,有一天别人让你把一些int类型改成char类型,那么你就要一个一个的把int改成char,虽然你们想说不是可以一键替换吗,这个方法也可以,但是不是全部都要改成char类型,这不是最佳的方法。所以作为程序员我们要专业一点,于是就要给自定义的给int类型取个别名,取什么名字可以自己决定,专业的人就要干专业的事。比如说我们可以改成这个

typedef int SLDataType;

这样就能解决上面的问题了,你想要改成什么数据类型,就只需要把int改成你要的类型。是不是很方便呢。

我们首先要做一些准备工作,方便为接下来的操作做准备

3.1定义结构体
typedef struct SeqList  
{
	SLDataType* arr;//存储数据的底层结构
	int capacity;   //记录顺序表的空间大小
	int size;       //记录顺序表当前有效的数据个数
}SL;

细心的小伙伴们发现我也给结构体取了一个别名SL,这样也是为了方便接下来的使用。

当然你也可以这样写

struct SeqList  
{
	SLDataType* arr;//存储数据的底层结构
	int capacity;   //记录顺序表的空间大小
	int size;       //记录顺序表当前有效的数据个数
};

typedef struct SeqList SL;  
3.2 结构体的初始化和销毁

在SeqList.h文件中定义初始化和销毁的函数,具体实现方法要在SeqList.c文件中实现

可能有人会这么写

这样写会报错,因为这样写是传值调用,而我们要传地址。所以正确写法是下面这种

void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLInit(SL* ps)//ps是形参
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

void SLDestroy(SL* ps)
{
	assert(ps);
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

我们可以测试一下

好了,这么写没有问题。

好了,准备工作基本完成。正式开始我们的增删改查吧。

3.3插入数据:尾插和头插

首先要分析空间够不够。

空间足够:直接插入,假设插入的数据是x=6,即arr[size]=6,size是有效数据的下一个

空间不够:扩容。那么扩容的方法有哪些呢?

  1. 一次扩充一个空间:插入一个元素还不会造成空间浪费
  2. 一次扩容固定个大小空间(10,100……)
  3. 成倍数的增加(1.5倍,2倍)

第一个方法虽然不会造成空间的浪费,但是由于扩容的频率太高会造成程序效率低下

第二个方法空间给小了,还需要继续扩容,也会造成程序效率低下,给大了又可能会造成空间的浪费。

这里我推荐第三个方法,成2倍数的增加(依次扩大4,8,16,32……个空间)数据插入的越多,扩容的空间越来越大,数据和扩容量成正相关,浪费也不会造成太多的浪费。扩容的方法是使用realloc函数,realloc函数使用方法可以看我这篇文章http://t.csdnimg.cn/rwb7g

头插的难点是如何将数据往后挪动

如果直接在第一个位置插入数据,那么就会造成数据丢失 !所以就要从后往前挪动,把第i个位置移到第i-1的位置处。

由于头插和尾插都要判断是否扩容,所以我们要将扩容空间单独写一个函数,这样空间不够的时候可以直接调用

扩容函数

void SLCheckCapacity(SL* ps)
{
	if (ps->size == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//扩容成倍数增加,每次扩容2倍
		//ps->arr=(SLDataType*)realloc(ps->arr,2 * ps->capacity)
		//不能这样写,因为初始化capacity为0
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));//要乘以数据类型的大小
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);//扩容失败直接中断程序
		}
		//扩容成功
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
}
//顺序表的头部/尾部的插入
void SLPushBack(SL* ps,SLDataType x);//尾插
void SLPushFront(SL* ps, SLDataType x);//头插
void SLPushBack(SL* ps, SLDataType x)//尾插
{
	assert(ps != NULL);

	//空间不够,扩容。当capacity <= size时
	SLCheckCapacity(ps);
	//空间足够,直接插入。当capacity>size时
	ps->arr[ps->size++] = x;
	//ps->size++;
}

void SLPushFront(SL* ps, SLDataType x)//头插
{
	assert(ps != NULL);

	//判断是否扩容
	SLCheckCapacity(ps);
	//旧数据往后挪动一位
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;
}

测试尾插

测试头插

打印函数

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

ok,扩容没有问题,这样就说明增加操作没有问题了。另外不能传入一个空值,所以要进行assert断言。

3.4 删除数据:头删和尾删

删除数据要分两种情况:顺序表为空,则不能进行删除;顺序表不为空,尾删则删除最后一个有效数据,size--。头删就要删除第一个数据,然后把后面的数据往前挪动

//顺序表的头部/尾部的删除
void SLPoBack(SL* ps);
void SLPoFront(SL* ps);
//顺序表的头部/尾部的删除
void SLPoBack(SL* ps)
{
	assert(ps != NULL);
	assert(ps->size);//顺序表为空不能进行删除

	//顺序表不为空
	ps->size--;
}

void SLPoFront(SL* ps)
{
	assert(ps != NULL);
	assert(ps->size);//顺序表为空不能进行删除

	//不为空执行挪动操作,后面的数据往前挪动一位
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}
测试尾删

测试头删

 3.5 指定位置删除或者插入数据

指定位置之前插入数据

void SLInsert(SL* ps, int pos, SLDataType x);
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);//pos不能超过当前顺序表的有效数据
	SLCheckCapacity(ps);//检查是否有空间可以插入

	//pos及之后的数据往后挪动一位,pos空出来,size++
	for (int i=ps->size; i>pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos] = x;
	ps->size++;
}

 测试:

删除指定位置的数据

void SLErase(SL* ps, int pos);
void SLErase(SL* ps, int pos)
{
	assert(ps != NULL);
	assert(pos >= 0 && pos < ps->size);//只能对size之前的数据进行删除
	
	//pos以后的数据往前挪动一位
	for (int i=pos; i<ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

测试

3.6 查找数据
int SLFind(SL* ps, SLDataType x);
int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->arr[i] == x)
		{
			return i;
		}
	}
	return -1;
}

测试

3.7 修改数据
void SLRevise(SL* ps,int pos,SLDataType x);
void SLRevise(SL* ps,int pos,SLDataType x)
{
	if (pos >= ps->size)
		printf("修改失败!要修改的元素不存在\n");
	else
	{
		printf("修改成功,新数据为:");
		ps->arr[pos] = x;
	}
}

测试 

4.完整代码呈现

 SeqList.h

#pragma once
//头文件的作用是定义顺序表的结构,顺序表要实现的接口/方法
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

//动态顺序表
//typedef Info SLDataType;

typedef int SLDataType;
typedef struct SeqList  //方法一
{
	SLDataType* arr;//存储数据的底层结构
	int capacity;   //记录顺序表的空间大小
	int size;       //记录顺序表当前有效的数据个数
}SL;

//typedef struct SeqList SL;   //方法二

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

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

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

//指定位置之前插入数据
//删除指定位置的数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, SLDataType x);

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

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
//具体实现顺序表里定义的接口/方法
#include"SeqList.h"
//初始化和销毁
void SLInit(SL* ps)//ps是形参
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

void SLCheckCapacity(SL* ps)
{
	if (ps->size == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//扩容成倍数增加,每次扩容2倍
		//ps->arr=(SLDataType*)realloc(ps->arr,2 * ps->capacity)
		//不能这样写,因为初始化capacity为0
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));//要乘以数据类型的大小
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);//扩容失败直接中断程序
		}
		//扩容成功
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
}

//顺序表的头部/尾部的插入
void SLPushBack(SL* ps, SLDataType x)//尾插
{
	assert(ps != NULL);

	//空间不够,扩容。当capacity <= size时
	SLCheckCapacity(ps);
	//空间足够,直接插入。当capacity>size时
	ps->arr[ps->size++] = x;
	//ps->size++;
}

void SLPushFront(SL* ps, SLDataType x)//头插
{
	assert(ps != NULL);

	//判断是否扩容
	SLCheckCapacity(ps);
	//旧数据往后挪动一位
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;
}

//顺序表的头部/尾部的删除
void SLPoBack(SL* ps)
{
	assert(ps != NULL);
	assert(ps->size);//顺序表为空不能进行删除

	//顺序表不为空
	ps->size--;
}

void SLPoFront(SL* ps)
{
	assert(ps != NULL);
	assert(ps->size);//顺序表为空不能进行删除

	//不为空执行挪动操作,后面的数据往前挪动一位
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

//指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);//pos不能超过当前顺序表的有效数据
	SLCheckCapacity(ps);

	//pos及之后的数据往后挪动一位,pos空出来,size++
	for (int i=ps->size; i>pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos] = x;
	ps->size++;
}

//删除指定位置的数据
void SLErase(SL* ps, int pos)
{
	assert(ps != NULL);
	assert(pos >= 0 && pos < ps->size);//只能对size之前的数据进行删除
	
	//pos以后的数据往前挪动一位
	for (int i=pos; i<ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

//在顺序表中查找x
int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->arr[i] == x)
		{
			return i;
		}
	}
	return -1;
}

//修改数据
void SLRevise(SL* ps,int pos,SLDataType x)
{
	if (pos >= ps->size)
		printf("修改失败!要修改的元素不存在\n");
	else
	{
		printf("修改成功,新数据为:");
		ps->arr[pos] = x;
	}
}

void SLDestroy(SL* ps)
{
	assert(ps);
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

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

test.c

#define _CRT_SECURE_NO_WARNINGS 1
//测试动作:测试顺序表
#include"SeqList.h"

void slTest01()
{
	SL sl;
	SLInit(&sl);//传址调用

	//测试尾插
	/*SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPrint(&sl);	*///1 2 3 4
	//SLPushBack(&sl, 5);
	//SLPrint(&sl);	//1 2 3 4



	测试头插
	/*SLPushFront(&sl, 5);
	SLPushFront(&sl, 6);
	SLPushFront(&sl, 7);
	SLPrint(&sl);*/

	//测试尾删
	/*SLPoBack(&sl);
	SLPoBack(&sl);
	SLPrint(&sl);*/

	//测试头删
	/*SLPoFront(&sl);
	SLPoFront(&sl);
	SLPrint(&sl);*/

	//测试指定位置插入
	//SLInsert(&sl, 0, 100);
	//SLPrint(&sl);
	//SLInsert(&sl, sl.size, 200);//在size位置插入数据
	//SLPrint(&sl);

	//测试删除指定位置的数据
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPrint(&sl);

	SLErase(&sl, 2);
	SLPrint(&sl);
	/*SLErase(&sl, sl.size - 1);
	SLPrint(&sl);*/
    
    //修改数据
	SLRevise(&sl, 1, 5);
	SLPrint(&sl);
	SLRevise(&sl, 4, 5);
}

void slTest02()
{
	SL sl;
	SLInit(&sl);//传址调用

	//测试尾插
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPrint(&sl);

	//测试查找
	int ret = SLFind(&sl, 2);
	if (ret < 0)
	{
		printf("数据不存在,查找失败!");
	}
	else {
		printf("数据找到了,在下标为%d的位置\n", ret);
	}
}

//void slTest03()
//{
//	SL sl;
//	SLInit(&sl);
//	SLDestroy(&sl);
//}

int main()
{
	//slTest01();
	slTest02();
	//slTest03();
	return 0;
}

终于大功告成了,感谢小伙伴们能看到这里,说明你们都想学好C语言,小伙伴们,我们一起加油。根据这个增删查改,我们就可以写出一个小程序了,那么就是通讯录的实现。等我有时间了我也会把通讯录的实现分享出来,供大家学习参考。感谢各位观看。

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

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

相关文章

【Web前端开发基础】CSS3之Web字体、字体图标、平面转换、渐变

CSS3之Web字体、字体图标、平面转换、渐变 目录 CSS3之Web字体、字体图标、平面转换、渐变一、Web字体1.1 Web字体概述1.2 字体文件1.3 font-face 规则 二、字体图标2.1 字体图标2.2 字体图标的优点2.3 图标库2.4 下载字体包2.5 字体图标的使用步骤2.6 字体图标使用注意点2.7 上…

12.常用统计分析方法——聚类分析

目录 基础知识 实操 层次聚类 划分聚类 方法一&#xff1a;K均值聚类&#xff08;最常见&#xff09; 方法二&#xff1a;基于中心点的划分&#xff08;PAM&#xff09; 避免不存在的类 基础知识 概念&#xff1a; 聚类分析是一种数据归约技术&#xff0c;旨在揭露一个…

prometheus监控RabbitMQ策略

一般用官方的rabbitmq_exporter采取数据即可&#xff0c;然后在普米配置。但如果rabbitmq节点的队列数超过了5000&#xff0c;往往rabbitmq_exporter就会瘫痪&#xff0c;因为rabbitmq_exporter采集的信息太多&#xff0c;尤其是那些队列的细节&#xff0c;所以队列多了&#x…

vue3-深入组件-组件注册和props更多细节

组件注册 定义好的组件需要注册才能被使用。 注册方式有两种 全局注册 局部注册 全局注册 .component() 方法&#xff0c;让组件在当前 Vue 应用中全局可用。 在 main.ts 中 import ./assets/main.cssimport { createApp } from vue import { createPinia } from pinia i…

无人机航迹规划(五):七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划(提供MATLAB代码)

一、七种算法&#xff08;DBO、LO、SWO、COA、LSO、KOA、GRO&#xff09;简介 1、蜣螂优化算法DBO 蜣螂优化算法&#xff08;Dung beetle optimizer&#xff0c;DBO&#xff09;由Jiankai Xue和Bo Shen于2022年提出&#xff0c;该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁…

10. UE5 RPG使用GameEffect创建血瓶修改角色属性

前面我们通过代码实现了UI显示角色的血量和蓝量&#xff0c;并实现了初始化和在数值变动时实时更新。为了测试方便&#xff0c;没有使用GameEffect去修改角色的属性&#xff0c;而是通过代码直接修改的数值。 对于GameEffect的基础&#xff0c;这里不再讲解&#xff0c;如果需要…

微机原理常考填空以及注意事项第(三)弹~

前面已经总结了200个常考题注意事项&#xff0c;可以翻阅查看。 以下仅个人总结的易错以及注意事项&#xff1a; 1&#xff0c;汇编语言源程序的基本格式&#xff1a; DATA SEGMENT;存放数据项的数据段 DATA ENDS EXTRA SEGMENT;存放数据项的附加段 EXTRA ENDS STACK1 SEGM…

Mybatis四大组件

一、Mybatis四大组件 SqlSessionFactoryBuild、SqlSessionFactory、SqlSession、Mapper。 二、SqlSession四大对象 Executor、StatementHandler、ParameterHandler、ResultSetHandler。 这里阐述一下上图的流程 Exeutor发起sql执行任务 1、先调用statementHandler中的pre…

输入某年某月某日,判断这一天是这一年的第几天?(Java)

思路&#xff1a; 1&#xff0c;分别定义三个变量来接收 年 月 日 2&#xff0c;累加已经过完的月份的天数 日期 3&#xff0c;二月份的天数要根据是否是闰年&#xff0c;随之改变 1 3 5 7 8 10 12 ---> 31天 4 6 9 11 ---> 30天 2 ---> 闰…

【bioinfo】收藏生信常用网址

文章目录 文件格式文档SAM/VCF工具手册bwa/samtools基因组统计学wikisam flag值查询序列反向互补TransVar 变异注释UCSC-blat在线比对常用数据库 NCBI/nsembl/HGNC论坛 biostars/SEQanswers查询文献影响因子假设检验查询生信软件查询在线可视化工具Proksee 文件格式文档SAM/VCF…

阿里云国外服务器价格购买与使用策略

阿里云国外服务器优惠活动「全球云服务器精选特惠」&#xff0c;国外服务器租用价格24元一个月起&#xff0c;免备案适合搭建网站&#xff0c;部署独立站等业务场景&#xff0c;阿里云服务器网aliyunfuwuqi.com分享阿里云国外服务器优惠活动&#xff1a; 全球云服务器精选特惠…

为什么JDK1.7的HashMap会出现扩容死链

为什么JDK1.7的HashMap会出现扩容死链&#xff1f; JDK1.7版本的HashMap在多线程的情况下扩容出现死循环&#xff08;扩容死链&#xff09;&#xff0c;根本原因是&#xff1a;HashMap在进行扩容时需要进行数据转移&#xff0c;jdk1.7的版本数据转移使用的是头插法&#xff08…

【每日一题】最大交换

文章目录 Tag题目来源解题思路方法一&#xff1a;暴力法方法二&#xff1a;贪心 写在最后 Tag 【暴力法】【贪心法】【数组】【2024-01-22】 题目来源 670. 最大交换 解题思路 本题的数据规模比较小&#xff0c;暴力法也可以通过。以下将会介绍暴力法和本题最优法。 方法一…

【AIGC】Diffusers:扩散模型的开发手册说明1

主要组件 最先进的扩散管道 diffusion pipelines&#xff0c;只需几行代码即可进行推理。可交替使用的各种噪声调度器 noise schedulers&#xff0c;用于平衡生成速度和质量。预训练模型 models&#xff0c;可作为构建模块&#xff0c;并与调度程序结合使用&#xff0c;来创建…

阿赵UE学习笔记——12、植物系统

阿赵UE学习笔记目录 大家好&#xff0c;我是阿赵。   继续学习虚幻引擎的用法。这次需要使用植物系统在地形上添加一些草和石头的装饰。 一、素材准备 之前介绍过&#xff0c;可以在Quixel上面获取免费的资源&#xff0c;所以我这里就下载了一些资源&#xff0c;有草和石头的…

基于springboot家政服务管理平台源码和论文

随着家政服务行业的不断发展&#xff0c;家政服务在现实生活中的使用和普及&#xff0c;家政服务行业成为近年内出现的一个新行业&#xff0c;并且能够成为大众广为认可和接受的行为和选择。设计家政服务管理平台的目的就是借助计算机让复杂的销售操作变简单&#xff0c;变高效…

代码随想录刷题笔记 DAY12 | 二叉树的理论基础 | 二叉树的三种递归遍历 | 二叉树的非递归遍历 | 二叉树的广度优先搜索

Day 12 01. 二叉树的理论基础 1.1 二叉树的种类 满二叉树&#xff1a;除了叶子节点以外&#xff0c;每个节点都有两个子节点&#xff0c;整个树是被完全填满的完全二叉树&#xff1a;除了底层以外&#xff0c;其他部分是满的&#xff0c;底部可以不是满的但是必须是从左到右连…

Java 设计者模式以及与Spring关系(六) 装饰和模版方法模式

简介: 本文是个系列一次会出两个设计者模式作用&#xff0c;如果有关联就三个&#xff0c;除此外还会讲解在spring中作用。 23设计者模式以及重点模式 我们都知道设计者模式有3类23种设计模式&#xff0c;标红是特别重要的设计者模式建议都会&#xff0c;而且熟读于心&#…

41.while语句

目录 一.什么是while语句 二.语法 三.执行流程图 四.举例 五.视频教程 一.什么是while语句 只要条件为真&#xff0c;while循环中的语句会一直重复执行。 二.语法 while&#xff08;表达式&#xff09;{//代码块 } 三.执行流程图 从流程图可以看出&#xff0c;while循环…

【JAVA语言-第14话】集合框架(一)——Collection集合,迭代器,增强for,泛型

目录 集合框架 1.1 概述 1.2 集合和数组的区别 1.3 Collection集合 1.3.1 概述 1.3.2 常用方法 1.4 迭代器 1.4.1 概述 1.4.2 常用方法 1.4.3 使用步骤 1.5 增强for循环 1.5.1 概述 1.5.2 使用 1.6 泛型 1.6.1 概述 1.6.2 使用泛型的利弊 1.6.2.1 好处 1…