[算法沉淀记录] 排序算法 —— 希尔排序
排序算法 —— 希尔排序
算法介绍
希尔排序(Shell Sort)是一种基于插入排序的算法,由Donald Shell于1959年提出。希尔排序的基本思想是将待排序的序列划分成若干个子序列,分别进行插入排序,待整个序列中的记录基本有序时,再对全体记录进行一次直接插入排序。
算法基本思想
基本概念
- 间隔序列:希尔排序中,间隔序列是一个递减的序列,用于控制子序列的划分。初始间隔较大,逐步减小,最终减至1,此时整个序列被视为一个子序列。
- 子序列:根据间隔序列,将原始序列划分成若干个子序列,每个子序列中的元素间隔为当前间隔序列中的数值。
算法步骤
- 选择一个间隔序列 ( G_1, G_2, …, G_t ),其中 ( G_t = 1 )。
- 根据当前间隔 ( G_i ),将序列分成若干子序列,对每个子序列进行插入排序。
- 减小间隔 ( G_{i+1} ),重复步骤2,直至间隔为1,此时整个序列被视为一个子序列,进行最后一次插入排序。
伪代码描述
function shellSort(arr):n = length(arr)gap = n / 2while gap > 0:for i = gap; i < n; i++:temp = arr[i]j = iwhile j >= gap and arr[j - gap] > temp:arr[j] = arr[j - gap]j -= gaparr[j] = tempgap = gap / 2return arr
优点
- 效率提升:希尔排序比传统的插入排序在效率上有显著提升,特别是当数据量较大时。
- 减少移动次数:通过比较距离较远的元素,希尔排序减少了元素之间的比较和移动次数,从而提高了排序效率。
- 灵活性:希尔排序的间隔序列可以灵活选择,不同的间隔序列可能会带来不同的性能表现。
- 易于实现:希尔排序的算法实现相对简单,理解和实现起来比较容易。
缺点
- 时间复杂度:在最坏的情况下,希尔排序的时间复杂度仍然是 (O(n^2)),这使得它在处理大数据集时可能不如其他更高效的排序算法(如快速排序、归并排序等)。
- 不稳定排序算法:希尔排序不是稳定的排序算法,相同值的元素可能会因为间隔序列的选择而交换位置。
- 依赖间隔序列:希尔排序的性能很大程度上取决于间隔序列的选择,选择不当可能会导致性能不如插入排序。
应用场景
- 小规模数据:对于小规模的数据集,希尔排序可能比其他算法更快,因为其时间复杂度接近线性。
- 简单应用:在不需要高精度或稳定性,且数据规模不大的情况下,希尔排序是一个不错的选择。
- 教育与学习:由于其算法实现简单,希尔排序常被用于教学,帮助初学者理解排序算法的概念。
尽管希尔排序在理论上的时间复杂度不如一些现代排序算法,但在实际应用中,尤其是在数据量不是非常大时,希尔排序由于其低廉的实现成本和较好的性能,仍然是一个可行的选择。此外,对于一些特定数据结构和数据集,通过精心设计的间隔序列,希尔排序可以展现出比传统插入排序更好的性能。
时间复杂度
希尔排序的时间复杂度分析相对复杂,因为它依赖于间隔序列的选择。以下是几种不同情况下的时间复杂度分析
最坏情况
在最坏的情况下,希尔排序的时间复杂度为 (O(n^2))。这是因为在最坏情况下,每次插入排序操作都需要移动其他元素。由于希尔排序是通过比较间隔序列中的元素来进行的,因此存在一种情况,其中间隔序列被设置为非常小的值(例如1),这实际上将希尔排序转换为普通的插入排序。
平均情况
在平均情况下,希尔排序的时间复杂度通常被认为介于 (O(n^{1.3} \log n)) 到 (O(n^{2.25} \log n)) 之间。这是因为在平均情况下,插入排序的效率得到了提高,因为每次插入操作不需要移动所有的元素。
最佳情况
在最佳情况下,希尔排序的时间复杂度可以达到 (O(n \log^2 n))。这是当间隔序列被设计得非常好的情况下,例如使用Sedgewick间隔序列时。在这种情况下,每次插入操作需要移动的元素数量较少,因此整体效率较高。
空间复杂度
希尔排序的空间复杂度为 (O(1))。这是因为希尔排序是原地排序算法,除了输入数组本身之外,它只需要一个很小的常数空间来存储间隔序列和临时变量。因此,希尔排序不需要额外的内存空间来完成排序。
证明
由于希尔排序的时间复杂度分析依赖于间隔序列的选择,没有统一的数学证明来确定其时间复杂度。上述的时间复杂度是基于实验和观察得出的,而不是精确的数学证明。然而,对于特定的间隔序列,如Sedgewick间隔序列,已经有一些研究表明它在平均和最佳情况下的时间复杂度。
总的来说,希尔排序的时间复杂度分析是实验性的,而不是理论性的。在实际应用中,选择合适的间隔序列可以显著提高希尔排序的性能,使其在某些情况下比传统的插入排序更有效率。
代码实现
Python 实现
def shell_sort(arr):n = len(arr)gap = n // 2while gap > 0:for i in range(gap, n):temp = arr[i]j = iwhile j >= gap and arr[j - gap] > temp:arr[j] = arr[j - gap]j -= gaparr[j] = tempgap //= 2
C++ 实现
void shellSort(int arr[], int n) {for (int gap = n/2; gap > 0; gap /= 2) {for (int i = gap; i < n; i += 1) {int temp = arr[i];int j;for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {arr[j] = arr[j - gap];}arr[j] = temp;}}
}
C++ 模板实现
template <typename T>
void shellSort(vector<T> &arr)
{// n is the size of the arrayint n = arr.size();// gap is the difference between the current position and the gap positionfor (int gap = n / 2; gap > 0; gap /= 2){// i is the current positionfor (int i = gap; i < n; ++i){// temp is the current elementT temp = arr[i];// j is the gap positionint j;// loop from i to gap and swap the elements if the gap position is greater than the current elementfor (j = i; j >= gap && arr[j - gap] > temp; j -= gap){arr[j] = arr[j - gap];}// swap the current element with the gap positionarr[j] = temp;}}
}
扩展阅读
优化时间复杂度的思路
- 选择合适的间隔序列:选择一个好的间隔序列是优化希尔排序的关键。Sedgewick间隔序列和Poonen间隔序列是经过精心设计的,可以在平均和最佳情况下提供较好的性能。
- 自定义间隔序列:根据具体的数据集特点,可以设计自定义的间隔序列,以适应特定的数据分布,从而提高排序效率。
- 减少比较和移动的次数:通过改进插入排序的实现,减少不必要的比较和元素的移动,可以提高希尔排序的效率。
历史上针对希尔排序时间复杂度的变种算法
- Sedgewick希尔排序:Robert Sedgewick提出了使用特定的间隔序列(Sedgewick间隔序列)来优化希尔排序。这种方法在平均和最佳情况下提供了较好的性能。
- Poonen希尔排序:Larry Poonen提出了使用一组固定的间隔序列来优化希尔排序,这些间隔序列不需要依赖于输入数据的规模。
- Knuth希尔排序:Donald Knuth提出了一种基于斐波那契数列的间隔序列,这种方法在某些情况下也表现良好。
- Hibbard希尔排序:虽然不是专门为时间复杂度优化设计的,但Hibbard间隔序列在某些情况下也可以提供较好的性能。
除了这些基于间隔序列优化的方法,还有一些其他的工作致力于改进希尔排序的性能,例如通过减少比较和交换操作来提高效率。然而,尽管这些方法可能对特定数据集或特定情况有所帮助,但它们并没有产生新的希尔排序变种,而是在原有算法基础上的一些改进。希尔排序的时间复杂度优化主要集中在间隔序列的选择和实现细节的优化上。通过选择合适的间隔序列和优化实现,可以在一定程度上提高希尔排序的性能。然而,需要注意的是,希尔排序的时间复杂度仍然在最坏情况下是 (O(n^2)),这使得它在处理大数据集时可能不如其他更高效的排序算法。
Hibbard希尔排序
伪代码
function hibbardShellSort(arr):n = length(arr)k = 1while (2^k - 1) < n:k += 1for gap = 2^(k-1) - 1; gap > 0; gap = (gap / 2) - 1:for i = gap; i < n; i++:temp = arr[i]j = iwhile j >= gap and arr[j - gap] > temp:arr[j] = arr[j - gap]j -= gaparr[j] = tempreturn arr
Python代码
def hibbard_shell_sort(arr):n = len(arr)k = 0while (1 << k) - 1 < n:k += 1gaps = [1]for i in range(k):gaps.append((1 << (2 * i)) - 1)for gap in reversed(gaps):for i in range(gap, n):temp = arr[i]j = iwhile j >= gap and arr[j - gap] > temp:arr[j] = arr[j - gap]j -= gaparr[j] = temp
C++模板代码
template <typename T>
void hibbardShellSort(vector<T> &arr)
{// Calculate the size of the arrayint n = arr.size();// Calculate the number of levels in the treeint k = 1;// Calculate the number of elements in each level of the treewhile ((1 << k) - 1 < n){k++;}// Sort each level of the treefor (int gap = (1 << (k - 1)) - 1; gap > 0; gap = (gap >> 1) - 1){// Sort each element in the levelfor (int i = gap; i < n; ++i){// Store the current element in a temporary variableT temp = arr[i];// Find the correct position for the elementint j;for (j = i; j >= gap && arr[j - gap] > temp; j -= gap){// Move the element to the correct positionarr[j] = arr[j - gap];}// Put the element in its correct positionarr[j] = temp;}}
}
完整的项目代码
Python
def shell_sort(arr):n = len(arr)gap = n // 2while gap > 0:for i in range(gap, n):temp = arr[i]j = iwhile j >= gap and arr[j - gap] > temp:arr[j] = arr[j - gap]j -= gaparr[j] = tempgap //= 2def hibbard_shell_sort(arr):n = len(arr)k = 0while (1 << k) - 1 < n:k += 1gaps = [1]for i in range(k):gaps.append((1 << (2 * i)) - 1)for gap in reversed(gaps):for i in range(gap, n):temp = arr[i]j = iwhile j >= gap and arr[j - gap] > temp:arr[j] = arr[j - gap]j -= gaparr[j] = tempdef knuth_shell_sort(arr):n = len(arr)k = 0fib = 1while fib < n:k += 1fib = (k % 2 == 0) and (3 * fib + 1) or (3 * fib - 1)gaps = [(fib - 1) for i in range(k, 0, -1)]for gap in reversed(gaps):for i in range(gap, n):temp = arr[i]j = iwhile j >= gap and arr[j - gap] > temp:arr[j] = arr[j - gap]j -= gaparr[j] = tempdef sedgewick_shell_sort(arr):n = len(arr)gap = 1while gap < n / 3:gap = 3 * gap + 1while gap > 0:for i in range(gap, n):temp = arr[i]j = iwhile j >= gap and arr[j - gap] > temp:arr[j] = arr[j - gap]j -= gaparr[j] = tempgap //= 3class Person:def __init__(self, name, age, score):self.name = nameself.age = ageself.score = scoredef __lt__(self, other):return self.score < other.scoredef __le__(self, other):return self.score <= other.scoredef __eq__(self, other):return self.score == other.score and self.age == other.age and self.name == other.namedef __ne__(self, other):return not self.__eq__(other)def __gt__(self, other):return self.score > other.scoredef __ge__(self, other):return self.score >= other.scoredef get_name(self):return self.namedef get_age(self):return self.agedef get_score(self):return self.scoredef test_shell_sort():data = [9, 8, 3, 7, 5, 6, 4, 1]shell_sort(data)print(data)d_data = [9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1]shell_sort(d_data)print(d_data)c_data = ['a', 'c', 'b', 'd', 'e']shell_sort(c_data)print(c_data)p_data = [Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)]shell_sort(p_data)for person in p_data:print(person.get_name(), person.get_age(), person.get_score())def test_hibbard_shell_sort():data = [9, 8, 3, 7, 5, 6, 4, 1]hibbard_shell_sort(data)print(data)d_data = [9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1]hibbard_shell_sort(d_data)print(d_data)c_data = ['a', 'c', 'b', 'd', 'e']hibbard_shell_sort(c_data)print(c_data)p_data = [Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)]hibbard_shell_sort(p_data)for person in p_data:print(person.get_name(), person.get_age(), person.get_score())def test_knuth_shell_sort():data = [9, 8, 3, 7, 5, 6, 4, 1]knuth_shell_sort(data)print(data)d_data = [9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1]knuth_shell_sort(d_data)print(d_data)c_data = ['a', 'c', 'b', 'd', 'e']knuth_shell_sort(c_data)print(c_data)p_data = [Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)]knuth_shell_sort(p_data)for person in p_data:print(person.get_name(), person.get_age(), person.get_score())def test_sedgewick_shell_sort():data = [9, 8, 3, 7, 5, 6, 4, 1]sedgewick_shell_sort(data)print(data)d_data = [9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1]sedgewick_shell_sort(d_data)print(d_data)c_data = ['a', 'c', 'b', 'd', 'e']sedgewick_shell_sort(c_data)print(c_data)p_data = [Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)]sedgewick_shell_sort(p_data)for person in p_data:print(person.get_name(), person.get_age(), person.get_score())if __name__ == "__main__":test_shell_sort()test_hibbard_shell_sort()test_knuth_shell_sort()test_sedgewick_shell_sort()
C++
#include <iostream>
#include <array>
#include <algorithm>
#include <vector>
#include <string>using namespace std;class Person
{
public:Person(string name, int age, int score){this->name = name;this->age = age;this->socre = score;}// Override the operator> for other function to use.bool operator>(const Person &other) const{// Compare the socre of two Person objects.return this->socre > other.socre;}// Override the operator< for other function to use.bool operator<(const Person &other) const{// Compare the socre of two Person objects.return this->socre < other.socre;}// Override the operator== for other function to use.bool operator==(const Person &other) const{// Compare the socre, age and name of two Person objects.return this->socre == other.socre &&this->age == other.age &&this->name == other.name;}// Override the operator!= for other function to use.bool operator!=(const Person &other) const{// Compare the socre, age and name of two Person objects.return this->socre != other.socre ||this->age != other.age ||this->name != other.name;}// Override the operator<= for other fnction to use.bool operator<=(const Person &other) const{// Compare the socre, age and name of two Person objects.return this->socre <= other.socre &&this->age <= other.age &&this->name <= other.name;}// Override the operator>= for other function to use.bool operator>=(const Person &other) const{// Compare the socre, age and name of two Person objects.return this->socre >= other.socre &&this->age >= other.age &&this->name >= other.name;}// Now there are some get parameters function for this calss:const string &getName() const { return this->name; }int getAge() const { return this->age; }int getScore() const { return this->socre; }private:string name;int age;int socre;
};template <typename T>
void shellSort(vector<T> &arr)
{// n is the size of the arrayint n = arr.size();// gap is the difference between the current position and the gap positionfor (int gap = n / 2; gap > 0; gap /= 2){// i is the current positionfor (int i = gap; i < n; ++i){// temp is the current elementT temp = arr[i];// j is the gap positionint j;// loop from i to gap and swap the elements if the gap position is greater than the current elementfor (j = i; j >= gap && arr[j - gap] > temp; j -= gap){arr[j] = arr[j - gap];}// swap the current element with the gap positionarr[j] = temp;}}
}void shellSortTestCase()
{vector<int> data = {9, 8, 3, 7, 5, 6, 4, 1};shellSort<int>(data);for (int i : data){cout << i << " ";}cout << endl;vector<double> dData = {9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1};shellSort<double>(dData);for (double i : dData){cout << i << " ";}cout << endl;vector<char> cData = {'a', 'c', 'b', 'd', 'e'};shellSort<char>(cData);for (char i : cData){cout << i << " ";}cout << endl;vector<Person> pData = {Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)};shellSort<Person>(pData);for (Person i : pData){cout << i.getName() << " " << i.getAge() << " " << i.getScore() << endl;}cout << endl;
}template <typename T>
void hibbardShellSort(vector<T> &arr)
{// Calculate the size of the arrayint n = arr.size();// Calculate the number of levels in the treeint k = 1;// Calculate the number of elements in each level of the treewhile ((1 << k) - 1 < n){k++;}// Sort each level of the treefor (int gap = (1 << (k - 1)) - 1; gap > 0; gap = (gap >> 1) - 1){// Sort each element in the levelfor (int i = gap; i < n; ++i){// Store the current element in a temporary variableT temp = arr[i];// Find the correct position for the elementint j;for (j = i; j >= gap && arr[j - gap] > temp; j -= gap){// Move the element to the correct positionarr[j] = arr[j - gap];}// Put the element in its correct positionarr[j] = temp;}}
}void hibbardShellSortTestCase()
{vector<int> data = {9, 8, 3, 7, 5, 6, 4, 1};hibbardShellSort<int>(data);for (int i : data){cout << i << " ";}cout << endl;vector<double> dData = {9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1};hibbardShellSort<double>(dData);for (double i : dData){cout << i << " ";}cout << endl;vector<char> cData = {'a', 'c', 'b', 'd', 'e'};hibbardShellSort<char>(cData);for (char i : cData){cout << i << " ";}cout << endl;vector<Person> pData = {Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)};hibbardShellSort<Person>(pData);for (Person i : pData){cout << i.getName() << " " << i.getAge() << " " << i.getScore() << endl;}cout << endl;
}template <typename T>
void knuthShellSort(vector<T> &arr)
{// find the length of the arrayint n = arr.size();// initialize the gapint k = 0;// initialize the fibonacci numberlong long fib = 1;// calculate the fibonacci numberwhile (fib < n){k++;fib = (k % 2 == 0) ? (3 * fib + 1) : (3 * fib - 1);}// create a vector to store the gapsvector<int> gaps;// calculate the gapsfor (int i = k; i >= 0; i--){fib = (i % 2 == 0) ? (3 * fib + 1) : (3 * fib - 1);gaps.push_back(static_cast<int>(fib) - 1);}// sort the array using the gapsfor (auto gap = gaps.rbegin(); gap != gaps.rend(); ++gap){// sort the array within the gapfor (int i = *gap; i < n; ++i){T temp = arr[i];int j;// find the correct positionfor (j = i; j >= *gap && arr[j - *gap] > temp; j -= *gap){arr[j] = arr[j - *gap];}arr[j] = temp;}}
}void knuthShellSortTestCase()
{vector<int> data = {9, 8, 3, 7, 5, 6, 4, 1};knuthShellSort<int>(data);for (int i : data){cout << i << " ";}cout << endl;vector<double> dData = {9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1};knuthShellSort<double>(dData);for (double i : dData){cout << i << " ";}cout << endl;vector<char> cData = {'a', 'c', 'b', 'd', 'e'};knuthShellSort<char>(cData);for (char i : cData){cout << i << " ";}cout << endl;vector<Person> pData = {Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)};knuthShellSort<Person>(pData);for (Person i : pData){cout << i.getName() << " " << i.getAge() << " " << i.getScore() << endl;}cout << endl;
}template <typename T>
void sedgewickShellSort(vector<T> &arr)
{int n = arr.size();int i = 0;while ((9 * (1 << (2 * i)) - 9 * (1 << i) + 1) < n){i++;}vector<int> gaps;for (int j = 0; j < i; j++){gaps.push_back(9 * (1 << (2 * j)) - 9 * (1 << j) + 1);}for (auto gap = gaps.rbegin(); gap != gaps.rend(); ++gap){for (int i = *gap; i < n; ++i){T temp = arr[i];int j;for (j = i; j >= *gap && arr[j - *gap] > temp; j -= *gap){arr[j] = arr[j - *gap];}arr[j] = temp;}}
}void sedgewickTestCase()
{vector<int> data = {9, 8, 3, 7, 5, 6, 4, 1};sedgewick<int>(data);for (int i : data){cout << i << " ";}cout << endl;vector<double> dData = {9.9, 9.1, 3.3, 7.7, 5.5, 6.6, 4.4, 1.1};sedgewick<double>(dData);for (double i : dData){cout << i << " ";}cout << endl;vector<char> cData = {'a', 'c', 'b', 'd', 'e'};sedgewick<char>(cData);for (char i : cData){cout << i << " ";}cout << endl;vector<Person> pData = {Person("Alice", 20, 90), Person("Bob", 18, 85), Person("Charlie", 22, 95)};sedgewick<Person>(pData);for (Person i : pData){cout << i.getName() << " " << i.getAge() << " " << i.getScore() << endl;}cout << endl;
}int main()
{shellSortTestCase();hibbardShellSortTestCase();knuthShellSortTestCase();sedgewickTestCase();return 0;
}
相关文章:
[算法沉淀记录] 排序算法 —— 希尔排序
排序算法 —— 希尔排序 算法介绍 希尔排序(Shell Sort)是一种基于插入排序的算法,由Donald Shell于1959年提出。希尔排序的基本思想是将待排序的序列划分成若干个子序列,分别进行插入排序,待整个序列中的记录基本有…...
conda 进入虚拟环境命令报错
问题描述 conda-script.py: error: argument COMMAND: invalid choice: activate 解决方案: 在终端命令先执行 conda init,重置conda环境。然后退出终端,重新进入终端即可conda activate env了。...

域名 SSL 证书信息解析 API 数据接口
域名 SSL 证书信息解析 API 数据接口 网络工具,提供域名 SSL 证书信息解析,多信息查询,毫秒级响应。 1. 产品功能 提供域名 SSL 证书信息解析;最完整 SSL 属性信息解析;支持多种元素信息抽取,包括主题的可…...

学习JAVA的第二天(基础)
目录 基本概念 关键字 class关键字 字面量 练习 变量 定义格式 变量使用 数据类型 基本数据类型 标识符 命名规则 键盘录入 1.导包 2.创建对象 3.接受数据 运算符 算术运算符 练习 隐式转换(自动类型提升) 强制转换 自增自减运算符 …...

代码随想录算法训练营第二十七天|93.复原IP地址、78.子集、90.子集II
93.复原IP地址 刷题https://leetcode.cn/problems/restore-ip-addresses/description/文章讲解https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html视频讲解https://www.bilibili.com/video/BV1XP4y1U73i/?vd_sourceaf4853e80f89e28094a5fe1e220d9…...

【蓝桥备赛】字串简写
字串简写 数据范围 字符串的长度为5*10的五次方,on方时间复杂度会很大。 才用动态规划的思想,dp[i]以i开头的的可能性,因为长度必须大于等于k,当i小于k的时候,如果等于第一个字符,s1时,dp[…...

nios ii开发随笔
错误一: d:/intelfpga/17.1/nios2eds/bin/gnu/h-x86_64-mingw32/bin/../lib/gcc/nios2-elf/5.3.0/../../../../../H-x86_64-mingw32/nios2-elf/bin/ld.exe: test.elf section .text will not fit in region ram_oc_xzs d:/intelfpga/17.1/nios2eds/bin/gnu/h-x86_6…...
SpringBoot项目嵌入RabbitMQ
在Spring Boot中嵌入RabbitMQ可以通过添加相应的依赖来完成。首先需要在pom.xml文件中引入spring-boot-starter-amqp依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</a…...

提升网络质量:UDPspeeder 实现网络优化与提速
提升网络质量:UDPspeeder 实现网络优化与提速 背景与意义原理与功能使用方法未来展望相关链接服务 在当今高度互联的网络环境下,网络质量的优化和提速对于用户体验至关重要。针对高延迟和丢包率较高的网络链路,UDPspeeder 提供了一种前向纠错…...

为什么前端开发变得越来越复杂了?这可能是我们的错
前端训练营:1v1私教,终身辅导计划,帮你拿到满意的 offer。 已帮助数百位同学拿到了中大厂 offer。欢迎来撩~~~~~~~~ Hello,大家好,我是 Sunday。 最近有很多同学来问我:“Sunday 老师,前端学起…...

VR系统的开发流程
虚拟现实(Virtual Reality,VR)系统是一种通过计算机技术模拟出的具有三维视角和交互性的虚拟环境,使用户能够沉浸在其中并与虚拟环境进行交互。这种技术通常利用头戴式显示器和手柄等设备,使用户能够感觉到仿佛身临其境…...

前端输入框校验限制不能输入中文
一般我们在做表单的时候都会有表单校验,通常都是用element提供的表单验证的功能,只需要通过 rules 属性传入约定的验证规则,如下面这样 rules: {userName: [{validator: checkUsername,trigger: "blur",},{ validator: this.checkData, trigge…...

强大的文本绘图——PlantUML
PlantUML是一款开源工具,它允许用户通过简单的文本描述来创建UML图(统一建模语言图)。这种方法可以快速地绘制类图、用例图、序列图、状态图、活动图、组件图和部署图等UML图表。PlantUML使用一种领域特定语言(DSL)&am…...
ES相关问题
在Elasticsearch(ES)集群中,节点根据其配置和角色可以分为以下几种主要类型: Master Node(主节点): 主节点负责管理整个集群的元数据,如索引的创建、删除、分片分配等。它维护着集群…...
基于Linux直接安装的Nginx版本升级方法
引言 随着版本的迭代和漏洞的发现,Nginx作为一款软件避免不了打补丁的命运。 以下基于Linux直接安装的Nginx版本升级。 以下操作均在本地虚拟机中操作验证,请验证后再线上操作。基于centos7测试。 前置资源 获取nginx的最新源码版本网址:…...

探索设计模式的魅力:状态模式揭秘-如何优雅地处理复杂状态转换
🌈 个人主页:danci_ 🔥 系列专栏:《设计模式》 💪🏻 制定明确可量化的目标,并且坚持默默的做事。 探索设计模式的魅力:状态模式揭秘-如何优雅地处理复杂状态转换 文章目录 一、案例…...
力扣hot100题解(python版10-12题)
哎- -最近本来就没时间写算法 这算法怎么还这么难。。。 10、和为 K 的子数组 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1: 输入:nums [1,1,1]…...

【算法】复杂度分析
第一章、如何分析代码的执行效率和资源消耗 我们知道,数据结构和算法解决的是“快”和“省”的问题,也就是如何让代码运行得更快,一级如何让代码更节省计算机的存储空间。因此,执行效率是评价算法好坏的一个非常重要的指标。那么&…...

车载电子测试学习内容
搜集了一些车载测试的学习内容,大家可以参考。...

STM32F103x 的时钟源
AHB (Advanced High-performance Bus) 高速总线,用来接高速外设的。 APB (Advanced Peripheral Bus) 低速总线,用来接低速外设的,包含APB1 和 APB2。 APB1:上面连接的是低速外设,包括电源接口、备份接口、 CAN 、 US…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...

R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...