[算法沉淀记录] 排序算法 —— 选择排序

排序算法 —— 选择排序

基本概念

选择排序是一种简单的排序算法,它的工作原理是每次从待排序的列表中选择最小(或最大)的元素,将其与列表中的第一个位置交换,然后继续对剩余的元素进行排序,直到整个列表排序完成。选择排序的时间复杂度为O(n^2),是一种不高效的排序算法,但在某些情况下,由于其简单性和稳定性,仍然被广泛使用。

算法基本思想

选择排序的基本思想是每次从待排序的列表中选择最小(或最大)的元素,将其与列表中的第一个位置交换,然后继续对剩余的元素进行排序,直到整个列表排序完成。

算法步骤

  1. 首先,将第一个元素设为最小值(或最大值)。
  2. 然后,将列表中的每个元素与最小值(或最大值)进行比较,如果找到更小的(或更大的)值,则更新最小值(或最大值)的索引。
  3. 最后,将最小值(或最大值)与列表中的第一个位置交换。
  4. 重复步骤1-3,直到整个列表排序完成。
  5. 返回排序后的列表。

伪代码描述

function selectionSort(arr):for i from 0 to length(arr) - 1:minIndex = ifor j from i + 1 to length(arr):if arr[j] < arr[minIndex]: # 寻找最小的元素minIndex = j # 更新最小元素的索引swap arr[minIndex] and arr[i] # 交换最小元素和第一个位置的元素return arr # 返回排序后的列表

优缺点

优点

  1. 简单易懂,易于实现。
  2. 适用于小规模的数据集。
  3. 可以在部分有序的数据集上进行优化。
  4. 适用于数据集的顺序与最终排序结果的顺序相同的情况。
  5. 适用于对内存要求严格的场景。
  6. 适用于对稳定性要求不高的场景。
  7. 适用于对时间要求不高的场景。
  8. 适用于对空间要求不高的场景。
  9. 适用于对数据集的顺序不敏感的情况。
  10. 适用于对数据集的顺序敏感的情况。

缺点

  1. 效率较低,时间复杂度为O(n^2)
  2. 需要进行多次交换操作,不适合大规模的数据集。
  3. 不适用于对稳定性要求较高的场景。
  4. 不适用于对时间要求较高的场景。
  5. 不适用于对空间要求较高的场景。

应用场景

  1. 当数据集较小且对时间要求不高时,可以选择使用选择排序。
  2. 当数据集的顺序与最终排序结果的顺序相同且对稳定性要求不高时,可以选择使用选择排序。
  3. 当对内存要求严格时,可以选择使用选择排序。

时间复杂度

  • 最好情况时间复杂度:O(n^2),当列表已经有序时。
  • 最坏情况时间复杂度:O(n^2),当列表逆序时。
  • 平均情况时间复杂度:O(n^2)

为什么时间复杂度是O(n^2)?

时间复杂度分析:

  • 外层循环需要n-1次迭代。
  • 内层循环需要n-1次迭代。
  • 总的时间复杂度为O(n^2)

如何避免最坏情况下的时间复杂度?

可以使用随机化选择的方法来避免最坏情况下的时间复杂度。每次选择最小值或最大值时,随机选择一个元素进行比较。这样可以保证在最坏情况下,时间复杂度为O(n^2)。但在平均情况下,时间复杂度为O(n)。因此,随机化选择是一种优化方法。但在实际应用中,随机化选择并不常用。因为随机化选择需要额外的空间来存储随机数。并且随机化选择的时间复杂度为O(n)。因此,随机化选择并不常用。

空间复杂度

  • 空间复杂度:O(1),不需要额外的空间。
  • 原地排序:是。

为什么空间复杂度是O(1)?

空间复杂度分析:

  • 只需要常数个额外的空间来存储临时变量。
  • 总的空间复杂度为O(1)

代码实现

template <typename T>
void selectionSort(vector<T> &arr)
{// n is the size of the arrayint n = arr.size();// loop through the array n-1 timesfor (int i = 0; i < n - 1; i++){// set the minimum index to iint min_index = i;// loop through the array from i+1 to nfor (int j = i + 1; j < n; j++){// if the current element is less than the minimum index elementif (arr[j] < arr[min_index]){// set the minimum index to the current elementmin_index = j;}}// if the minimum index is not equal to iif (min_index != i){// swap the elements at index i and min_indexswap(arr[i], arr[min_index]);}}
}

这段代码是C++中一个选择排序算法的实现。选择排序是一种简单的排序算法,它的工作原理是不断地选择剩余元素中的最小(或最大)元素,然后将其放到已排序部分的末尾。下面是该算法的详细解释:

  1. 模板参数:
    template <typename T>
    
    这使得selectionSort函数可以接受任何类型的元素数组,例如整数、浮点数、字符或自定义对象。
  2. 函数参数:
    void selectionSort(vector<T> &arr)
    
    该函数接受一个类型为Tvector的引用,这意味着任何传入此函数的数组都将在排序过程中被修改。
  3. 获取数组大小:
    int n = arr.size();
    
    这里,我们获取数组的长度,这样我们就可以在后续的循环中使用它。
  4. 外部循环:
    for (int i = 0; i < n - 1; i++)
    
    外部循环从数组的第一个元素运行到倒数第二个元素。这是因为最后一个元素将在每次迭代中被正确放置(因为它将是剩余元素中的最大元素)。
  5. 设置最小索引:
    int min_index = i;
    
    我们假设当前索引i处的元素是未排序部分的最小元素。
  6. 内部循环:
    for (int j = i + 1; j < n; j++)
    
    内部循环从i+1开始,到数组的末尾结束。这是为了比较未排序部分的每个元素,以找到实际的最小元素。
  7. 找到最小元素:
    if (arr[j] < arr[min_index])
    {min_index = j;
    }
    
    如果我们发现一个元素小于当前认为的最小元素,我们就更新min_index以指向这个新的最小元素。
  8. 交换元素:
    if (min_index != i)
    {swap(arr[i], arr[min_index]);
    }
    
    如果我们在未排序部分找到了一个比当前索引i处的元素更小的元素,我们就交换这两个元素。这确保了最小元素被放置在已排序部分的末尾。
  9. 重复:
    外部循环继续,重复此过程,直到数组完全排序。
    选择排序的时间复杂度是 O ( n 2 ) O(n^2) O(n2),因为它涉及双重循环。这使得它在处理大型数据集时效率不高,但对于小型数据集或几乎已经排序的数据集,它可以相当快速。

上述代码的Python版本:

def selection_sort(arr):n = len(arr)for i in range(n - 1):min_index = ifor j in range(i + 1, n):if arr[j] < arr[min_index]:min_index = jif min_index != i:arr[i], arr[min_index] = arr[min_index], arr[i]

完整的代码

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <cassert>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 selectionSort(vector<T> &arr)
{// n is the size of the arrayint n = arr.size();// loop through the array n-1 timesfor (int i = 0; i < n - 1; i++){// set the minimum index to iint min_index = i;// loop through the array from i+1 to nfor (int j = i + 1; j < n; j++){// if the current element is less than the minimum index elementif (arr[j] < arr[min_index]){// set the minimum index to the current elementmin_index = j;}}// if the minimum index is not equal to iif (min_index != i){// swap the elements at index i and min_indexswap(arr[i], arr[min_index]);}}
}void basicTypeSelectionSortCase()
{vector<int> intArr = {5, 2, 8, 1, 3};vector<double> doubleArr = {5.5, 2.2, 8.8, 1.1, 3.3};vector<char> charArr = {'g', 'e', 'o', 'r', 'g'};selectionSort<int>(intArr);selectionSort<double>(doubleArr);selectionSort<char>(charArr);cout << "Sorted int array: ";for (int i : intArr){cout << i << " ";}cout << endl;cout << "Sorted double array: ";for (double i : doubleArr){cout << i << " ";}cout << endl;cout << "Sorted char array: ";for (char i : charArr){cout << i << " ";}cout << endl;
}void personSelecttionSortCase()
{// Now I want to write some Person class's quick sort examples in here:vector<Person> personArr = {Person("John", 25, 88), Person("Alice", 30, 77), Person("Bob", 20, 66)};selectionSort<Person>(personArr);cout << "Sorted Person array: ";const auto &personSize = personArr.size();for (size_t i = 0; i < personSize; i++){const auto &person = personArr[i];cout << person.getName() << " " << person.getAge() << " " << person.getScore() << endl;}cout << endl;// Now I want to write some Person class's quick sort examples in here:vector<Person> personArrNew = {Person("Tom", 35, 77), Person("Panda", 22, 88), Person("Alex", 50, 99)};const auto &personSizeNew = personArrNew.size();selectionSort<Person>(personArrNew);cout << "Sorted Person array: " << endl;for (size_t i = 0; i < personSizeNew; i++){const auto &person = personArrNew[i];cout << person.getName() << " " << person.getAge() << " " << person.getScore() << endl;}cout << endl;
}void testSelectionSort()
{vector<int> arr1 = {64, 25, 12, 22, 11};selectionSort(arr1);assert(arr1 == vector<int>({11, 12, 22, 25, 64}));vector<int> arr2 = {5, 2, 8, 12, 4};selectionSort(arr2);assert(arr2 == vector<int>({2, 4, 5, 8, 12}));vector<int> arr3 = {9, 3, 1, 6, 5, 2};selectionSort(arr3);assert(arr3 == vector<int>({1, 2, 3, 5, 6, 9}));vector<int> arr4 = {1, 2, 3, 4, 5, 6};selectionSort(arr4);assert(arr4 == vector<int>({1, 2, 3, 4, 5, 6}));vector<int> arr5 = {6, 5, 4, 3, 2, 1};selectionSort(arr5);assert(arr5 == vector<int>({1, 2, 3, 4, 5, 6}));
}int main()
{testSelectionSort();basicTypeSelectionSortCase();personSelecttionSortCase();return 0;
}

这段C++代码定义了一个Person类,并自定义了比较操作符。Person类有三个成员变量:nameagescore。它还有比较操作符(><==!=<=>=),允许它与其他Person对象根据它们的分数进行比较。

selectionSort函数是一个通用的排序函数,它接受一个向量,并使用选择排序算法对其进行排序。它的原理是遍历向量,找到剩余未排序部分的最小元素,然后将其与未排序部分的第一个元素交换。这个过程会重复,直到整个向量都被排序。

basicTypeSelectionSortCase函数演示了如何使用selectionSort函数,对不同数据类型(int、double和char)进行排序。它创建了整数、双精度浮点数和字符类型的向量,使用selectionSort函数进行排序,然后打印排序后的数组。

personSelecttionSortCase函数演示了如何使用selectionSort函数,对Person类进行排序。它创建了一个Person对象的向量,使用selectionSort函数进行排序,然后打印排序后的数组。

testSelectionSort函数是selectionSort函数的一个测试用例。它创建了一个整数类型的向量,使用selectionSort函数进行排序,然后检查排序后的向量是否与预排序的向量相等。如果排序后的向量与预排序的向量相等,测试通过;否则,测试失败。

main函数中,调用了testSelectionSort函数,对selectionSort函数进行测试,包括不同数据类型的测试和Person类的测试。如果所有测试都通过,程序将输出"所有测试通过"。

以下是这个代码的Python版本:

class Person:def __init__(self, name: str, age: int, score: int):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 self.score != other.score or self.age != other.age or self.name != other.namedef __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 selection_sort(arr):n = len(arr)for i in range(n - 1):min_index = ifor j in range(i + 1, n):if arr[j] < arr[min_index]:min_index = jif min_index != i:arr[i], arr[min_index] = arr[min_index], arr[i]def test_selection_sort():arr1 = [64, 25, 12, 22, 11]selection_sort(arr1)assert arr1 == [11, 12, 22, 25, 64]arr2 = [5, 2, 8, 12, 4]selection_sort(arr2)assert arr2 == [2, 4, 5, 8, 12]arr3 = [9, 3, 1, 6, 5, 2]selection_sort(arr3)assert arr3 == [1, 2, 3, 5, 6, 9]arr4 = [1, 2, 3, 4, 5, 6]selection_sort(arr4)assert arr4 == [1, 2, 3, 4, 5, 6]arr5 = [6, 5, 4, 3, 2, 1]selection_sort(arr5)assert arr5 == [1, 2, 3, 4, 5, 6]def basic_type_selection_sort_case():int_arr = [5, 2, 8, 1, 3]double_arr = [5.5, 2.2, 8.8, 1.1, 3.3]char_arr = ['g', 'e', 'o', 'r', 'g']selection_sort(int_arr)selection_sort(double_arr)selection_sort(char_arr)print("Sorted int array:", int_arr)print("Sorted double array:", double_arr)print("Sorted char array:", char_arr)def person_selection_sort_case():person_arr = [Person("John", 25, 88), Person("Alice", 30, 77), Person("Bob", 20, 66)]selection_sort(person_arr)print("Sorted Person array:")for person in person_arr:print(person.get_name(), person.get_age(), person.get_score())person_arr_new = [Person("Tom", 35, 77), Person("Panda", 22, 88), Person("Alex", 50, 99)]selection_sort(person_arr_new)print("Sorted Person array:")for person in person_arr_new:print(person.get_name(), person.get_age(), person.get_score())if __name__ == "__main__":test_selection_sort()basic_type_selection_sort_case()person_selection_sort_case()

总结

在本文档中,我们学习了如何使用选择排序算法对数组进行排序。我们首先定义了一个选择排序函数,然后使用该函数对不同类型的数组进行排序。最后,我们展示了排序后的数组。希望这个文档对你有所帮助!

扩展阅读

优化时间复杂度的思路

选择排序是一种简单直观的排序算法。它的工作原理是在未排序的序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
选择排序的时间复杂度为 O ( n 2 ) O(n^2) O(n2),因为它需要进行 n − 1 n-1 n1 轮的比较,每轮比较中需要比较剩余未排序的元素数量,这个数量从 n − 1 n-1 n1 递减到 1。因此,选择排序并不是一种高效的排序算法,尤其是在处理大数据集时。
尽管如此,选择排序算法的优化主要集中在减少比较次数上,但它的基本时间复杂度很难有大的改进。下面是一些优化选择排序的尝试:

  1. 跳跃选择排序(Jump Selection Sort):
    在每一轮选择最小(或最大)元素时,可以跳过一些元素。例如,第一轮跳过1个元素,第二轮跳过2个元素,以此类推。这样可以稍微减少比较次数,但时间复杂度仍然是 O ( n 2 ) O(n^2) O(n2)
  2. 双向选择排序(Bidirectional Selection Sort):
    也称为双边选择排序,这种方法每一轮同时找到最大和最小元素,并放到序列的两端。这样可以将排序过程减半,但每轮的比较次数仍然是 O ( n ) O(n) O(n),因此总体的时间复杂度仍然是 O ( n 2 ) O(n^2) O(n2)
  3. 使用更高效的交换方法:
    在某些情况下,可以优化交换两个元素的方法,例如使用异或运算。但这种方法对时间复杂度的改善有限。
  4. 并行化:
    选择排序的一个潜在优化是并行化处理。每一轮可以并行地找到最小(或最大)元素,特别是在多核处理器上。但这种方法的主要限制是并行处理本身的复杂性,以及可能存在的并行开销。
    总的来说,选择排序的优化主要是减少比较次数,但它们并不能改变其 O ( n 2 ) O(n^2) O(n2) 的时间复杂度。对于大多数实际应用,更高效的排序算法(如快速排序、归并排序或堆排序)通常是更好的选择。

跳跃选择排序(Jump Selection Sort)

跳跃选择排序(Jump Selection Sort)是选择排序的一种变种,它通过减少比较的次数来提高效率。在跳跃选择排序中,不是每次都只比较相邻的两个元素,而是每次跳过多个元素,比较剩余未排序元素中的最小(或最大)元素,并将其放到正确的位置。
跳跃选择排序的基本步骤如下:

  1. 计算跳跃长度:
    确定每次跳跃的长度。这通常是通过分析数据集的特性来完成的。例如,如果数据已经部分排序,跳跃长度可以从1逐渐增加到数据集的大小。
  2. 跳跃选择:
    从第一个元素开始,跳过跳跃长度个元素,然后找到剩余未排序元素中的最小(或最大)元素,并将其放到当前位置。
  3. 重复:
    继续跳跃选择,直到所有元素都被处理。
    以下是跳跃选择排序的伪代码:
function jump_selection_sort(arr):n = length(arr)# 初始化跳跃长度为数据集大小for step in range(n):# 假设最小元素在当前元素min_index = step# 跳过跳跃长度个元素for i in range(step + 1, step + jump_length + 1):# 检查是否找到更小的元素if arr[i] < arr[min_index]:min_index = i# 交换元素swap(arr[step], arr[min_index])

对于C++的模板实现,我们可以使用以下代码:

// The jump selection sort function.
template <typename T>
void jumpSelectionSort(vector<T> &arr)
{// n is the size of the arrayint n = arr.size();// step is the jump sizeint step = n / 2;// while step is greater than 0while (step > 0){// for each element in the arrayfor (int i = 0; i + step < n; i++){// min_index is the index of the minimum element// in the sub array from i to i + stepint min_index = i;// for each element in the sub array from i to i + stepfor (int j = i + 1; j <= i + step && j < n; j++){// if the element at j is less than the element at min_indexif (arr[j] < arr[min_index]){// set min_index to jmin_index = j;}}// if the element at min_index is not equal to iif (min_index != i){// swap the elements at i and min_indexswap(arr[i], arr[min_index]);}}// set step to be half of the previous stepstep = step / 2;}
}template <typename T>
void testJumpSelectionSort(vector<T> &testVec)
{auto sortedArr = testVec;sort(sortedArr.begin(), sortedArr.end());jumpSelectionSort<T>(testVec);if (testVec == sortedArr){cout << "Test passed for the given test case!" << endl;}
}void jumpSelectionSortCase()
{vector<int> arr{3, 7, 9, 1, 2, 6, 8, 4, 5};testJumpSelectionSort<int>(arr); // Test case 1: Passed.// ... other test cases ...vector<double> dArr{3.0, 7.0, 9.0, 1.0, 2.0, 6.0, 8.0, 4.0, 5.0};testJumpSelectionSort<double>(dArr); // Test case 2: Passed.vector<float> fArr{3.0f, 7.0f, 9.0f, 1.0f, 2.0f, 6.0f, 8.0f, 4.0f, 5.0f};testJumpSelectionSort<float>(fArr); // Test case 3: Passed.vector<char> cArr{'c', 'a', 'b'};testJumpSelectionSort<char>(cArr); // Test case 4: Passed.vector<Person> personArr{Person("Alice", 25, 80), Person("Bob", 20, 65), Person("Charlie", 22, 77)};testJumpSelectionSort<Person>(personArr); // Test case 5: Passed.
}

请注意,跳跃选择排序的性能改进依赖于跳跃长度的选择。在某些情况下,它可能比基本的 O ( n 2 ) O(n^2) O(n2)选择排序要快,但通常情况下,它仍然不如 O ( n log ⁡ n ) O(n \log n) O(nlogn)的排序算法,如快速排序、归并排序或堆排序。

双向选择排序(Bidirectional Selection Sort)

双向选择排序(Bidirectional Selection Sort)是选择排序的一种变体,它在每一步排序中同时找到最大值和最小值,并将它们放到已排序部分的正确位置。这样,每一步可以减少两次交换操作,从而在某些情况下比传统的选择排序稍微高效一些。

双向选择排序的基本思想是:

  1. 在未排序的部分找到最小元素,并将其放到已排序部分的起始位置。
  2. 在未排序的部分找到最大元素,并将其放到已排序部分的末尾位置。
  3. 重复上述步骤,每次减少未排序部分的边界,直到整个数组被排序。

伪代码如下:

function bidirectionalSelectionSort(arr):n = length(arr)for i from 0 to n/2:# 找到[i, n-i-1]区间内的最小元素的索引min_index = ifor j from i+1 to n-i-1:if arr[j] < arr[min_index]:min_index = j# 将找到的最小元素交换到位置iswap(arr[i], arr[min_index])# 如果最大元素的索引小于当前的最小元素索引,需要调整if min_index == i:max_index = min_indexelse:max_index = i# 找到[i, n-i-1]区间内的最大元素的索引for j from i+1 to n-i-1:if arr[j] > arr[max_index]:max_index = j# 将找到的最大元素交换到位置n-i-1swap(arr[n-i-1], arr[max_index])

下面是C++模板的实现代码:

template <typename T>
void bidirectionalSelectionSort(vector<T> &arr)
{// n is the size of the arrayint n = arr.size();// loop from 0 to n/2for (int i = 0; i < n / 2; ++i){// set the min and max index to iint min_index = i, max_index = i;// loop from i+1 to n-i-1for (int j = i + 1; j <= n - i - 1; ++j){// if arr[j] is less than arr[min_index]if (arr[j] < arr[min_index]){// set min_index to jmin_index = j;}// if arr[j] is greater than arr[max_index]if (arr[j] > arr[max_index]){// set max_index to jmax_index = j;}}// if min_index is not equal to iif (min_index != i){// swap arr[i] and arr[min_index]swap(arr[i], arr[min_index]);}// if max_index is equal to iif (max_index == i){// set max_index to min_indexmax_index = min_index;}// if max_index is not equal to n-i-1if (max_index != n - i - 1){// swap arr[n-i-1] and arr[max_index]swap(arr[n - i - 1], arr[max_index]);}}
}template <typename T>
void printResult(vector<T>& data)
{bidirectionalSelectionSort(data);cout << "Sorted array: \n";for (T value : data){cout << value << " ";}cout << endl;
}void bidirectionalSelectionSortCase()
{// Sort a double arrayvector<double> doubleData = {64.0, 34.0, 25.0, 12.0, 22.0, 11.0, 90.0};printResult(doubleData);// Sort an int arrayvector<int> intData = {64, 34, 25, 12, 22, 11, 90};printResult(intData);// Sort a char arrayvector<char> charData = {'d', 'b', 'a', 'c'};printResult(charData);
}

在这个C++实现中,我们使用模板使得bidirectionalSelectionSort函数可以接受任何类型的vector,只要该类型支持比较操作。在main函数中,我们展示了如何使用这个模板化的函数来排序doubleint类型的数组。

个人格言

追寻与内心共鸣的生活,未来会逐渐揭晓答案。

Pursue the life that resonates with your heart, and the future will gradually reveal the answer.

在这里插入图片描述

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

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

相关文章

基于Java SSM框架实现家庭食谱管理系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现家庭食谱管理系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个家庭食谱管理系统 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论…

省内顺丰寄一台电脑多少钱,顺丰不会乱丢包裹

省内用顺丰快递寄电脑要多少钱&#xff1f; 使用顺丰速运。 顺丰快递不会乱扔包裹。 根据地区不同&#xff0c;邮费预计在120至150元左右。 有些地方顺丰不允许寄电脑&#xff0c;因为电脑特别容易损坏。 一般来说&#xff0c;您需要自己做。 有的顺丰还帮忙在电脑主机的外箱上…

喜报|迪捷软件入选工信部“2023年信息技术应用创新解决方案”

为进一步推进信创生态建设&#xff0c;激发产业自主创新活力&#xff0c;高效促进供需协同发展&#xff0c;加强区域联动和资源整合&#xff0c;国家工业和信息化部网络安全产业发展中心&#xff08;工业和信息化部信息中心&#xff09;联合相关单位&#xff0c;遴选了一批可复…

2024年江苏事业单位招聘报名指南

江苏事业单位目前已出的公告中&#xff0c;扬州和常州的报名时间相对较早&#xff0c;2月27日就开始报名了&#xff1b;其他大多在2月28日或3月1日起开始报名。 报名请移步<江苏人事考试网> 【报名时间】 2月28日9:00-3月4日16:00#图文万粉激励计划# 【资格初审】2月28…

招聘系统架构的设计与实现

在当今竞争激烈的人才市场中&#xff0c;有效的招聘系统对企业吸引、筛选和管理人才至关重要。本文将探讨招聘系统的架构设计与实现&#xff0c;帮助企业构建一个高效、可靠的人才招聘平台。 ## 1. 系统架构设计 ### 1.1 微服务架构 招聘系统通常采用微服务架构&#xff0c;将…

提高办公效率:Excel在文秘与行政办公中的应用技巧

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在当今信息化时代&#xff0c;Excel作为一款常…

大学课本电子版下载

原文&#xff1a;https://www.zhihu.com/question/356005353

一款.NET下 WPF UI框架介绍

WPF开源的UI框架有很多,如HandyControl、MahApps.Metro、Xceed Extended WPF Toolkit™、Modern UI for WPF (MUI)、Layui-WPF、MaterialDesignInXamlToolkit、等等,今天小编带大家认识一款比较常用的kaiyuanUI---WPF UI,这款ui框架美观现代化,用起来也超级方便, 界面展示…

No matching version found for get-symbol-description@^1.0.2前端项目报错解决(亲测可用)

目录 一、问题详情 二、解决方案 一、问题详情 拉取一个新的项目的时候&#xff0c;前端进行install依赖的时候&#xff0c;报了如下的错误。 6120 verbose node v16.15.1 6121 verbose npm v8.11.0 6122 error code ETARGET 6123 error notarget No matching version foun…

2024年1月京东洗衣机行业数据分析:TOP10品牌销量销额排行榜

鲸参谋监测的京东平台1月份洗衣机市场销售数据已出炉&#xff01; 根据鲸参谋电商数据分析平台显示&#xff0c;今年1月份&#xff0c;京东平台上洗衣机的销量约160万件&#xff0c;环比上个月增长约42%&#xff0c;同比去年下滑7%&#xff1b;销售额约28亿元&#xff0c;环比…

Vue-2

生命周期 Vue 生命周期 Vue 生命周期函数 Vue 生命周期过程中&#xff0c;会自动运行一些函数&#xff0c;被称为"生命周期钩子"&#xff0c;让开发者可以在特定阶段运行自己的代码 created 应用演示 <body><div class"box"><ul v-for&q…

景联文科技:引领战场数据标注服务,赋能态势感知升级

自21世纪初&#xff0c;信息化战争使战场环境变得更为复杂和难以预测&#xff0c;持续涌入的海量、多样化、多来源和高维度数据&#xff0c;加大了指挥员的认知负担&#xff0c;使其需要具备更强的数据处理能力。 同时&#xff0c;计算机技术和人工智能技术的飞速发展&#xff…

【算法训练营】:周测5

需要详细的实现代码实现请私信博主 考题10-5 题目描述 平面固定有一些全等的圆角矩形&#xff0c;不同的圆角矩形具有不同的位置和倾斜角。这些圆角矩形都通过将以原本四个直角处距离两条直角边均为 r&#xfffd; 的位置为圆心&#xff0c;半径为 r&#xfffd; 且与两条直…

CCF-CSP: 因子化简(100分)

第一次提交的时候90分&#xff0c;显示的超时&#xff0c;第一反应是难道有死循环? 检查一遍发现并没有&#xff0c;那就是真的超时了&#xff0c;然后翻阅blog,发现不需要去做判断是否是素数这一步&#xff0c;原因是任意一个非素数都是素数乘积构成&#xff0c;比如说&#…

dpdk协议栈之udp架构优化

dpdk优势 传统网络架构与 DPDK&#xff08;Data Plane Development Kit&#xff09;网络架构之间存在许多区别&#xff0c;而 DPDK 的优势主要体现在以下几个方面&#xff1a; 数据包处理性能&#xff1a;传统网络架构中&#xff0c;网络数据包的处理通常由操作系统的网络协议…

理想滤波器、巴特沃斯滤波器、高斯滤波器实现(包含低通与高通,代码实现与分析)

本篇博客聚焦理想滤波器、巴特沃斯滤波器、高斯滤波器进行原理剖析、代码实现和结果总结&#xff0c;代码含有详细注释&#xff0c;希望帮助大家理解。 以下将从理想低通滤波器、理想高通滤波器、巴特沃斯低通滤波器、巴特沃斯高通滤波器、高斯低通滤波器、高斯高通滤波器六个…

【GPTs分享】每日GPTs分享之Image Generator Tool

今日GPTs分享&#xff1a;Image Generator Tool。Image Generator Tool是一种基于人工智能的创意辅助工具&#xff0c;专门设计用于根据文字描述生成图像。这款工具结合了专业性与友好性&#xff0c;鼓励用户发挥创造力&#xff0c;同时提供高效且富有成效的交互体验。 主要功能…

Debezium发布历史153

原文地址&#xff1a; https://debezium.io/blog/2023/07/10/custom-http-signaling-notification/ 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. Debezium signaling and notifications - Part 2: Customisat…

<网络安全>《55 概念讲解<第二课 MAC地址>》

1 MAC地址是什么&#xff1f; MAC地址&#xff08;Media Access Control Address&#xff09;是一种标识网络设备的唯一地址&#xff0c;也被称为物理地址或硬件地址。它由网络设备制造商在生产过程中写入网卡的EPROM&#xff08;一种可擦写的闪存芯片&#xff09;。 IP地址和…

LabVIEW变压器振动信号数据采集与分析

LabVIEW变压器振动信号数据采集与分析 随着电力系统的快速发展&#xff0c;对变压器的安全监控和故障诊断需求日益增加。设计了一套基于LabVIEW的变压器振动信号数据采集与分析系统&#xff0c;提高变压器的运行安全性和可靠性&#xff0c;实现对变压器振动信号的实时监测和故…