8.1 C++ STL 变易拷贝算法
C++ STL中的变易算法(Modifying Algorithms)是指那些能够修改容器内容的算法,主要用于修改容器中的数据,例如插入、删除、替换等操作。这些算法同样定义在头文件 <algorithm>
中,它们允许在容器之间进行元素的复制、拷贝、移动等操作,从而可以方便地对容器进行修改和重组。
主要包括以下几类变易算法:
- 复制算法:
copy()
:将一个容器的元素复制到另一个容器中。copy_if()
:根据给定的条件(函数对象或谓词)复制满足条件的元素到另一个容器中。copy_n()
:从指定位置开始,复制指定个数的元素到另一个容器中。copy_backward()
:将一个容器的元素复制到另一个容器中,并保持原有的顺序。
- 拷贝算法:
fill()
:用指定值替换容器中的所有元素。fill_n()
:用指定值替换容器中从指定位置开始的一定数量的元素。generate()
:根据给定的生成函数,替换容器中的所有元素。generate_n()
:根据给定的生成函数,替换容器中从指定位置开始的一定数量的元素。
- 移动算法:
move()
:将一个容器中的元素移动到另一个容器中,通常用于移动语义的场景。
这些变易算法允许我们在不创建新容器的情况下,对现有容器进行元素的复制、拷贝和重排。使用这些算法可以实现高效的数据操作,节省了内存开销和不必要的数据拷贝。同时,这些算法也是C++ STL中非常有用和常用的功能,为C++开发者提供了强大的工具来操作和修改容器中的元素。
8.1 元素复制算法
Copy 算法函数,用于将一个源序列的内容复制到另一个目标序列中。copy函数的用法如下:
template<class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result);
其中,first、last
是迭代器,表示源序列的范围;result
是迭代器,表示目标序列的起始位置。调用copy
函数后,将会将[first, last]
区间内的元素复制到从result
开始的目标序列中,并返回指向目标序列最后一个复制元素之后的位置的迭代器。
需要注意的是,copy函数只能复制对象,不能使用于复制C字符串(包括char*和char[])
等字符数组。对于字符数组,可以使用strcpy
函数进行复制。另外,如果源序列区间和目标序列区间有重叠部分,需要使用copy_backward
函数。
如下案例中,实现容器之间元素的拷贝复制操作,将两个迭代器进行互相拷贝。
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;void MyPrint(int x) { cout << x << " "; }int main(int argc, char* argv[])
{vector<int> var1 = { 1,3,5,7,9 };vector<int> var2 = { 2,4,6,8,10 };// 复制var1到var2 此时var2中的内容将被覆盖copy(var1.begin(), var1.end(), var2.begin());// var1 -> 覆盖到 --> var2for_each(var2.begin(), var2.end(), MyPrint);cout << endl;// 复制var1中的前3个元素,并输出copy_backward(var1.begin(), var1.begin() + 2, var1.end());for_each(var1.begin(), var1.end(), MyPrint);system("pause");return 0;
}
8.2 元素交换算法
Swap 算法函数,用于交换两个对象或是两个结构的值。swap函数的用法如下:
template <class T>
void swap (T& a, T& b);
其中,a、b
是要交换值的两个对象。
swap函数使用时需要注意,swap并不像第一眼看到的那样简单粗暴地直接交换值,它实际上是通过移动指针进行的值交换,因此对于大规模的对象交换,使用swap
会比暴力直接交换值更加高效。同时,swap函数还保证了异常安全性,即在对象交换时如果发生了异常,swap函数会确保原始状态恢复,不会产生未定义行为。
在C++11中,类也可以自定义swap
成员函数,当使用了自定义的swap函数时,调用std::swap
函数将使用类内定义的swap函数进行值交换。一般而言,自定义swap函数应该优先使用std::swap
进行值交换,从而可以借助std::swap
的优势提高交换效率。
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;void MyPrint(int x) { cout << x << " "; }int main(int argc, char* argv[])
{vector<int> var1 = { 1,3,5,7,9 };vector<int> var2 = { 2,4,6,8,10 };// 两个容器之间数值互换swap(var1, var2);for_each(var1.begin(), var1.end(), MyPrint);// 通过迭代的方式实现数值互换iter_swap(&var1, &var2);for_each(var2.begin(), var2.end(), MyPrint);// 区间选择交换swap_ranges(var1.begin(), var1.end(), var2.begin());for_each(var2.begin(), var2.end(), MyPrint);system("pause");return 0;
}
8.3 元素搬运算法
Transform 算法函数,用于将给定源序列中的元素按照指定规则进行变换,并将结果存放到目标序列中。transform函数的用法如下:
template<class InputIterator, class OutputIterator, class UnaryOperation>
OutputIterator transform(InputIterator first1, InputIterator last1, OutputIterator result, UnaryOperation op);
其中,first1、last1
是迭代器,表示源序列的范围;result
是迭代器,表示目标序列的起始位置;op是一个一元函数对象,用于对源序列中的元素进行变换。调用transform
函数后,将会对[first1, last1]
区间内的每个元素执行一次op操作,并将结果存放到对应的result
位置。
但读者需要注意,transform函数会根据op的返回值类型确定目标序列的元素类型,并自动调用构造函数生成目标序列中的元素。因此,如果op返回的类型是一个自定义的类型,需要确保该类型具有默认构造函数和赋值运算符函数。另外,如果源序列与目标序列重叠,需要使用另一种重载的transform函数来保证正确性。
transform函数的使用场景十分广泛,可以用于对任意类型的序列进行任意类型的变换,例如将数组中的每个元素加1,将vector中的每个字符串转换为大写形式等等。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;void MyPrint(int x) { cout << x << " "; }class TransForm
{// 在搬运的过程中每次+10写入到vTarget;
public: int operator()(int val){ return val + 10;}
};
class New_TransForm
{// 使用仿函数,将两个数组中的值相加
public: int operator()(int val1, int val2){return val1 + val2;}
};int main(int argc, char* argv[])
{vector<int> var = { 1,2,3,4,5 }; // 原容器vector<int > vTarget; // 目标容器// 第一种形式:将var中的数据每次+10后搬运到vTarget中vTarget.resize(5); // transform 不会自动开辟内存,需要我们手动开辟transform(var.begin(), var.end(), vTarget.begin(), TransForm());// 循环输出 此处的 [](int val){cout << val << " "; 其实是 MyPrint 不过是匿名了for_each(vTarget.begin(), vTarget.end(), [](int val){cout << val << " "; });cout << endl;// 第二种形式:将var1,var2两个容器中的值相加,相加后搬运到new_vTarget容器中vector<int> var1 = { 1, 2, 3, 4, 5 }; // 原容器vector<int> var2 = { 6, 7, 8, 9, 10 }; // 原容器vector<int> new_vTarget; // 目标容器new_vTarget.resize(5);transform(var1.begin(), var1.end(), var2.begin(), new_vTarget.begin(), New_TransForm());for_each(new_vTarget.begin(), new_vTarget.end(), MyPrint);system("pause");return 0;
}
8.4 元素替换算法
Replace 算法函数,用于将给定序列中的所有等于给定值的元素替换为指定的新值。replace函数的用法如下:
template <class ForwardIterator, class T>
void replace (ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value);
其中,first、last
是迭代器,表示待替换的序列的范围;old_value
表示要被替换的值;new_value
表示替换后的新值。调用replace
函数后,会将[first, last]
区间内所有等于old_value
的元素全部替换为new_value
。
但读者需要注意,replace函数只能替换对象,不能复制对象。例如,replace函数无法用来替换字符串或其他类似C风格字符串或STL字符串的对象。如果需要替换字符串或其他复杂对象,可以考虑使用其他函数,例如字符串的replace成员函数。另外,replace函数只能对相等的元素进行替换,无法按照某种规律进行替换。如果需要按照某种规律替换序列,可以考虑使用replace_if函数。
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;void MyPrint(int x) { cout << x << " "; }
class MyCompart
{
public: bool operator()(int val){// 将大于5的数据替换return val > 5;}
};int main(int argc, char* argv[])
{vector<int> var = { 1,2,3,4,4,5,5,6,7,8,8,9,0,2,1,0 };// 全部替换: 将var中的4全部替换为4000replace(var.begin(), var.end(), 4, 4000); for_each(var.begin(), var.end(), MyPrint);// 条件替换:将所有的大于5的数替换为0replace_if(var.begin(), var.end(), MyCompart(), 0);for_each(var.begin(), var.end(), MyPrint);system("pause");return 0;
}
8.5 容器初始化算法
Fill 算法函数,用于将给定序列中的所有元素全部填充为指定的值。fill函数的用法如下:
template <class ForwardIterator, class T>
void fill (ForwardIterator first, ForwardIterator last, const T& val);
其中,first、last
是迭代器,表示待填充的序列的范围;val
表示要填充的值。调用fill
函数后,会将[first, last]
区间内的所有元素全部填充为val
。
需要注意的是,fill
函数只能填充对象,不能复制对象。例如,fill
函数无法用来填充字符串或其他类似C风格字符串或STL字符串的对象。如果需要填充字符串或其他复杂对象,可以考虑使用其他函数,例如memset
函数对于字符串数组的初始化。还需要注意的是,fill函数只能等量复制相同的值,无法按照某种规律变化,如果需要按照某种规律填充序列,可以使用generate
函数。
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;void MyPrint(int x) { cout << x << " "; }int main(int argc, char* argv[])
{vector<int> var = { 1,2,3,4,4,5,5,6,7,8,8,9,0,2,1,0 };// 将前3个元素填充为0fill_n(var.begin(), 3, 0);for_each(var.begin(), var.end(), MyPrint);// 全部填充为0fill_n(var.begin(), var.size(), 0);for_each(var.begin(), var.end(), MyPrint);// 全部填充为10fill(var.begin(), var.end(), 10);for_each(var.begin(), var.end(), MyPrint);system("pause");return 0;
}
8.6 普通条件移除
Remove_if 算法函数,用于从给定序列中删除满足某个条件的元素。remove_if函数的用法如下:
template <class ForwardIterator, class UnaryPredicate>
ForwardIterator remove_if (ForwardIterator first, ForwardIterator last, UnaryPredicate pred);
其中,first、last
是迭代器,表示要进行操作的序列的范围;pred
是一个一元谓词函数,用于指定需要删除的元素。调用remove_if
函数后,将会删除[first, last]
区间内满足pred
条件的元素,并将其移到区间尾部,返回指向第一个被移动元素位置的迭代器。
remove_if函数并不会真正地删除被移动的元素,而是将它们移动到区间尾部,所以最终在[first, last]
区间剩下的元素是不确定的。如果想要真正地删除被移动的元素,可以再调用容器类的erase
函数删除尾部的元素。需要注意的是,erase
函数只能对带有erase成员函数(例如vector、list)的容器使用,对于没有erase
成员函数的容器(例如数组),需要手动调整数组的长度。
如下是一个使用案例,代码中实现了将容器中不等于某个值的元素移除出容器,代码如下所示;
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;void MyPrint(int x) { cout << x << " "; }
bool even(int val) { return val % 2 ? 0 : 1; }int main(int argc, char* argv[])
{vector<int> var { 4,3,4,8,9,5,6,7,8,9,2,1,4 };// 移除var里面的所有的4vector<int>::iterator result;result = remove(var.begin(), var.end(), 4);for_each(var.begin(), var.end(), MyPrint);cout << endl;// 移除var里面所有的偶数vector<int>::iterator result1;result1 = remove_if(var.begin(), var.end(), even);for_each(var.begin(), var.end(), MyPrint);system("pause");return 0;
}
8.7 条件移除复制
Remove_copy 算法函数,用于将满足某个条件的元素从一个源序列复制到目标序列中,同时去除不满足条件的元素。remove_copy函数的用法如下:
template <class InputIterator, class OutputIterator, class T>
OutputIterator remove_copy (InputIterator first, InputIterator last, OutputIterator result, const T& value);
其中,first、last
是迭代器,表示要进行操作的源序列的范围;result
是迭代器,表示复制后的目标序列起始位置;value
是需要去除的元素的值。调用remove_copy
函数后,将会将原序列[first, last]
中不等于value
的元素复制到目标序列[result, result + (last - first))
中,并返回目标序列最后一个复制元素的后继位置的迭代器。需要注意的是,remove_copy
函数并不会真正地将值为value
的元素从原序列中移除,而是将它们留在原序列中,因此返回的目标序列只包含不等于value
的元素。
remove_copy函数的使用场景通常是,需要在不破坏原序列的情况下,复制其中一些元素到目标序列中,并去除一些元素。如下案例中所示,算法实现了将原容器中不等于某个给定值的元素复制到新容器中。
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;void MyPrint(int x) { cout << x << " "; }bool even(int val){ return val % 2 ? 0 : 1; }int main(int argc, char* argv[])
{vector<int> var { 4,3,4,8,9,5 };int iarray[6] = { 0, 0, 0, 0, 0, 0, };// 移除复制,将var中的数据的前4个数据复制到iarray中,var中数据保持不变remove_copy(var.begin(), var.end(), iarray, 4);for_each(iarray, iarray+6, MyPrint);cout << endl;// 移除var中的偶数,剩余元素复制到iarray中remove_copy_if(var.begin(), var.end(), iarray, even);for_each(iarray, iarray + 6, MyPrint);system("pause");return 0;
}
8.8 容器元素去重算法
Unique 算法函数,用于删除给定序列中相邻的重复元素,只保留一个副本。unique函数的用法如下:
template <class ForwardIterator>
ForwardIterator unique (ForwardIterator first, ForwardIterator last);
其中,first、last
是迭代器,表示要进行去重的序列的范围。调用unique
函数后,将会去除[first, last]
区间内相邻的重复元素,仅保留第一个元素,其余相同的元素都将被删除,剩下的元素会被移动到前面,返回指向最后一个未被删除元素之后的迭代器,通常与erase
函数一起使用以删除多余的元素。
unique函数只删除相邻的重复元素,不删除中间隔着其他元素的重复元素,例如序列[a, b, b, c, b, d, d]
经过unique
去重后会变为[a, b, c, b, d]
,注意不会删除序列中间的b,因为它并不相邻。还需要注意的是,unique只对相邻元素进行去重,如果需要对无序序列进行去重,可以先对序列进行排序,然后再调用unique函数。
如下笔者提供两个案例,案例中函数unique_copy
实现邻近元素去重,函数unique
去除连续重复元素,如下所示;
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;void MyPrint(int x) { cout << x << " "; }int main(int argc, char* argv[])
{vector<int> var { 2,5,5,5,5,5,6,7,5,9,5};int iarray[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };// 实现邻近元素去重,只能去除相邻元素中重复的unique_copy(var.begin(), var.end(), iarray);for_each(iarray, iarray + 10, MyPrint);cout << endl;// 另一种邻近元素去重算法vector<int>::iterator result;result = unique(var.begin(), var.end());for_each(var.begin(),result,MyPrint);system("pause");return 0;
}
8.9 元素反向拷贝算法
Reverse 算法函数,用于将给定序列中的元素翻转,即将元素按逆序排列。reverse函数的用法如下:
template <class BidirectionalIterator>
void reverse (BidirectionalIterator first, BidirectionalIterator last);
其中,first、last
是迭代器,表示要进行翻转的序列的范围。调用reverse
函数后,将会把[first, last]
中的元素按相对位置逆序排列,即对于[first, last]
中的任意两个迭代器i、j
,若 i小于j,则翻转后的序列中,i对应的元素会出现在j之后。
读者需要注意,reverse函数不会改变序列中各个元素的值,只会改变它们的位置,因此是一个非变易算法。与rotate
函数类似,reverse
函数一般只用于BidirectionalIterator
迭代器类型的序列,即支持双向遍历的序列(例如双向链表),而不支持随机访问的序列(例如单向链表)。
简单总结来说,该算法实现了对容器中元素的反向排列,和反向复制容器中的数据,这个复制案例如下所示;
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;void MyPrint(int x) { cout << x << " "; }int main(int argc, char* argv[])
{vector<int> var { 1,2,3,4,5,6,7,8,9,10 };// 将元素反向排列后输出reverse(var.begin(), var.end());for_each(var.begin(), var.end(), MyPrint);cout << endl;// 将元素反向复制到iarray数组中存储int iarray[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };reverse_copy(var.begin(), var.end(), iarray);for_each(iarray,iarray+10, MyPrint);system("pause");return 0;
}
8.10 容器旋转复制算法
Rotate是的一个算法函数,用于将给定序列中的元素向左循环移动若干个位移,即将序列中前面的元素移动到末尾,其最终的位置与原来位置的距离是一个定值。rotate函数的用法如下:
template <class ForwardIterator>
void rotate (ForwardIterator first, ForwardIterator middle, ForwardIterator last);
其中,first、middle、last
是迭代器,表示要进行循环移动的序列的范围。调用rotate函数后,将会将序列[first, last]
中的元素向左循环移动,使得中间区间[middle, last)
的元素移动到前面,前面的区间[first, middle)
的元素移动到后面,即做如下变换:
[ a b c d e f g ] -> [ d e f g a b c ]↑ ↑middle first
但读者需要注意,rotate
函数不会改变序列中各个元素的值,只会改变它们的位置。另外,若中间区间[middle, last)
为空,则整个序列不会发生变化;若其包含所有元素,则rotate
等效于reverse
函数。由于此函数的核心功能是反转数组,所以在使用时需要自行指定一个中心数。
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;void MyPrint(int x) { cout << x << " "; }int main(int argc, char* argv[])
{vector<int> var { 1,2,3,4,5,6,7,8,9,10 };for_each(var.begin(), var.end(), MyPrint);// 以元素6为中心,将两边数据旋转后输出cout << "middle => " << *(var.begin() + 5) << endl;rotate(var.begin(), var.begin() + 5, var.end());for_each(var.begin(), var.end(), MyPrint);cout << endl;// 旋转后复制到iarray数组中存储int iarray[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };rotate_copy(var.begin(), var.begin() + 5, var.end(), iarray);for_each(iarray,iarray+10, MyPrint);system("pause");return 0;
}
8.11 随机数相关算法
Random 是C++11
引入的标准库函数,用于生成随机数。该函数库提供了多个随机数引擎和分布函数,可以用于产生各种类型的随机数,例如在给定范围内生成整数或浮点数、生成布尔值等。以下是random
库中的一些常用函数:
- std::mt19937:是一种随机数引擎,使用梅森旋转算法产生高质量的伪随机数。
- std::uniform_int_distribution:用于生成随机的整数分布,可以指定整数范围。
- std::uniform_real_distribution:用于生成随机的浮点数分布,可以指定实数范围。
- std::normal_distribution:用于生成随机的标准正态分布或自定义正态分布。
- std::bernoulli_distribution:用于模拟一个伯努利分布,即二项分布的情况,可以生成布尔值。
使用random
库时,通常先创建一个随机数引擎实例,然后再创建一个特定的分布函数实例,最后利用分布函数实例的调用运算符()
来产生随机数。例如:
std::mt19937 gen{std::random_device{}()};
std::uniform_int_distribution<int> dist{1, 10};
int x = dist(gen); // 在1到10之间生成一个均匀分布的整数
如下案例中实现了简单的生成随机数,以及对随机数进行初始化,其代码中的算法generate_n
用于生成随机数,而random_shuffle
算法则用于打乱数组。
#include <iostream>
#include <vector>
#include <ctime>
#include <algorithm>
using namespace std;void MyPrint(int x) { cout << x << " "; }int main(int argc, char* argv[])
{// 增加此方法,每次都可以随机打乱srand((unsigned int)time(NULL));vector<int> var(10);// 生成随机数:生成5个随机数,并存入vargenerate_n(var.begin(), 5, rand);for_each(var.begin(), var.end(), MyPrint);cout << endl;// 随机抖动: 随机的打乱一个数组int iarray[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };random_shuffle(iarray, iarray + 10);for_each(iarray, iarray + 10, MyPrint);system("pause");return 0;
}
8.12 容器元素分割算法
Partition 算法函数,用于将给定序列中的元素根据某个条件分为两组,使得满足条件的元素全部在一组,不满足条件的元素在另一组,最终返回第一个不满足条件的元素的位置。具体流程是,首先在序列中选定一个元素作为分界点,然后将序列中的其他元素依次与分界点比较,如果满足条件则移动到左边,否则移动到右边,最终左边的所有元素都满足条件,右边的所有元素都不满足条件。partition函数的用法如下:
template <class ForwardIterator, class UnaryPredicate>
ForwardIterator partition (ForwardIterator first, ForwardIterator last, UnaryPredicate pred);
其中,first
和last
是一个前闭后开区间,表示待分割的序列的范围;pred
是一个一元谓词函数,用于指定元素满足的条件。函数执行完毕后,返回指向第一个不满足条件的元素的迭代器。
该算法用于重新分割排列容器的元素,第一种无序分割,第二种为有序分割,如下代码是该函数的具体使用案例。
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;void MyPrint(int x) { cout << x << " "; }// 判断是否小于10
bool Less(int y){ return y < 10 ? 1 : 0; }int main(int argc, char* argv[])
{int iarray[10] = { 12,45,2,6,8,-5,-12,-78,-4,3 };// 按照小于10对容器进行分割int * result = partition(iarray, iarray + 10, Less);// 输出小于10的元素for_each(iarray, result , MyPrint);cout << endl;// 按照小于10对容器分割,但保持原来的次序int * new_ret = stable_partition(iarray, iarray + 10, Less);for_each(iarray, iarray + 10, MyPrint);cout << " --> 分界元素 Mid:" << *new_ret << endl;system("pause");return 0;
}
本文作者: 王瑞
本文链接: https://www.lyshark.com/post/83787397.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章:

8.1 C++ STL 变易拷贝算法
C STL中的变易算法(Modifying Algorithms)是指那些能够修改容器内容的算法,主要用于修改容器中的数据,例如插入、删除、替换等操作。这些算法同样定义在头文件 <algorithm> 中,它们允许在容器之间进行元素的复制…...

攻击LNMP架构Web应用
环境配置(centos7) 1.php56 php56-fpm //配置epel yum install epel-release rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm//安装php56,php56-fpm及其依赖 yum --enablereporemi install php56-php yum --enablereporemi install php…...

深度学习入门-3-计算机视觉-图像分类
1.概述 图像分类是根据图像的语义信息对不同类别图像进行区分,是计算机视觉的核心,是物体检测、图像分割、物体跟踪、行为分析、人脸识别等其他高层次视觉任务的基础。图像分类在许多领域都有着广泛的应用,如:安防领域的人脸识别…...

shopee运营新手入门教程!Shopee运营技巧!
随着跨境电商行业的蓬勃发展,越来越多的人开始关注Shopee这个平台。短视频等渠道也成为了人们了解Shopee的途径。因此,对于许多新手来说,在Shopee上开店成为了一种吸引人的选择。为了帮助这些新手更好地入门,下面将介绍一下Shop…...

Python Web框架:Django、Flask和FastAPI巅峰对决
今天,我们将深入探讨Python Web框架的三巨头:Django、Flask和FastAPI。无论你是Python小白还是老司机,本文都会为你解惑,带你领略这三者的魅力。废话不多说,让我们开始这场终极对比! Django:百…...

机器学习线性代数基础
本文是斯坦福大学CS 229机器学习课程的基础材料,原始文件下载 原文作者:Zico Kolter,修改:Chuong Do, Tengyu Ma 翻译:黄海广 备注:请关注github的更新,线性代数和概率论已经更新完毕…...

PyQt5组件之QLabel显示图像和视频
目录 一、显示图像和视频 1、显示图像 2、显示视频 二、QtDesigner 窗口简单介绍 三、相关函数 1、打开本地图片 2、保存图片到本地 3、打开文件夹 4、打开本地文本文件并显示 5、保存文本到本地 6、关联函数 7、图片 “.png” | “.jpn” Label 自适应显示 8、Q…...

微信程序 自定义遮罩层遮不住底部tabbar解决
一、先上效果 二 方法 1、自定义底部tabbar 实现: https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html 官网去抄 简单写下:在代码根目录下添加入口文件 除了js 文件的list 需要调整 其他原封不动 代码…...

Python简易部署方法
一.安装Python解释器和vscode或者其他开发工具 下载地址: 1.下载vscode 链接: https://code.visualstudio.com/. 2.下载python解释器 链接: https://www.python.org/downloads/. 二.安装包 打开cmd,输入命令:pip install 包名 三.配置…...

Spring Boot单元测试与Mybatis单表增删改查
目录 1. Spring Boot单元测试 1.1 什么是单元测试? 1.2 单元测试有哪些好处? 1.3 Spring Boot 单元测试使用 单元测试的实现步骤 1. 生成单元测试类 2. 添加单元测试代码 简单的断言说明 2. Mybatis 单表增删改查 2.1 单表查询 2.2 参数占位符 ${} 和 #{} ${} 和 …...

机器学习样本数据划分的典型Python方法
机器学习样本数据划分的典型Python方法 DateAuthorVersionNote2023.08.16Dog TaoV1.0完成文档撰写。 文章目录 机器学习样本数据划分的典型Python方法样本数据的分类Training DataValidation DataTest Data numpy.ndarray类型数据直接划分交叉验证基于KFold基于RepeatedKFold基…...

重建与突破,探讨全链游戏的现在与未来
全链游戏(On-Chain Game)是指将游戏内资产通过虚拟货币或 NFT 形式记录上链的游戏类型。除此以外,游戏的状态存储、计算与执行等皆被部署在链上,目的是为用户打造沉浸式、全方位的游戏体验,超越传统游戏玩家被动控制的…...

[C++] 模板template
目录 1、函数模板 1.1 函数模板概念 1.2 函数模板格式 1.3 函数模板的原理 1.4 函数模板的实例化 1.4.1 隐式实例化 1.4.2 显式实例化 1.5 模板参数的匹配原则 2、类模板 2.1 类模板的定义格式 2.2 类模板的实例化 讲模板之前呢,我们先来谈谈泛型编程&am…...

[vite] 项目打包后页面空白,配置了base后也不生效
记录下解决问题的过程和思路 首先打开看打包后的 dist/index.html 文件,和页面上的报错 这里就发现了第一个问题 报错的意思是 index.html中引用的 css文件 和 js文件 找不到 为了解决这个问题,在vite.config.js配置中,增加一项 base:./ …...

springboot整合kafka-笔记
springboot整合kafka-笔记 配置pom.xml 这里我的springboot版本是2.3.8.RELEASE,使用的kafka-mq的版本是2.12 <dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>s…...

Rust软件外包开发语言的特点
Rust 是一种系统级编程语言,强调性能、安全性和并发性的编程语言,适用于广泛的应用领域,特别是那些需要高度可靠性和高性能的场景。下面和大家分享 Rust 语言的一些主要特点以及适用的场合,希望对大家有所帮助。北京木奇移动技术有…...

Spring Boot业务代码中使用@Transactional事务失效踩坑点总结
1.概述 接着之前我们对Spring AOP以及基于AOP实现事务控制的上文,今天我们来看看平时在项目业务开发中使用声明式事务Transactional的失效场景,并分析其失效原因,从而帮助开发人员尽量避免踩坑。 我们知道 Spring 声明式事务功能提供了极其…...

知识体系总结(九)设计原则、设计模式、分布式、高性能、高可用
文章目录 架构设计为什么要进行技术框架的设计 六大设计原则一、单一职责原则二、开闭原则三、依赖倒置原则四、接口分离原则五、迪米特法则(又称最小知道原则)六、里氏替换原则案例诠释 常见设计模式构造型单例模式工厂模式简单工厂工厂方法 生成器模式…...

Springboot 集成Beetl模板
一、在启动类下的pom.xml中导入依赖: <!--beetl模板引擎--><dependency><groupId>com.ibeetl</groupId><artifactId>beetl</artifactId><version>2.9.8</version></dependency> 二、 配置 beetl需要的Beetl…...

RabbitMQ查询队列使用情况和消费者详情实现
spring-boot-starter-amqp spring-boot-starter-amqp是Spring Boot框架中与AMQP(高级消息队列协议)相关的自动配置启动器。它提供了使用AMQP进行消息传递和异步通信的功能。 以下是spring-boot-starter-amqp的主要特性和功能: 自动配置:spring-boot-starter-amqp通过自动…...

Spark第二课RDD的详解
1.前言 RDD JAVA中的IO 1.小知识点穿插 1. 装饰者设计模式 装饰者设计模式:本身功能不变,扩展功能. 举例: 数据流的读取 一层一层的包装,进而将功能进行进一步的扩展 2.sleep和wait的区别 本质区别是字体不一样,sleep斜体,wait正常 斜体是静态方法…...

人工智能学习框架—飞桨Paddle人工智能
1.人工智能框架 机器学习的三要素:模型、学习策略、优化算法。 当我们用机器学习来解决一些模式识别任务时,一般的流程包含以下几个步骤: 1.1.浅层学习和深度学习 浅层学习(Shallow Learning):不涉及特征学习,其特征…...

SElinux 导致 Keepalived 检测脚本无法执行
哈喽大家好,我是咸鱼 今天我们来看一个关于 Keepalived 检测脚本无法执行的问题 一位粉丝后台私信我,说他部署的 keepalived 集群 vrrp_script 模块中的脚本执行失败了,但是手动执行这个脚本却没有任何问题 这个问题也是咸鱼第一次遇到&…...

2022年电赛C题——小车跟随行驶系统——做题记录以及经验分享
前言 自己打算将做过的电赛真题,主要包含控制组的,近几年出现的小车控制题目,自己做过的真题以及在准备电赛期间刷真题出现的问题以及经验分享给大家 这次带来的是22年电赛C题——小车跟随行驶系统,这道题目指定使用的是TI的单片…...

vscode + python
序 参考链接: 【教程】VScode中配置Python运行环境_哔哩哔哩_bilibili Python部分 Python Releases for Windows | Python.org vscode部分 Visual Studio Code - Code Editing. Redefined 一路next,全部勾上: 就可以了: 安装插…...

badgerdb里面的事务
事务的ACID A 原子性(Atomicity) 多步骤操作,只能是两种状态,要么所有的步骤都成功执行,要么所有的步骤都不执行,举例说明就是小明向小红转账30元的场景,拆分成两个步骤,步骤1&#…...

C# this.Invoke(new Action(() => { /* some code */ }))用法说明
在 C# 中,this.Invoke(new Action(() > { /* some code */ })) 是一种用于在 UI 线程上执行代码的方法,通常用于在后台线程中更新 UI 控件的值或执行其他需要在 UI 线程上执行的操作。 在 Windows Forms 或 WPF 等图形界面应用程序中,UI …...

MongoDB:MySQL,Redis,ES,MongoDB的应用场景
简单明了说明MySQL,ES,MongoDB的各自特点,应用场景,以及MongoDB如何使用的第一章节. 一. SQL与NoSQL SQL被称为结构化查询语言.是传统意义上的数据库,数据之间存在很明确的关联关系,例如主外键关联,这种结构可以确保数据的完整性(数据没有缺失并且正确).但是正因为这种严密的结…...

leetcode每日一题_2682.找出转圈游戏输家
2682.找出转圈游戏输家 题目: n 个朋友在玩游戏。这些朋友坐成一个圈,按 顺时针方向 从 1 到 n 编号。从第 i 个朋友的位置开始顺时针移动 1 步会到达第 (i 1) 个朋友的位置(1 < i < n),而从第 n 个朋友的位置开始顺时针移…...

OpenCV之薄板样条插值(ThinPlateSpline)
官方文档:OpenCV: cv::ThinPlateSplineShapeTransformer Class Reference 使用方法: 头文件:#include <opencv2/shape/shape_transformer.hpp> (1)点匹配 一般根据有多少个样本(或者点)…...