掌握顺序表,成为数据结构和算法的高手

2023-05-16

文章目录

  • 1. 线性结构与线性表
  • 2. 线性表的顺序存储
  • 3. 顺序表的基础操作
    • 🍑 顺序表接口总览
    • 🍑 初始化顺序表
    • 🍑 销毁链表
    • 🍑 插入操作
    • 🍑 删除操作
    • 🍑 获取元素操作
      • 🍅 按位置获取
      • 🍅 按元素值获取
    • 🍑 打印操作
    • 🍑 获取表的长度
    • 🍑 翻转顺序表
    • 🍑 判断顺序表是否为空
    • 🍑 扩容操作
    • 🍑 头插操作
    • 🍑 尾插操作
    • 🍑 头删操作
    • 🍑 尾删操作
  • 4. 总结

1. 线性结构与线性表

线性结构是一种数据结构,其中保存的数据像一条线一样按顺序排列,数据之间是一对一的关系,也就是每个数据只有一个直接前驱和一个直接后继。不过,第一个数据没有前趋,最后一个数据没有后继,这意味着数据之间只有简单的前后(相邻)次序关系。可以想象一下排队的情景,这就是线性结构。

线性表是一种线性结构,是具有相同数据类型的 n(n≥0)个数据的有限序列,其中 n 是线性表的长度。其一般表示为( a 1 , a 2 , … a i , a i + 1 , … , a n a1,a2,…ai,ai+1,…,an a1,a2,ai,ai+1,,an)。当 n=0 时,线性表就是一个空表。

在一般表示中,a1 是第一个数据,ai 是第 i 个数据,an 是最后一个数据,这表示线性表中的数据是有先后次序的。除 a1 外,每个数据有且仅有一个直接前驱数据,除 an 外,每个数据有且仅有一个直接后继数据。

这表示什么呢?我们可以发现,除第一个数据外总有办法根据当前数据找到其直接前驱,除最后一个数据外,总有办法根据当前数据找到其直接后继。要注意的是,每个数据所占用的存储空间大小相同。数组、链表、栈、队列等都属于线性表中的一种,或者也可以理解成,数组、链表、栈、队列等都可以用来表达线性表。

如下图所示,就是一个线性表

在这里插入图片描述

这里延伸一下,与线性表的概念相对应的,还有非线性表。非线性表里的数据之间并不是简单的一对一关系,可能是一对多或多对多关系。树、图、堆等都属于非线性表中的一种,后面都会进行详细讲解。

在这里插入图片描述

在有了一种数据结构之后(包括线性表、非线性表),一般还需要实现在该数据结构上的一些基本操作,才能够方便地操作其中的数据。我们习惯将这些基本操作封装成函数或接口,方便自己或团队其他成员使用,这样不但可以避免重复的工作,更可以在很大程度上减少对数据操作出错的可能性。

2. 线性表的顺序存储

线性表的顺序存储指的是用一段连续的内存空间依次存储线性表中的数据,而数组正好具有内存空间连续的特性,因此,线性表的顺序存储是采用一维数组来实现的(回忆一下 STL 中 vector 容器也是用一段连续的内存空间来保存数据),采用一维数组实现的线性表也叫做顺序表。

一维数组的存储结构如下:

在这里插入图片描述

如图所示,一维数组(简称数组)的下标从 0 开始,最大的数组下标为 n,这意味着整个数组能容纳 n+1 个元素。这里要注意,在实现顺序表时,有两点需要说明。

(1)随机访问

因为内存空间连续且数据类型相同,因此,随机访问数组中的任意元素(数据)就非常方便快捷。

那么什么是随机访问呢?它指的是通过数组首地址和所给元素下标就可以在最短的时间内找到任意的数组元素。另外,想一想,通过下标随机访问数组元素的时间复杂度是多少呢?

没错就是O(1)。

我们再来说说随机访问的地址又是怎么得到的。比如有一个长度为 10 的整型数组 a,首地址为是 1000,那么这个数组中第 3 个元素,也就是数组元素 a[2] 的地址,就可以直接用 a[i]地址 = 数组首地址 + 下标 *sizeof(整型) 得到。
举个例子,如果假设整型数据所占用的内存空间是 4 字节,那么数组元素 a[2] 的地址是 1000+2*4=1008。同理,数组元素 a[5] 的地址是 1000+5*4=1020

(2)插入或删除元素

在顺序存储中,插入或者删除元素可能会碰到的情况就是要求数据之间彼此要紧挨在一起,数据之间不允许有空位,也就是说必须保证数据之间内存的连续性,所以当向数组中插入元素或删除数组中元素时,必须要做大量的数据搬运工作,所以插入或删除元素的效率会变得很低。这一点,你在后续进行代码实现的时候,会体会得更加深刻。

顺序表的第一种实现方式:为一维数组静态分配内存。

比如,定义如下的 SeqList 结构来表示顺序表。

typedef struct
{ 
	int _data[10]; //静态数组来保存顺序表中的元素,一共10个位置(最多存入10个元素)
	int _length; //顺序表当前实际长度(当前顺序表中已经存入了多少个元素)
}SeqList;

上述代码中,数组 _data 的大小在编译时就已经确定,后续无法改变,这意味着该顺序表最多只能保存 10 个元素。

顺序表的第二种实现方式:为一维数组动态分配内存。比如,定义如下的 SeqList 结构来表示顺序表。

typedef struct
{ 
	int* data; // 顺序表中的元素保存在m_data所指向的动态数组内存中
	int length; // 顺序表当前实际长度
	int MaxSize; // 动态数组最大容量,因动态数组可以扩容,因此要记录该值
}SeqList;

上述代码中,数组 data 的大小事先是不确定的,在程序执行过程中,用 new 的方式为 data 指针(一维数组)分配一定数量的内存。当顺序表中数据元素逐渐增多,当前分配的内存无法容纳时,可以用 new 新开辟一块更大的内存,并将当前内存中的数据拷贝到新内存中去,同时把旧的内存释放掉。

通过静态分配内存方式与动态分配内存方式实现顺序表的过程,在程序代码上大同小异,但后者代码实现起来要更加复杂一些。因此,后续我会采用动态分配内存的方式来实现顺序表。

3. 顺序表的基础操作

了解整体框架之后,下面我们就来看一看顺序表的具体实现代码,包括基本框架、插入、删除、获取以及其它的一些常用操作。

🍑 顺序表接口总览

首先,要把顺序表相关的类的基本框架实现出来。

#define InitSize 10 //动态数组的初始尺寸
#define IncSize 5 //当动态数组存满数据后每次扩容所能多保存的数据元素数量

// 顺序表的定义
template<class T> // T代表数组中元素的类型
class SeqList
{
public:
	//构造函数,参数可以有默认值 
	SeqList(int length = InitSize); 
	
	//析构函数
	~SeqList();
public:
	//在第i个位置插入指定元素e
	bool ListInsert(int i, const T& e);

	//删除第i个位置的元素
	bool ListDelete(int i);

	//获得第i个位置的元素值
	bool GetElem(int i, T& e);

	//按元素值查找其在顺序表中第一次出现的位置
	int LocateElem(const T& e);

	//输出顺序表中的所有元素
	void DispList();

	//获取顺序表的长度
	int ListLength();

	//翻转顺序表
	void ReverseList();

	//判断是否为空表
	bool Empty();

	//头插
	bool ListPushFront(const T& e);

	//尾插
	bool ListPushBack(const T& e);

	//头删
	bool ListPopFront();

	//尾删
	bool ListPopBack();
private:
	// 当顺序表存满数据后可以调用此函数为顺序表扩容
	void IncreaseSize();
private:
	T* _data; // 存放顺序表中的元素
	int _length; // 存放顺序表中的元素
	int _maxsize; // 存放顺序表中的元素
};

我们在 main 主函数中,加入下面的代码就可以创建一个初始大小为 10 的顺序表对象了。

SeqList<int> sl(10);

🍑 初始化顺序表

通过构造函数对顺序表进行初始化

代码如下:

// 通过构造函数对顺序表进行初始化
template<class T>
SeqList<T>::SeqList(int length)
{
	_data = new T[length]; // 为一维数组动态分配内存
	_length = 0; // 顺序表当前实际长度为0,表示还未向其中存入任何数据元素
	_maxsize = length; // 顺序表最多可以存储maxsize个数据元素
} 

🍑 销毁链表

通过析构函数对顺序表进行资源释放。

代码如下:

// 通过析构函数对顺序表进行资源释放
template <class T>
SeqList<T>::~SeqList()
{
	delete[] _data; // 删除new出来的空间
	_length = 0; // 把length的长度置为0
}

🍑 插入操作

还记得我们刚刚说的顺序存储的特点吗?因为顺序表中每个数据元素在内存中是连续存储的,所以如果要在某个位置插入一个元素,则需要把原来该位置的元素依次向后移动。如下图所示:

在这里插入图片描述

仔细观察,如果我要将元素 10 插入到顺序表的第 3 个位置,为了保证元素之间内存的连续性,就需要将原来第 3 个位置以及第 3 个位置之后的所有元素依次向后移动 1 个位置,为新插入的元素腾出地方。

那么这里就有几点需要考虑的问题了。

(1)数组下标是多少?

这里所谈的插入位置是从编号 1 开始的,而数组下标是从 0 开始的,所以在写代码将插入的位置转换成数组下标时,需要减 1。

(2)先从谁开始移动呢?

在移动 3、4、5 这几个元素时,需要先把元素 5 移动到第 6 个位置,再把元素 4 移动到第 5 个位置,最后把元素 3 移动到第 4 个位置。也就是先从数组中最后一个元素开始依次向后移动。如果先把元素 3 移动到第 4 个位置了,那么就会把原来第 4 个位置的元素 4 直接覆盖掉。

(3)插入位置和原有长度有什么关系吗?

如果在第 3 个位置插入元素,则顺序表中必须至少要有 2 个元素。试想一下,如果顺序表为空或只有 1 个元素,那么它的第 2 个位置肯定是空的。因为顺序表中各个元素的内存必须是连续的,我们不可以隔着一个或者多个空位置向顺序表中插入元素。

(4)最后,如果顺序表已经满了,则不应该允许插入数据。

插入操作的实现代码如下:

// 在第i个位置(位置编号从1开始)插入指定元素e
// 时间复杂度:O(n),时间开销主要源于元素的移动
template<class T>
bool SeqList<T>::ListInsert(int i, const T& e)
{
	// 如果顺序表已经存满了数据,则不允许再插入新数据了
	if (_length >= _maxsize) {
		cout << "顺序表已满,不能再进行插入!" << endl;
		return false;
	}

	// 判断插入位置i是否合法,i的合法值应该是1到m_length+1之间
	if (i < 1 || i > (_length + 1)) {
		cout << "元素" << e << "插入的位置" << i << "不合法,合法的位置是1到" << _length + 1 << "之间!" << endl;
		return false;
	}

	// 从最后一个元素开始向前遍历到要插入新元素的第i个位置,分别将这些位置中原有的元素向后移动一个位置
	for (int j = _length; j >= i; --j) {
		_data[j] = _data[j - 1];
	}
	_data[i - 1] = e; // 在指定位置i处插入元素e,因为数组下标从0开始,所以这里用i-1表示插入位置所对应的数组下标
	cout << "成功在位置为" << i << "处插入元素" << _data[i - 1] << endl;  
	_length++; // 实际表长+1
	return true;
}

我们可以给出一组数据测试一下:

在这里插入图片描述

🍑 删除操作

因为顺序表中每个数据元素在内存中是连续存储的,所以如果删除某个位置的元素,则需要依次把该位置后面的元素依次向前移动。

如下图所示:

在这里插入图片描述

现在如果要将第 3 个位置的元素 10 删除,为了保证元素之间内存的连续性,需要将原来第 4 个位置以及第 4 个位置之后的所有元素依次向前移动 1 个位置,以保证元素之间的内存紧密相连。

那么这里就有几个需要考虑的问题了。

(1)先从谁开始移动呢?

在移动 3、4、5 这几个元素时,需要先把元素 3 移动到第 3 个位置,再把元素 4 移动到第 4 个位置,最后把元素 5 移动到第 5 个位置,也就是先从数组中要删除元素位置的后面一个位置的元素开始依次向前移动,且不可先把元素 5 移动到第 5 个位置,因为这样会把本来在第 5 个位置的元素 4 直接覆盖掉。

(2)另一方面,所要删除的位置必须有元素才可以删除。

我们看一下删除操作的实现代码:

// 删除第i个位置的元素
template<class T>
bool SeqList<T>::ListDelete(int i)
{
	// 当顺序表为空时,不能被删除
	if (_length < 1) {
		cout << "当前顺序表为空,不能删除任何数据!" << endl;
		return false;
	}

	// 当删除位置不合法时,不能被删除
	if (i < 1 || i > _length) {
		cout << "删除的位置" << i << "不合法,合法的位置是1到" << _length << "之间" << endl;
		return false;
	}

	// 删除i位置的元素
	// 注意删除i位置的元素,实际上该元素的下标是i-1
	cout << "成功删除位置为" << i << "处的元素,该元素的值为" << _data[i - 1] << endl;
	for (int j = i; j < _length; ++j) {
		_data[j - 1] = _data[j]; // 依次往前挪动
	}
	_length--; // 表长度-1
	return true;
}

我们可以给出一组数据测试一下:

在这里插入图片描述

🍑 获取元素操作

关于元素获取操作,我们分为两种情况来讨论:按位置获取和按元素值获取。

🍅 按位置获取

首先看一下如何按位置获取顺序表中元素值

代码如下:

// 获取第i个位置的元素值
template<class T>
bool SeqList<T>::GetElem(int i, T& e)
{
	//
	if (_length < 1) {
		cout << "当前顺序表为空,不能获取任何数据!" << endl;
		return false;
	}

	if (i < 1 || i > _length) {
		cout << "获取元素的位置" << i << "不合法,合法的位置是1到" << _length << "之间!" << endl;    
		return false;
	}

	// 参数e是引用类型参数,我们可以将该值带回,并对其进行修改
	e = _data[i - 1];
	cout << "成功获取位置为" << i << "的元素,该元素的值为" << _data[i - 1] << endl; 
	return true;
}

给出一组数据测试一下:

在这里插入图片描述

🍅 按元素值获取

再来看一看按元素值查找其在顺序表中第一次出现的位置

代码如下:

//按元素值查找其在顺序表中第一次出现的位置
template<class T>
int SeqList<T>::LocateElem(const T& e)
{
	for (int i = 0; i < _length; ++i)
	{
		if (_data[i] == e)
		{
			cout << "值为" << e << "的元素在顺序表中第一次出现的位置为" << i + 1 << endl;
			return i + 1;  //返回的位置应该用数组下标值+1
		}
	}
	cout << "值为" << e << "的元素在顺序表中没有找到" << endl;
	return -1;  //返回-1表示查找失败
}

给出一组数据测试一下:

在这里插入图片描述

🍑 打印操作

输出顺序表中的所有元素。

代码如下:

//输出顺序表中的所有元素,时间复杂度为O(n)
template<class T>
void SeqList<T>::DispList()
{
	for (int i = 0; i < _length; ++i)
	{
		cout << _data[i] << " ";  //每个数据之间以空格分隔
	}
	cout << endl; //换行
}

🍑 获取表的长度

获取顺序表的长度

代码如下:

//获取顺序表的长度,时间复杂度为O(1)
template<class T>
int SeqList<T>::ListLength()
{
	return _length;
}

🍑 翻转顺序表

所谓翻转顺序表,就是把顺序表中元素的排列顺序反过来,比如原来存放的元素是 1、2、3、4、5,那么翻转后存放的元素就是 5、4、3、2、1。

如下图所示:

在这里插入图片描述

解决这种问题并不难,只需要将第 1 个元素和第 5 个(最后一个)元素交换位置,第 2 个元素跟第 4 个(倒数第二个)元素交换位置,第 3 个元素保持不动即可。

🍑 判断顺序表是否为空

如果顺序表为空,返回 true,如果不为空,返回 false。

//判断是否为空表
template<class T>
bool SeqList<T>::Empty()
{
	//如果顺序表为空,则为true(1)
	//如果顺序表不为空,则为false(0)
	return _length == 0;
}

🍑 扩容操作

扩容是什么意思呢?比如在前面针对插入函数 ListInsert 的代码实现中,如果顺序表已经存满了数据,那就不允许再插入新数据了,这造成了一些使用中的不便,这个时候,我们当然希望顺序表能够自动扩容。

具体的实现思路,就是重新 new 一块比原顺序表所需内存更大一些的内存以便容纳更多的元素,然后把原来内存中的元素拷贝到新内存(这一步动作如果元素很多将很耗费时间)并把原内存释放掉(当然,这样做也是比较影响程序执行效率的)。

为此,引入成员函数 IncreaseSize,代码如下:

//当顺序表存满数据后可以调用此函数为顺序表扩容,时间复杂度为O(n)
template<class T>
void SeqList<T>::IncreaseSize()
{
	T* p = _data;
	_data = new T[_maxsize + IncSize]; //重新为顺序表分配更大的内存空间  
	for (int i = 0; i < _length; i++)
	{
		_data[i] = p[i];                //将数据复制到新区域
	}
	_maxsize = _maxsize + IncSize;     //顺序表最大长度增加IncSize
	delete[] p;                          //释放原来的内存空间
}

现在,就可以修改插入函数 ListInsert 的代码,以达到当顺序表满之后再插入数据时能够自动扩容的目的,只需要对 if 判断语句进行简单修改,其他代码不变,代码如下:

// 如果顺序表已经存满了数据,则不允许再插入新数据了
if (_length >= _maxsize) {
    IncreaseSize(); //扩容操作
}

🍑 头插操作

也就是在顺序表的头部插入元素

代码如下:

//头插
template<class T>
bool SeqList<T>::ListPushFront(const T& e)
{
	// 如果顺序表已经存满了数据,那么需要进行扩容
	if (_length >= _maxsize) {
		IncreaseSize();
	}

	int end = _length - 1;
	while (end >= 0) {
		_data[end + 1] = _data[end]; // 将数据 从后往前 依次 向后挪动
		--end;
	}
	_data[0] = e;
	_length++;
	return true;
}

给出一组数据进行测试:

在这里插入图片描述

🍑 尾插操作

尾插相对于头插就比较简单了,首先检查容量是否足够,如果不够,先扩容;如果够,直接 顺序表尾部插入数据即可

代码如下:

//尾插
template<class T>
bool SeqList<T>::ListPushBack(const T& e)
{
	// 如果顺序表已经存满了数据,那么需要进行扩容
	if (_length >= _maxsize) {
		IncreaseSize();
	}
	_data[_length] = e;
	_length++; // 插入完以后,顺序表元素个数加一
	return true;
}

给出一组数据进行测试:

在这里插入图片描述

🍑 头删操作

要删除顺序表头部的数据,我们可以从下标为 1 的位置开始,依次将数据 向前覆盖 即可

代码如下:

//头删
template<class T>
bool SeqList<T>::ListPopFront()
{
	// 当顺序表为空时,不能被删除
	if (_length < 1) {
		cout << "当前顺序表为空,不能删除任何数据!" << endl;
		return false;
	}
	int begin = 1;
	while (begin < _length) {
		_data[begin - 1] = _data[begin]; // 将数据依次向前覆盖
		++begin;
	}
	_length--; // 顺序表元素个数减一
	return true;
}

给出一组数据进行测试:

在这里插入图片描述

🍑 尾删操作

从顺序表 尾部 删除数据的话,就更简单了,因为我们的顺序表是动态内存开辟的,所以直接将 顺序表的元素个数减一 即可。

代码如下:

//尾删
template<class T>
bool SeqList<T>::ListPopBack()
{
	// 当顺序表为空时,不能被删除
	if (_length < 1) {
		cout << "当前顺序表为空,不能删除任何数据!" << endl;
		return false;
	}
	_length--;
	return true;
}

给出一组数据进行测试:

在这里插入图片描述

4. 总结

总结一下顺序表的几个重要的特点

  • 通过下标随机访问数组元素的时间复杂度仅为 O(1)。
  • 存储的数据紧凑,表中的元素在内存中紧密相连,无须为维持表中元素之间的前后关系而增加额外的存储空间(后面学习到链表时会看到增加额外存储空间来维持表中元素前后关系的情形)。
  • 插入和删除操作可能会移动大量元素导致这两个动作效率不高。
  • 需要大片连续的内存空间来存储数据。
  • 动态分配内存的方式实现的顺序表在扩展顺序表容量时扩展的空间大小不好确定,分配太多内存容易造成浪费,分配太少内存就会导致 new 和 delete 被频繁调用,影响程序执行效率。而且扩展顺序表容量操作的时间复杂度也比较高。

正如我们所见,顺序表要求内存中数据连续存储,这既带来了定位元素的便利,同时也拖慢了插入和删除元素的速度。

值得说明的是,对于多数需要使用顺序表的场合,直接使用标准模板库中的 vector 容器即可,其丰富的接口会给开发带来更多的便利。

如果是对于性能要求极其严苛的底层开发,而且通过测试确定了自己编写的代码执行效率比 vector 容器更高,也可以自行实现顺序表。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

掌握顺序表,成为数据结构和算法的高手 的相关文章

  • C语言练习之路--函数篇

    目录 一 前言二 选择题三 编程题1 乘法口诀表2 交换两个整数3 函数判断闰年4 函数判断素数5 递归实现n的k次方6 计算一个数的每位之和 xff08 递归实现 xff09 7 strlen的模拟 xff08 递归实现 xff09 8
  • 使用VOFA调试PID算法

    1 选用FireWater模式 这个模式下才支持多通道数据 2 代码编写 我使用的是cubemx和keil xff08 1 先在cubemx里把串口打开 我用的是401 xff08 2 打开我的Keil继续 span class token
  • 基于 JSP+Mysql 学生成绩查询web系统

    文章目录 一 学习任务二 学习内容1 准备工作1 1 相关软件1 2 源代码 2 连接MySQL3 idea配置4 运行结果5 web访问 三 参考博客 一 学习任务 首先在Mysql中创建相应的学生成绩表 xff0c 然后基于 JSP 4
  • jquery获取指定元素的指定属性的值

    使用jquery获取指定元素的指定属性的值 xff1a 选择器 attr 34 属性名 34 gt 用来获取那些值不是true false的属性的值 选择器 prop 34 属性名 34 gt 用来获取值是true false的属性的值 例
  • Maven3.6.1下载安装基本使用 (初识)(自用)

    对MAVEN的粗浅认识 Apache Maven 是 项目管理与构建工具 基于POM xff08 项目对象模型 xff09 的概念 作用 提供了一套标准化的项目结构 粗浅理解就是 xff0c 通常eclipse xff0c idea等jav
  • VSCode代码格式化快捷键

    我们在编写代码和阅读别人代码的时候 xff0c 容易出现同级元素缩进没有对齐的情况 xff0c 我们需对代码进行格式化 xff0c 以方便自己和他人的阅读 在vscode中使用快捷键 Shift 43 Alt 43 F 使用示例 xff1a
  • for循环【C++】

    for循环 执行一个特定循环的控制结构 for 条件 条件判断 条件处理 执行体 xff1b 条件 条件判断和条件处理都不是必要的 xff0c 当三者都没有 xff0c 则相当于一个无限循环 条件不一定需要在括号内声明和初始化 xff0c
  • 基于深度强化学习的智能船舶航迹跟踪控制

    基于深度强化学习的智能船舶航迹跟踪控制 人工智能技术与咨询 昨天 本文来自 中国舰船研究 xff0c 作者祝亢等 关注微信公众号 xff1a 人工智能技术与咨询 了解更多咨询 xff01 0 引 言 目前 xff0c 国内外对运载工具的研究
  • 面向区块链的高效物化视图维护和可信查询

    面向区块链的高效物化视图维护和可信查询 人工智能技术与咨询 来源 xff1a 软件学报 xff0c 作者蔡 磊等 摘 要 区块链具有去中心化 不可篡改和可追溯等特性 可应用于金融 物流等诸多行业 由于所有交易数据按照交易时间顺序存储在各个区
  • 基于深度学习的磁环表面缺陷检测算法

    基于深度学习的磁环表面缺陷检测算法 人工智能技术与咨询 来源 xff1a 人工智能与机器人研究 xff0c 作者罗菁等 关键词 缺陷检测 xff1b 深度学习 xff1b 磁环 xff1b YOLOv3 xff1b 摘要 在磁环的生产制造过
  • 基于PX4的地面无人车避障系统及路径规划研究

    基于PX4的地面无人车避障系统及路径规划研究 人工智能技术与咨询 来源 xff1a 动力系统与控制 xff0c 作者姜琼阁等 关键词 地面无人车 xff1b 避障 xff1b PX4 xff1b 摘要 地面无人车避障及路径规划是指 xff0
  • 基于图像的数据增强方法发展现状综述

    基于图像的数据增强方法发展现状综述 人工智能技术与咨询 2022 03 22 20 57 点击蓝字 关注我们 来源 xff1a 计算机科学与应用 xff0c 作者冯晓硕等 关键词 数据增强 xff1b 图像数据集 xff1b 图像处理 xf
  • 基于改进SSD算法的小目标检测与应用

    人工智能技术与咨询 点击蓝字 关注我们 来源 xff1a 计算机科学与应用 xff0c 作者刘洋等 关键词 SSD xff1b 深度学习 xff1b 小目标检测 摘要 xff1a 摘要 针对通用目标检测方法在复杂环境下检测小目标时效果不佳
  • Excel线性回归分析

    文章目录 一 学习任务二 学习内容1 1 高尔顿数据集进行线性回归分析1 1 1 父母身高平均值和其中一个子女身高进行回归分析1 1 2 父子身高回归方程1 1 3 母子身高回归方程 1 2 Anscombe四重奏数据集进行回归分析 一 学
  • 组网雷达融合处理组件化设计与仿真

    人工智能技术与咨询 点击蓝色 关注我们 关键词 xff1a 组网雷达 点迹融合 航迹融合 组件化设计 仿真 摘要 数据融合处理是多雷达组网的核心 以典型防空雷达网为参考对象 xff0c 采用组件化设计方式 xff0c 将组网数据融合处理过程
  • 人工智能 知识图谱

    关于举办 2022年数字信息化培训项目系列 知识图谱Knowledge Graph构建与应用研修班线上课程的通知 各有关单位 一 培训目标 本次课程安排紧密结合理论与实践 xff0c 深入浅出 xff0c 循序渐进 从基本概念讲起 xff0
  • 深度学习(Deep Learning)

    知识关键点 1 人工智能 深度学习的发展历程 2 深度学习框架 3 神经网络训练方法 4 卷积神经网络 xff0c 卷积核 池化 通道 激活函数 5 循环神经网络 xff0c 长短时记忆 LSTM 门控循环单元 GRU 6 参数初始化方法
  • 基于深度学习的机器人目标识别和跟踪

    如今 xff0c 深度学习算法的发展越来越迅速 xff0c 并且在图像处理以及目标对象识别方面已经得到了较为显著的突破 xff0c 无论是对检测对象的类型判断 xff0c 亦或者对检测对象所处方位的检测 xff0c 深度学习算法都取得了远超
  • 零基础Linux版MySQL源码方式安装+配置+远程连接完整图解 无坑实录

    无论开发还是运维 xff0c 项目环境搞不定 xff0c 还真让你干不成活 xff0c MySQL在不同场景 不同平台下安装方式也不同 xff0c 本次主要分享centos7下MySQL源码rpm方式安装 xff0c 其它方式后续分享 xf

随机推荐

  • C++,友元,语法+示例,非常详细!!!!

    友元概念 友元的目的就是让一个函数或者类 访问另外一个类中的私有成员 友元的关键字为 friend 友元的几种实现 全局函数做 友元类做 友元成员函数做 友元重载函数做 友元 全局函数做 友元 include lt iostream gt
  • STL——STL简介、STL六大组件

    一 STL是什么 STL standard template library xff1a C 43 43 标准模板库 xff0c 是C 43 43 标准库的重要组成部分 xff0c 不仅是一个可复用的组件库 xff0c 还是一个包罗数据结构
  • 文件流指针和文件描述符

    1 文件流指针和文件描述符的产生 fopen函数打开文件成功后会返回文件流指针 open函数打开文件成功后返回的是文件描述符 他俩的相同点是通过文件流指针和文件描述符都可以对文件进行操作 2 fopen函数和open函数的介绍 fopen函
  • docker 操作

    查看容器 xff1a sudo docker ps a 删除容器 xff1a sudo docker rm NAMES 容器的名字 下载镜像 xff1a sudo docker pull rmus2022 server v1 2 0 查看镜
  • 树莓派32位系统烧录及连接

    目录 前言 一 烧录树莓派系统 1 格式化tf卡 2 烧录系统 二 连接树莓派 1 开启SSH 2 开启网络共享 3 下载Putty 三 开启图形化界面 非必须 最后 xff1a 前言 我在树莓派环境搭建的过程中 xff0c 看了几十篇博客
  • 鸢尾花Iris数据集进行SVM线性分类

    文章目录 一 学习任务二 学习内容1 鸢尾花数据集使用SVM线性分类1 1 SVM介绍1 2 LinearSVC xff08 C xff09 方式实现分类1 3 分类后的内容基础上添加上下边界 三 参考博客 一 学习任务 安装python3
  • intel realsense d435i相机标定中文文档

    intel realsense d435i相机标定中文文档 此文档参考了官方的英文文档 xff0c 原地址面向英特尔 实感 深度摄像头的 IMU 校准工具 intelrealsense com IMU概述 xff1a 惯性测量单元 imu
  • VScode-git提交 无法推送refs到远端

    在将代码同步到远端仓库时 xff0c 弹窗提醒 无法推送refs到远端 您可以试着运行 拉取 功能 xff0c 整合您的更改 但尝试后发现 拉取 功能也无法解决问题 xff0c 最后是因为文件过大原因 xff0c 在这里记录一下解决方法 x
  • VMware16虚拟机中安装OpenEuler详细教程指南

    文章目录 安装前提准备镜像创建虚拟机安装欧拉踩坑指南 x1f351 网络指南 安装前提 Windown 10VMware 16openEuler 20 03 LTS SP3 准备镜像 镜像地址 xff1a OpenEuler 直接在官网下载
  • C/C++排序算法(三)—— 冒泡排序和快速排序

    文章目录 前言1 冒泡排序 x1f351 基本思想 x1f351 图解冒泡 x1f351 动图演示 x1f351 代码实现 x1f351 代码优化 x1f351 特性总结 2 快速排序 x1f351 hoare 版本 x1f345 图解过程
  • C/C++排序算法(四)—— 归并排序和计数排序

    文章目录 前言1 归并排序 x1f351 基本思想 x1f351 算法图解 x1f345 分组 x1f345 归并 x1f345 比较 x1f351 动图演示 x1f351 代码实现 x1f351 非递归实现 x1f345 情况一 x1f3
  • C++深入浅出(九)—— 多态

    文章目录 1 多态的概念2 多态的定义及实现 x1f351 多态的构成条件 x1f351 虚函数 x1f351 虚函数的重写 x1f351 虚函数重写的两个例外 x1f351 C 43 43 11的override 和 final x1f3
  • C++STL剖析(八)—— unordered_set和unordered_multiset的概念和使用

    文章目录 前言1 unordered set的介绍和使用 x1f351 unordered set的构造 x1f351 unordered set的使用 x1f345 insert x1f345 find x1f345 erase x1f3
  • C++STL剖析(九)—— unordered_map和unordered_multimap的概念和使用

    文章目录 1 unordered map的介绍和使用 x1f351 unordered map的构造 x1f351 unordered map的使用 x1f345 insert x1f345 operator x1f345 find x1f
  • C++STL剖析(十)—— 位图(bitset)

    文章目录 1 位图的介绍2 位图的概念3 位图的实现 x1f351 构造函数 x1f351 设置指定位 x1f351 清除指定位 x1f351 获取指定位的状态 x1f351 打印函数 4 总结 1 位图的介绍 在介绍位图之前先来看一道面试
  • C/C++数据结构(十二)—— 红黑树

    文章目录 1 红黑树的概念2 红黑树的性质3 红黑树节点的定义4 红黑树的旋转5 红黑树的插入 x1f351 情况一 x1f351 情况二 x1f351 情况三 x1f345 叔叔结点存在且为红色 x1f345 叔叔结点存在且为黑色 x1f
  • 机器学习数学基础

    文章目录 一 学习任务二 学习内容1 梯度下降法的一般求解步骤2 梯度下降法手工求解极值2 1 计算过程 3 Excel中利用梯度下降求解近似根4 线性回归问题求解4 1 最小二乘法4 2 梯度下降法 三 参考资料 一 学习任务 解释微分
  • 一篇文章吃透算法时间复杂度

    文章目录 前言1 什么是好的算法2 算法的效率度量3 时间复杂度4 大 O 时间复杂度表示法5 算法时间复杂度计算规则 x1f351 规则 1 xff1a 只关注循环中的代码段 x1f351 规则 2 xff1a 加法规则 x1f351 规
  • 2023 年最佳 C++ IDE

    文章目录 前言1 Visual Studio2 Code Blocks3 CLion4 Eclipse CDT xff08 C C 43 43 开发工具 xff09 5 CodeLite6 Apache NetBeans7 Qt Creat
  • 掌握顺序表,成为数据结构和算法的高手

    文章目录 1 线性结构与线性表2 线性表的顺序存储3 顺序表的基础操作 x1f351 顺序表接口总览 x1f351 初始化顺序表 x1f351 销毁链表 x1f351 插入操作 x1f351 删除操作 x1f351 获取元素操作 x1f34