[算法沉淀记录] 排序算法 —— 冒泡排序

排序算法 —— 冒泡排序

基本概念

冒泡排序是一种简单的排序算法。它重复地遍历要排序的列表,一次比较两个元素,并交换它们的位置,如果它们不是按照升序排列的。这步遍历是重复进行的,直到没有再需要交换,也就是说该列表已经排序完成。该算法为交换排序之一。

算法步骤

  1. 比较相邻的元素。如果第一个比第二个大,就交换它们两个。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 重复步骤1~3,直到排序完成。

时间复杂度

冒泡排序算法的运行时间与输入数据有关。最佳情况下,数据已经排序,算法仅需一次遍历即可完成。在最坏情况下,数据是完全逆序的,需要 n-1 次遍历和 n-1 次比较。因此,其时间复杂度为 O(n^2)

最好的时间复杂度

当列表已经排序时,冒泡排序的最佳时间复杂度为 O(n)。在最坏情况下,当列表反转时,时间复杂度为 O(n^2)

最坏的时间复杂度

当列表反转时,冒泡排序的最坏时间复杂度为 O(n^2)

平均时间复杂度

冒泡排序的平均时间复杂度为 O(n^2)

空间复杂度

冒泡排序的空间复杂度为 O(1),它只使用了两个附加变量。

稳定性

冒泡排序是一种稳定的排序算法,因为它不会改变相等元素的顺序。

优缺点

冒泡排序是一种简单的排序算法,但它也有其优缺点。它的优点是它的实现非常简单,并且对于小数据集来说,它的性能很好。然而,它的缺点是它对于大型数据集来说非常慢,并且它需要额外的空间来存储临时变量。因此,它最适合用于小数据集的排序。

优点

  • 实现简单
  • 对于小数据集来说,它的性能很好
  • 它是一个稳定的排序算法,不会改变具有相等键的元素的相对顺序。
  • 原地排序,不需要额外的内存。

缺点

  • 对于大型数据集来说,它的性能很慢
  • 它需要额外的空间来存储临时变量

应用场景

冒泡排序是一种基础的排序算法,由于其算法简单,因此常用于教学排序算法的入门。在实际应用中,由于其平均和最坏情况下的时间复杂度都是O(n^2),所以它并不适合处理大数据集。然而,冒泡排序在特定情况下仍然有其适用场景:

  1. 小型数据集:当数据量较小,特别是数据规模在几十到几百之间时,冒泡排序可以很快完成任务,因为其常数因子较小。
  2. 部分已排序的数组:如果数组已经部分排序,冒泡排序可以很快地将剩下的元素排到正确的位置,因为它在每一轮排序后至少会将一个元素放到最终位置。
  3. 几乎已排序的数组:对于几乎已经排序好的数组,冒泡排序的时间复杂度可以接近O(n),因为在这种情况下,内部循环的提前终止特性会发挥作用。
  4. 内存使用限制:冒泡排序是原地排序算法,除了交换元素时需要的常数额外空间,不需要额外的存储空间,这在有严格内存使用限制的环境下是一个优点。
  5. 实现简单:在一些简单的应用场景中,如嵌入式系统或教学示例中,可能会优先选择冒泡排序,因为它的实现代码简单,易于理解和维护。
  6. 稳定排序:冒泡排序是一个稳定的排序算法,如果需要保持相等元素的相对顺序不变,冒泡排序可以满足这一需求。
  7. 教学演示:在计算机科学教育中,冒泡排序经常被用来教授排序算法的基本概念,如比较和交换操作。
    尽管冒泡排序在上述场景中有其应用,但在大多数需要高性能排序的应用中,更高效的算法如快速排序、归并排序或堆排序通常是更好的选择。

代码实现

下面是一个简单的python的案例:

def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        for j in range(0, n-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
    return arr

接下来是一个C++代码案例:

void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n-1; i++) {
        for (int j = 0; j < n-i-1; j++) {
            if (arr[j] > arr[j+1]) {
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}

下面是一个 C++ 模板的代码案例:

template <typename T>
void bubbleSort(T arr[], int n)
{
    // Loop through the array n-1 times
    for (int i = 0; i < n - 1; i++)
    {
        // Loop through the array n-i-1 times
        for (int j = 0; j < n - i - 1; j++)
        {
            // If the element at index j is greater than the element at index j+1, swap them
            if (arr[j] > arr[j + 1])
            {
                swap(arr[j], arr[j + 1]);
            }
        }
    }
}

完整 C++ 代码

下面是一个完整的C++代码案例:

#include <iostream>
#include <cassert>
#include <string>

using namespace std;

template <typename T>
void bubbleSort(T arr[], int n)
{
    // Loop through the array n-1 times
    for (int i = 0; i < n - 1; i++)
    {
        // Loop through the array n-i-1 times
        for (int j = 0; j < n - i - 1; j++)
        {
            // If the element at index j is greater than the element at index j+1, swap them
            if (arr[j] > arr[j + 1])
            {
                swap(arr[j], arr[j + 1]);
            }
        }
    }
}

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;
    }

    // Now there are some get parameters function for this calss:
    const string &getName() const { return this->name; }
    int getAge() const { return this->age; }
    int getSocre() const { return this->socre; }

private:
    string name;
    int age;
    int socre;
};

// This is a unit test function for Person class.
void testPerson()
{
    Person person1("Alice", 20, 90);
    Person person2("Bob", 21, 80);
    Person person3("Charlie", 22, 85);

    // Test operator>
    assert(person1 > person2);
    assert(!(person1 > person3));

    // Test operator<
    assert(person2 < person1);
    assert(!(person3 < person1));

    // Test operator==
    assert(person1 == person1);
    assert(!(person1 == person2));

    // Test operator!=
    assert(person1 != person2);
    assert(!(person1 != person1));
}

int main()
{
    // Declare an array of integers
    int arr[] = {64, 34, 25, 12, 22, 11, 90};
    // Calculate the size of the array
    int n = sizeof(arr) / sizeof(arr[0]);
    // Call the bubbleSort function to sort the array
    bubbleSort<int>(arr, n);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < n; i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;

    // Declare an array of floats
    double arr2[] = {64.5, 34.2, 25.1, 12.6, 22.8, 11.9, 90.0};
    // Calculate the size of the array
    int n2 = sizeof(arr2) / sizeof(arr2[0]);
    // Call the bubbleSort function to sort the array
    bubbleSort<double>(arr2, n2);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < n2; i++)
    {
        cout << arr2[i] << " ";
    }
    cout << endl;

    // Declare an array of characters
    char arr3[] = {'g', 'e', 'k', 'i', 't', 'c', 'h'};
    // Calculate the size of the array
    int n3 = sizeof(arr3) / sizeof(arr3[0]);
    // Call the bubbleSort function to sort the array
    bubbleSort<char>(arr3, n3);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < n3; i++)
    {
        cout << arr3[i] << " ";
    }
    cout << endl;

    testPerson();
    // Now I want to write some Person class's bubble sort examples in here:
    // Declare an array of Person objects
    Person arr4[] = {Person("John", 25, 90), Person("Alice", 30, 85), Person("Bob", 20, 78), Person("Eve", 22, 89)}; // This is a dummy Person class, you need to implement it properly.
    // Calculate the size of the array
    int n4 = sizeof(arr4) / sizeof(arr4[0]);
    // Call the bubbleSort function to sort the array
    bubbleSort<Person>(arr4, n4);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < n4; i++)
    {
        const auto& person = arr4[i];
        cout << person.getName() << " " << person.getAge() << " " << person.getSocre() << endl;
    }
    cout << endl;

    // Declare an array of Person pointers
    Person *arr5[4];
    arr5[0] = new Person("John", 25, 90);
    arr5[1] = new Person("Alice", 30, 85);
    arr5[2] = new Person("Bob", 20, 78);
    arr5[3] = new Person("Eve", 22, 89);
    // Calculate the size of the array
    int n5 = sizeof(arr5) / sizeof(arr5[0]);
    // Call the bubbleSort function to sort the array
    bubbleSort<Person *>(arr5, n5);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < n5; i++)
    {
        const auto& person = arr5[i];
        cout << person->getName() << " " << person->getAge() << " " << person->getSocre() << endl;
    }
    cout << endl;

    return 0;
}

这段代码在最开始定义了一个模板函数bubbleSort,用于对不同类型的数据(如整数、浮点数和字符)进行冒泡排序。然后,定义了一个名为Person的类,该类具有nameagescore属性,并重载了><==!=运算符,以便在排序时比较Person对象。

接下来,定义了一个名为testPerson的函数,用于测试Person类。在这个函数中,创建了一些Person对象,并测试了重载的运算符。

main函数中,首先对整数、浮点数和字符类型的数组进行冒泡排序,然后测试Person类。最后,对Person对象的数组和Person指针的数组进行冒泡排序,并输出排序后的结果。

综上所述,这段代码演示了如何使用冒泡排序算法对不同类型的数据进行排序,并展示了如何使用Person类进行排序。

扩展阅读

优化时间复杂度和空间复杂度的思路

冒泡排序的时间复杂度和空间复杂度优化通常涉及以下几个方面:

  1. 提前终止:在冒泡排序的过程中,如果在某一趟遍历中没有发生任何元素的交换,那么可以认为数组已经排序完成,可以提前终止排序过程。这种优化可以将最好情况下的时间复杂度从O(n^2)降低到O(n)。
  2. 双向冒泡(鸡尾酒排序):传统的冒泡排序每次只将最大的元素移动到数组的一端,而双向冒泡排序则是在每趟遍历中同时将最大元素和最小元素移动到数组的两端。这样可以在一定程度上减少排序所需的趟数。
  3. 梳排序(Comb Sort):梳排序是冒泡排序的一种改进,它通过设置一个逐渐减小的“间隔”(也称为“梳子”)来比较和交换元素。开始时,间隔较大,可以快速将大距离的元素移动到正确位置,随着排序的进行,间隔逐渐减小,最终变为1,这时数组几乎已经排序完成,进行最后一轮冒泡排序。梳排序的平均时间复杂度接近O(n2/2p),其中p是梳子间隔减小的速度。
  4. 泡沫优化:在冒泡排序中,每一趟遍历后,最后一个交换的位置之后的元素在下一趟遍历中不再需要比较,因为这部分的元素已经是排序好的。记录这个位置,下一趟遍历只需要遍历到这个位置即可。
  5. 差值交换:在冒泡排序中,如果使用差值交换代替传统的交换方式,可以减少交换操作的次数。差值交换是指只在需要交换的元素之间记录差值,而不是实际交换它们的位置。

常见的变种算法

历史上常用的冒泡排序变种包括:

  • 经典冒泡排序:最基本的冒泡排序,每次遍历将最大的元素移动到数组的末尾。
  • 鸡尾酒排序:也称为双向冒泡排序,每次遍历同时将最大元素移动到数组的一端,最小元素移动到另一端。
  • 梳排序(Comb Sort):通过逐渐减小的间隔来比较和交换元素,最后进行一次冒泡排序来修正剩余的元素顺序。
  • 奇偶排序:在冒泡排序的基础上,交替进行奇数索引和偶数索引的元素比较和交换。
  • 混沌冒泡排序:引入随机性,每次随机选择两个元素进行比较和交换,用于某些特定场景下的排序。

需要注意的是,尽管这些优化可以在某些情况下提高冒泡排序的性能,但它们通常不能改变冒泡排序最坏情况下的时间复杂度O(n^2)。因此,对于大规模数据集的排序,更高效的算法如快速排序、归并排序或堆排序通常是更好的选择。

鸡尾酒排序(双向冒泡排序)

鸡尾酒排序(Cocktail Sort)也被称为双向冒泡排序或鸡尾酒搅拌排序,它是一种改进的冒泡排序算法。与传统的冒泡排序不同,鸡尾酒排序在每趟遍历中会同时将最大元素和最小元素移动到数组的两端,而不是只将最大元素移动到一端。这样可以在一定程度上减少排序所需的趟数。

算法步骤

算法步骤如下:

  1. 初始化:设置两个指针,一个指向数组的开始(left),另一个指向数组的末尾(right)。设置一个标志变量,用于检测在上一趟遍历中是否发生了元素交换。
  2. 正向遍历:从left开始,到right结束,比较相邻元素,如果它们的顺序错误,则交换它们。这一步将最大的元素移动到数组的末尾。
  3. 反向遍历:将right指针减一,从right开始,到left结束,比较相邻元素,如果它们的顺序错误,则交换它们。这一步将最小的元素移动到数组的开头。
  4. 重复步骤2和3:重复步骤2和3,直到在一次完整的正向遍历和反向遍历中都没有发生元素交换,这时数组已经排序完成。
  5. 结束:当left >= right时,排序结束。
伪代码描述

鸡尾酒排序的伪代码如下:

procedure cocktailSort(arr: list of sortable items)
    n = length(arr)
    swapped = true
    start = 0
    end = n - 1
    while (swapped == true)
        // 设置交换标志为false
        swapped = false
        // 正向遍历
        for i = start to end - 1
            if (arr[i] > arr[i + 1])
                swap(arr[i], arr[i + 1])
                // 发生了交换,设置交换标志为true
                swapped = true
        // 如果没有发生交换,数组已经排序完成
        if (swapped == false)
            break
        // 将end指针减一
        end = end - 1
        // 设置交换标志为false
        swapped = false
        // 反向遍历
        for i = end - 1 downto start
            if (arr[i] > arr[i + 1])
                swap(arr[i], arr[i + 1])
                // 发生了交换,设置交换标志为true
                swapped = true
        // 将start指针加一
        start = start + 1
    // 结束循环
end procedure
C++ 模板代码

下面是使用C++模板实现的鸡尾酒排序:

template<typename T>
void cocktailSort(std::vector<T>& arr) {
    bool swapped = true;
    int start = 0;
    int end = arr.size() - 1;
    while (swapped) {
        // 设置交换标志为false
        swapped = false;
        // 正向遍历
        for (int i = start; i < end; ++i) {
            if (arr[i] > arr[i + 1]) {
                std::swap(arr[i], arr[i + 1]);
                // 发生了交换,设置交换标志为true
                swapped = true;
            }
        }
        // 如果没有发生交换,数组已经排序完成
        if (!swapped) {
            break;
        }
        // 将end指针减一
        --end;
        // 设置交换标志为false
        swapped = false;
        // 反向遍历
        for (int i = end - 1; i >= start; --i) {
            if (arr[i] > arr[i + 1]) {
                std::swap(arr[i], arr[i + 1]);
                // 发生了交换,设置交换标志为true
                swapped = true;
            }
        }
        // 将start指针加一
        ++start;
    }
}

梳排序(Comb Sort)

梳排序(Comb Sort)是一种由Wlodzimierz Dobosiewicz于1980年发明,由Tim Peter于1989年发表的排序算法。它是冒泡排序的一种改进算法,旨在减少其所需的交换次数。梳排序通过比较相隔一定“间隔”(也称为“梳子”)的元素来工作,逐渐减小这个间隔,最终进行一次冒泡排序来修正剩余的元素顺序。

算法步骤

算法步骤如下:

  1. 初始化间隔:开始时,间隔设置为数组长度除以1.3(这个值是经验值,也可以使用其他系数),向下取整。这个间隔会随着排序的进行而逐渐减小。
  2. 缩减间隔:在每趟排序之后,间隔会按照某个系数(通常也是1.3)减小,直到间隔变为1。
  3. 排序:对于当前的间隔,比较相隔该间隔的元素,如果它们的顺序错误,则交换它们。这个过程类似于冒泡排序,但是比较的元素间隔更大。
  4. 重复步骤2和3:重复步骤2和3,直到间隔减小到1。这时,数组应该已经基本有序。
  5. 最终冒泡排序:进行一次传统的冒泡排序,确保数组完全有序。
伪代码描述

梳排序的伪代码如下:

procedure combSort(arr: list of sortable items)
    n = length(arr)
    gap = n
    shrink = 1.3
    swapped = false
    while gap > 1 or swapped
        // 设置间隔
        gap = floor(gap / shrink)
        if gap < 1
            gap = 1
        swapped = false
        // 对于当前的间隔,进行排序
        for i = 0 to n - gap - 1
            if arr[i] > arr[i + gap]
                swap(arr[i], arr[i + gap])
                swapped = true
    // 最终进行一次冒泡排序
    for i = 0 to n - 2
        if arr[i] > arr[i + 1]
            swap(arr[i], arr[i + 1])
end procedure
C++ 模板代码

下面是使用C++模板实现的梳排序:

#include <iostream>
#include <vector>
#include <cmath> // 用于计算地板除法
template<typename T>
void combSort(std::vector<T>& arr) {
    int n = arr.size();
    int gap = n;
    bool swapped = false;
    const double shrink = 1.3;
    while (gap > 1 || swapped) {
        // 设置间隔
        gap = static_cast<int>(floor(gap / shrink));
        if (gap < 1) {
            gap = 1;
        }
        swapped = false;
        // 对于当前的间隔,进行排序
        for (int i = 0; i < n - gap; ++i) {
            if (arr[i] > arr[i + gap]) {
                std::swap(arr[i], arr[i + gap]);
                swapped = true;
            }
        }
    }
    // 最终进行一次冒泡排序
    for (int i = 0; i < n - 1; ++i) {
        if (arr[i] > arr[i + 1]) {
            std::swap(arr[i], arr[i + 1]);
        }
    }
}

混沌冒泡排序

混沌冒泡排序(Chaotic Bubble Sort)是一种基于冒泡排序的变体,它在比较和交换元素时引入了混沌理论的原理。混沌理论是一种研究在确定性系统中出现的看似随机或复杂行为的方法。在混沌冒泡排序中,混沌序列用于决定哪些元素进行比较和交换,而不是按照固定的顺序。

算法步骤

算法步骤如下:

  1. 生成混沌序列:首先,需要生成一个混沌序列,这个序列的长度与待排序数组的长度相同。混沌序列中的每个元素都是数组索引的一个排列,确保每个索引都会被访问到。
  2. 排序过程:使用生成的混沌序列进行排序。对于混沌序列中的每一对索引,比较对应的数组元素,如果它们的顺序错误,则交换它们。
  3. 重复排序:重复步骤2,直到没有更多的元素需要交换,即数组已经排序完成。
伪代码描述

混沌冒泡排序的伪代码如下:

procedure chaoticBubbleSort(arr: list of sortable items)
    n = length(arr)
    // 生成混沌序列
    chaoticSequence = generateChaoticSequence(n)
    // 初始化交换标志
    swapped = true
    while swapped
        // 设置交换标志为false
        swapped = false
        // 使用混沌序列进行排序
        for i = 1 to n - 1
            // 获取混沌序列中的索引
            index1 = chaoticSequence[i]
            index2 = chaoticSequence[i + 1]
            // 比较并交换元素
            if arr[index1] > arr[index2]
                swap(arr[index1], arr[index2])
                // 发生了交换,设置交换标志为true
                swapped = true
    end while
end procedure
C++模板实现

下面是使用C++模板实现的混沌冒泡排序:

#include <iostream>
#include <vector>
#include <cstdlib> // 用于生成随机数
template<typename T>
void chaoticBubbleSort(std::vector<T>& arr) {
    int n = arr.size();
    std::vector<int> chaoticSequence(n);
    bool swapped = true;
    // 生成混沌序列
    for (int i = 0; i < n; ++i) {
        chaoticSequence[i] = i;
    }
    // 混沌打乱序列
    for (int i = 0; i < n; ++i) {
        std::swap(chaoticSequence[i], chaoticSequence[rand() % n]);
    }
    while (swapped) {
        swapped = false;
        // 使用混沌序列进行排序
        for (int i = 0; i < n - 1; ++i) {
            // 获取混沌序列中的索引
            int index1 = chaoticSequence[i];
            int index2 = chaoticSequence[i + 1];
            // 比较并交换元素
            if (arr[index1] > arr[index2]) {
                std::swap(arr[index1], arr[index2]);
                swapped = true;
            }
        }
    }
}

这段代码定义了一个模板函数chaoticBubbleSort,它可以接受任何类型的可排序元素数组。在main函数中,我们创建了一个整数向量并使用chaoticBubbleSort进行排序,然后打印排序后的结果。请注意,这个实现使用了std::rand()来生成混沌序列,这并不是真正的混沌序列生成方法,而是一种简单的随机化方法。在实际应用中,可能需要使用更复杂的混沌映射函数来生成混沌序列。

奇偶排序

奇偶排序(Odd-Even Sort),也称为奇偶换位排序,是一种基于比较的排序算法,它是冒泡排序的一种变体。在奇偶排序中,排序过程分为两个阶段:奇数阶段和偶数阶段。在奇数阶段,比较所有奇数索引的元素对;在偶数阶段,比较所有偶数索引的元素对。这样交替进行,直到数组完全排序。

算法步骤

算法步骤如下:

  1. 初始化:设置一个标记变量,用于检测在上一轮排序中是否发生了元素交换。
  2. 奇数阶段:比较所有奇数索引的元素对(索引为1, 2, 3, …),如果它们的顺序错误,则交换它们。
  3. 偶数阶段:比较所有偶数索引的元素对(索引为0, 2, 4, …),如果它们的顺序错误,则交换它们。
  4. 重复步骤2和3:重复步骤2和3,直到在一次完整的奇数阶段和偶数阶段中都没有发生元素交换,这时数组已经排序完成。
伪代码描述

奇偶排序的伪代码如下:

procedure oddEvenSort(arr: list of sortable items)
    n = length(arr)
    swapped = true
    while swapped
        swapped = false
        // 奇数阶段
        for i = 1 to n - 2 by 2
            if arr[i] > arr[i + 1]
                swap(arr[i], arr[i + 1])
                swapped = true
        // 偶数阶段
        for i = 0 to n - 2 by 2
            if arr[i] > arr[i + 1]
                swap(arr[i], arr[i + 1])
                swapped = true
    end while
end procedure
C++模板代码实现

下面是使用C++模板实现的奇偶排序:

#include <iostream>
#include <vector>
template<typename T>
void oddEvenSort(std::vector<T>& arr) {
    bool swapped = true;
    int n = arr.size();
    while (swapped) {
        swapped = false;
        // 奇数阶段
        for (int i = 1; i < n - 1; i += 2) {
            if (arr[i] > arr[i + 1]) {
                std::swap(arr[i], arr[i + 1]);
                swapped = true;
            }
        }
        // 偶数阶段
        for (int i = 0; i < n - 1; i += 2) {
            if (arr[i] > arr[i + 1]) {
                std::swap(arr[i], arr[i + 1]);
                swapped = true;
            }
        }
    }
}

带扩展阅读的完整C++代码

#include <iostream>
#include <cassert>
#include <string>
#include <vector>
#include <cstdlib>

using namespace std;

template <typename T>
void bubbleSort(T arr[], int n)
{
    // Loop through the array n-1 times
    for (int i = 0; i < n - 1; i++)
    {
        // Loop through the array n-i-1 times
        for (int j = 0; j < n - i - 1; j++)
        {
            // If the element at index j is greater than the element at index j+1, swap them
            if (arr[j] > arr[j + 1])
            {
                swap(arr[j], arr[j + 1]);
            }
        }
    }
}

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;
    }

    // Now there are some get parameters function for this calss:
    const string &getName() const { return this->name; }
    int getAge() const { return this->age; }
    int getSocre() const { return this->socre; }

private:
    string name;
    int age;
    int socre;
};

// This is a unit test function for Person class.
void testPerson()
{
    Person person1("Alice", 20, 90);
    Person person2("Bob", 21, 80);
    Person person3("Charlie", 22, 85);

    // Test operator>
    assert(person1 > person2);
    assert(!(person1 > person3));

    // Test operator<
    assert(person2 < person1);
    assert(!(person3 < person1));

    // Test operator==
    assert(person1 == person1);
    assert(!(person1 == person2));

    // Test operator!=
    assert(person1 != person2);
    assert(!(person1 != person1));
}

template <typename T>
void cocktailSort(vector<T> &arr)
{
    // Initialize swapped to true to enter loop
    bool swapped = true;
    // Initialize start and end indices
    int start = 0;
    int end = arr.size() - 1;
    // Loop until all swaps are done
    while (swapped)
    {
        // Reset swapped to false
        swapped = false;
        // Loop through all elements in array
        for (int i = start; i < end; ++i)
        {
            // If element is greater than next element, swap them
            if (arr[i] > arr[i + 1])
            {
                swap(arr[i], arr[i + 1]);
                swapped = true;
            }
        }
        // If no swaps, then array is sorted
        if (!swapped)
        {
            break;
        }
        // Decrement end index
        --end;
        // Reset swapped to false
        swapped = false;
        // Loop through all elements in array
        for (int i = end - 1; i >= start; --i)
        {
            // If element is greater than next element, swap them
            if (arr[i] > arr[i + 1])
            {
                swap(arr[i], arr[i + 1]);
                swapped = true;
            }
        }
        // Increment start index
        ++start;
    }
}

template <typename T>
void combSort(vector<T> &arr)
{
    // n is the size of the array
    int n = arr.size();
    // gap is the gap between elements
    int gap = n;
    // swapped is a flag to check if any elements have been swapped
    bool swapped = false;
    // the constant value of the gap is 1.3
    const double shrink = 1.3;
    // while the gap is greater than 1 or swapped is true
    while (gap > 1 || swapped)
    {
        // gap is the new gap
        gap = static_cast<int>(floor(gap / shrink));
        // if the gap is less than 1, set it to 1
        if (gap < 1)
        {
            gap = 1;
        }
        // set swapped to false
        swapped = false;
        // loop through the array
        for (int i = 0; i < n - gap; ++i)
        {
            // if the current element is greater than the next element
            if (arr[i] > arr[i + gap])
            {
                // swap them
                swap(arr[i], arr[i + gap]);
                // set swapped to true
                swapped = true;
            }
        }
    }
    // loop through the array
    for (int i = 0; i < n - 1; ++i)
    {
        // if the current element is greater than the next element
        if (arr[i] > arr[i + 1])
        {
            // swap them
            swap(arr[i], arr[i + 1]);
        }
    }
}

template <typename T>
void chaoticBubbleSort(vector<T> &arr)
{
    // n is the size of the array
    int n = arr.size();
    // create a vector to store the chaotic sequence
    vector<int> chaoticSequence(n);
    // set swapped to true to start the loop
    bool swapped = true;
    // fill the chaotic sequence with the indices of the array
    for (int i = 0; i < n; ++i)
    {
        chaoticSequence[i] = i;
    }
    // shuffle the chaotic sequence
    for (int i = 0; i < n; ++i)
    {
        swap(chaoticSequence[i], chaoticSequence[rand() % n]);
    }
    // start the bubble sort loop
    while (swapped)
    {
        swapped = false;
        // loop through the array and compare each element to the one after it
        for (int i = 0; i < n - 1; ++i)
        {
            // store the indices of the elements
            int index1 = chaoticSequence[i];
            int index2 = chaoticSequence[i + 1];
            // if the element at the first index is greater than the one after it
            if (arr[index1] > arr[index2])
            {
                // swap them
                swap(arr[index1], arr[index2]);
                // set swapped to true to start the next loop
                swapped = true;
            }
        }
    }
}

template <typename T>
void oddEvenSort(vector<T> &arr)
{
    bool swapped = true;
    int n = arr.size();
    while (swapped)
    {
        swapped = false;
        for (int i = 1; i < n - 1; i += 2)
        {
            if (arr[i] > arr[i + 1])
            {
                swap(arr[i], arr[i + 1]);
                swapped = true;
            }
        }

        for (int i = 0; i < n - 1; i += 2)
        {
            if (arr[i] > arr[i + 1])
            {
                swap(arr[i], arr[i + 1]);
                swapped = true;
            }
        }
    }
}

void bubbleSortTestCase()
{
    // Declare an array of integers
    int arr[] = {64, 34, 25, 12, 22, 11, 90};
    // Calculate the size of the array
    int n = sizeof(arr) / sizeof(arr[0]);
    // Call the bubbleSort function to sort the array
    bubbleSort<int>(arr, n);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < n; i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;

    // Declare an array of floats
    double arr2[] = {64.5, 34.2, 25.1, 12.6, 22.8, 11.9, 90.0};
    // Calculate the size of the array
    int n2 = sizeof(arr2) / sizeof(arr2[0]);
    // Call the bubbleSort function to sort the array
    bubbleSort<double>(arr2, n2);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < n2; i++)
    {
        cout << arr2[i] << " ";
    }
    cout << endl;

    // Declare an array of characters
    char arr3[] = {'g', 'e', 'k', 'i', 't', 'c', 'h'};
    // Calculate the size of the array
    int n3 = sizeof(arr3) / sizeof(arr3[0]);
    // Call the bubbleSort function to sort the array
    bubbleSort<char>(arr3, n3);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < n3; i++)
    {
        cout << arr3[i] << " ";
    }
    cout << endl;

    testPerson();
    // Now I want to write some Person class's bubble sort examples in here:
    // Declare an array of Person objects
    Person arr4[] = {Person("John", 25, 90), Person("Alice", 30, 85), Person("Bob", 20, 78), Person("Eve", 22, 89)}; // This is a dummy Person class, you need to implement it properly.
    // Calculate the size of the array
    int n4 = sizeof(arr4) / sizeof(arr4[0]);
    // Call the bubbleSort function to sort the array
    bubbleSort<Person>(arr4, n4);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < n4; i++)
    {
        const auto &person = arr4[i];
        cout << person.getName() << " " << person.getAge() << " " << person.getSocre() << endl;
    }
    cout << endl;

    // Declare an array of Person pointers
    Person *arr5[4];
    arr5[0] = new Person("John", 25, 90);
    arr5[1] = new Person("Alice", 30, 85);
    arr5[2] = new Person("Bob", 20, 78);
    arr5[3] = new Person("Eve", 22, 89);
    // Calculate the size of the array
    int n5 = sizeof(arr5) / sizeof(arr5[0]);
    // Call the bubbleSort function to sort the array
    bubbleSort<Person *>(arr5, n5);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < n5; i++)
    {
        const auto &person = arr5[i];
        cout << person->getName() << " " << person->getAge() << " " << person->getSocre() << endl;
    }
    cout << endl;
}

void cocktailSortTestCase()
{
    // Declare an array of integers
    vector<int> arr = {64, 34, 25, 12, 22, 11, 90};
    // Call the bubbleSort function to sort the array
    cocktailSort<int>(arr);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr.size(); i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;

    // Declare an array of floats
    vector<double> arr2 = {64.5, 34.2, 25.1, 12.6, 22.8, 11.9, 90.0};
    // Call the bubbleSort function to sort the array
    cocktailSort<double>(arr2);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr2.size(); i++)
    {
        cout << arr2[i] << " ";
    }
    cout << endl;

    // Declare an array of characters
    vector<char> arr3 = {'g', 'e', 'k', 'i', 't', 'c', 'h'};
    // Call the bubbleSort function to sort the array
    cocktailSort<char>(arr3);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr3.size(); i++)
    {
        cout << arr3[i] << " ";
    }
    cout << endl;
    // Now I want to write some Person class's bubble sort examples in here:
    // Declare an array of Person objects
    vector<Person> arr4 = {Person("John", 25, 90), Person("Alice", 30, 85), Person("Bob", 20, 78), Person("Eve", 22, 89)}; // This is a dummy Person class, you need to implement it properly.
    // Call the bubbleSort function to sort the array
    cocktailSort<Person>(arr4);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr4.size(); i++)
    {
        const auto &person = arr4[i];
        cout << person.getName() << " " << person.getAge() << " " << person.getSocre() << endl;
    }
    cout << endl;
}

void combSortTestCase()
{
    // Declare an array of integers
    vector<int> arr = {64, 34, 25, 12, 22, 11, 90};
    // Call the bubbleSort function to sort the array
    combSort<int>(arr);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr.size(); i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;

    // Declare an array of floats
    vector<double> arr2 = {64.5, 34.2, 25.1, 12.6, 22.8, 11.9, 90.0};
    // Call the bubbleSort function to sort the array
    combSort<double>(arr2);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr2.size(); i++)
    {
        cout << arr2[i] << " ";
    }
    cout << endl;

    // Declare an array of characters
    vector<char> arr3 = {'g', 'e', 'k', 'i', 't', 'c', 'h'};
    // Call the bubbleSort function to sort the array
    combSort<char>(arr3);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr3.size(); i++)
    {
        cout << arr3[i] << " ";
    }
    cout << endl;
    // Now I want to write some Person class's bubble sort examples in here:
    // Declare an array of Person objects
    vector<Person> arr4 = {Person("John", 25, 90), Person("Alice", 30, 85), Person("Bob", 20, 78), Person("Eve", 22, 89)}; // This is a dummy Person class, you need to implement it properly.
    // Call the bubbleSort function to sort the array
    combSort<Person>(arr4);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr4.size(); i++)
    {
        const auto &person = arr4[i];
        cout << person.getName() << " " << person.getAge() << " " << person.getSocre() << endl;
    }
    cout << endl;
}

void chaoticButtleSortTestCase()
{
    // Declare an array of integers
    vector<int> arr = {64, 34, 25, 12, 22, 11, 90};
    // Call the bubbleSort function to sort the array
    chaoticBubbleSort<int>(arr);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr.size(); i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;

    // Declare an array of floats
    vector<double> arr2 = {64.5, 34.2, 25.1, 12.6, 22.8, 11.9, 90.0};
    // Call the bubbleSort function to sort the array
    chaoticBubbleSort<double>(arr2);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr2.size(); i++)
    {
        cout << arr2[i] << " ";
    }
    cout << endl;

    // Declare an array of characters
    vector<char> arr3 = {'g', 'e', 'k', 'i', 't', 'c', 'h'};
    // Call the bubbleSort function to sort the array
    chaoticBubbleSort<char>(arr3);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr3.size(); i++)
    {
        cout << arr3[i] << " ";
    }
    cout << endl;
    // Now I want to write some Person class's bubble sort examples in here:
    // Declare an array of Person objects
    vector<Person> arr4 = {Person("John", 25, 90), Person("Alice", 30, 85), Person("Bob", 20, 78), Person("Eve", 22, 89)}; // This is a dummy Person class, you need to implement it properly.
    // Call the bubbleSort function to sort the array
    chaoticBubbleSort<Person>(arr4);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr4.size(); i++)
    {
        const auto &person = arr4[i];
        cout << person.getName() << " " << person.getAge() << " " << person.getSocre() << endl;
    }
    cout << endl;
}

void oddEvenSortTestCase()
{
    // Declare an array of integers
    vector<int> arr = {64, 34, 25, 12, 22, 11, 90};
    // Call the bubbleSort function to sort the array
    oddEvenSort<int>(arr);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr.size(); i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;

    // Declare an array of floats
    vector<double> arr2 = {64.5, 34.2, 25.1, 12.6, 22.8, 11.9, 90.0};
    // Call the bubbleSort function to sort the array
    oddEvenSort<double>(arr2);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr2.size(); i++)
    {
        cout << arr2[i] << " ";
    }
    cout << endl;

    // Declare an array of characters
    vector<char> arr3 = {'g', 'e', 'k', 'i', 't', 'c', 'h'};
    // Call the bubbleSort function to sort the array
    oddEvenSort<char>(arr3);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr3.size(); i++)
    {
        cout << arr3[i] << " ";
    }
    cout << endl;
    // Now I want to write some Person class's bubble sort examples in here:
    // Declare an array of Person objects
    vector<Person> arr4 = {Person("John", 25, 90), Person("Alice", 30, 85), Person("Bob", 20, 78), Person("Eve", 22, 89)}; // This is a dummy Person class, you need to implement it properly.
    // Call the bubbleSort function to sort the array
    oddEvenSort<Person>(arr4);
    // Print the sorted array
    cout << "Sorted array: \n";
    for (int i = 0; i < arr4.size(); i++)
    {
        const auto &person = arr4[i];
        cout << person.getName() << " " << person.getAge() << " " << person.getSocre() << endl;
    }
    cout << endl;
}

int main()
{
    testPerson();
    bubbleSortTestCase();
    cocktailSortTestCase();
    combSortTestCase();
    chaoticButtleSortTestCase();
    oddEvenSortTestCase();
    return 0;
}

个人格言

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

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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MATLAB】 LMD信号分解+FFT傅里叶频谱变换组合算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 展示出图效果 1 LMD分解算法 LMD (Local Mean Decomposition) 分解算法是一种信号分解算法&#xff0c;它可以将一个信号分解成多个局部平滑的成分&#xff0c;并且可以将高频噪声和低频信号有效地分离出来。LMD 分解算…

消息中间件篇之RabbitMQ-消息不丢失

一、生产者确认机制 RabbitMQ提供了publisher confirm机制来避免消息发送到MQ过程中丢失。消息发送到MQ以后&#xff0c;会返回一个结果给发送者&#xff0c;表示消息是否处理成功。 当消息没有到交换机就失败了&#xff0c;就会返回publish-confirm。当消息没有到达MQ时&…

打开 Camera app 出图,前几帧图像偏暗、偏色该怎样去避免?

1、问题背景 使用的安卓平台&#xff0c;客户的应用是要尽可能快的获取到1帧图像效果正常的图片。 但当打开 camera 启动出流后&#xff0c;前3-5帧图像是偏暗、偏色的&#xff0c;如下图所示&#xff0c;是抓取出流的前25帧图像&#xff0c; 前3帧颜色是偏蓝的&#xff0c;…

[嵌入式系统-33]:RT-Thread -18- 新手指南:三种不同的版本、三阶段学习路径

目录 前言&#xff1a;学习路径&#xff1a;入门学习-》进阶段学习》应用开发 一、RT-Thread版本 1.1 标准版 1.2 Nano 1.3 Smart版本 1.4 初学者制定学习路线 1.5 RT-Thread在线文档中心目录结构 1.6 学习和使用RT-Thread的三种场景 二、入门学习阶段&#xff1a;内…

架构设计:微服务架构实践

引言 前段时间做项目的时候有客户问到过我&#xff0c;什么微服务&#xff1f;微服务是一种架构风格&#xff0c;其中软件系统被构建为一组小型服务&#xff0c;每个服务都运行在自己的进程中并使用轻量级通信机制&#xff08;如HTTP或消息队列&#xff09;进行通信。这些服务…

Spring Boot与Netty:构建高性能的网络应用

点击下载《Spring Boot与Netty&#xff1a;构建高性能的网络应用》 1. 前言 本文将详细探讨如何在Spring Boot应用中集成Netty&#xff0c;以构建高性能的网络应用。我们将首先了解Netty的原理和优势&#xff0c;然后介绍如何在Spring Boot项目中集成Netty&#xff0c;包括详…

代码随想录算法训练营第三天

● 自己看到题目的第一想法 203.移除链表元素 方法一&#xff1a; 思路&#xff1a; 设置虚拟头节点 dummyhead 设置临时指针 cur 遍历 整个链表 循环&#xff1a; 如果 cur !nullptr &&cur->next !nullptr 则 遍历链表 否则结束遍历 如果 cur->next val 则…

C++ //练习 8.4 编写函数,以读模式打开一个文件,将其内容读入到一个string的vector中,将每一行作为一个独立的元素存于vector中。

C Primer&#xff08;第5版&#xff09; 练习 8.4 练习 8.4 编写函数&#xff0c;以读模式打开一个文件&#xff0c;将其内容读入到一个string的vector中&#xff0c;将每一行作为一个独立的元素存于vector中。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09…

装修避坑干货|阳台洗衣柜洗衣机一体柜设计。福州中宅装饰,福州装修

装修的时候常常会在洗衣柜中嵌入洗衣机&#xff0c;其实阳台柜的安装并不像看起来的那么简单&#xff0c;下面给大家说说几个注意事项‼️ 01.水电位置 在安装阳台柜之前&#xff0c;务必确认水电管道的位置。确保阳台柜不会阻碍水电管道的使用&#xff0c;以免造成不必要的麻…

U盘乱码与文件丢失:恢复指南与预防策略

U盘乱码文件丢失是一种常见的技术问题&#xff0c;通常表现为存储在U盘中的文件名显示为不可识别的字符或文件无法正常打开&#xff0c;有时甚至文件会完全消失。这种情况可能由多种原因引起&#xff0c;包括但不限于文件系统损坏、不正确的拔插操作、病毒感染、兼容性问题等。…

花生壳内网穿透教程(图文并茂)

目录 前言&#xff1a; 使用教程&#xff1a; 1.注册账号 2.软件下载及安装&#xff1a; 3.账号绑定及花生壳的使用 4.内网穿透的配置&#xff08;重点&#xff09; 4.2 新增映射页面&#xff1a; 4.3 上面几种映射的区别&#xff1a; 4.4 上面TCP类型的区别&#xff1a;…

Linux进程信号 ----- (信号保存)

前言 信号从产生到执行&#xff0c;并不会被立即处理&#xff0c;这就意味着需要一种 “方式” 记录信号是否产生&#xff0c;对于 31 个普通信号来说&#xff0c;一个 int 整型就足以表示所有普通信号的产生信息了&#xff1b;信号还有可能被 “阻塞”&#xff0c;对于这种多状…

鸿蒙中的九种布局概述

鸿蒙中的九种布局概述 概述 鸿蒙开发中包含就种布局&#xff0c;分别为线性布局、层叠布局、弹性布局、相对布局、栅格布局、媒体布局、列表、网格、轮播。 线性布局 线性布局通过Row和Column进行构建&#xff0c;是其他布局的基础。其中Row是水平方向排列&#xff0c;Colu…

电路设计(25)——4位数字频率计的multisim仿真及PCB设计

1.设计要求 使用4位数码管&#xff0c;显示输入信号的频率。完成功能仿真后&#xff0c;用AD软件&#xff0c;画出原理图以及PCB。 2.电路设计 输入信号的参数为&#xff1a; 可见&#xff0c;输入为168HZ&#xff0c;测量值为170HZ&#xff0c;误差在可接受的范围内。 3.PCB设…

Jenkins解决Host key verification failed (2)

Jenkins解决Host key verification failed 分析原因情况 一、用OpenSSH的人都知ssh会把你每个你访问过计算机的公钥(public key)都记录在~/.ssh/known_hosts。当下次访问相同计算机时&#xff0c;OpenSSH会核对公钥。如果公钥不同&#xff0c;OpenSSH会发出警告&#xff0c;避免…

【Java程序设计】【C00299】基于Springboot的仓库管理系统(有论文)

基于Springboot的仓库管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的仓库管理系统&#xff0c;本系统有管理员角色权限&#xff1b; 系统整体功能有&#xff1a;个人信息管理、仓库管理、物资管理、物资…

matplotlib子图绘制

文章目录 子图组合网格布局GridSpec matplotlib教程&#xff1a; 初步 子图 从绘图流程出发&#xff0c;【plt】图像有三个层级&#xff0c;依次是窗口、坐标系以及图像。在一个坐标系中可以有多条曲线&#xff0c;即表示多个图像&#xff1b;相应地在一个窗口中&#xff0c;…

文心一言 VS 讯飞星火 VS chatgpt (201)-- 算法导论15.2 6题

六、用go语言&#xff0c;证明&#xff1a;对 n 个元素的表达式进行完全括号化&#xff0c;恰好需要 n-1 对括号。 文心一言&#xff0c;代码正常运行&#xff1a; 在Go语言中&#xff0c;证明对n个元素的表达式进行完全括号化恰好需要n-1对括号&#xff0c;可以通过数学归纳…

将yolov8权重文件转为onnx格式并在c#中使用

yolo模型转ONNX 在yolov8中&#xff0c;我们将训练结果的.pt权重文件转换为onnx格式只需要使用ultralytics库中的YOLO类&#xff0c;使用pip安装ultralytics库&#xff0c;然后执行下面python代码 from ultralytics import YOLO# 加载YOLOv8模型 model YOLO("best.pt&q…

听力障碍的康复训练方法有哪些?

康复小知识 回声复语教育科技研究院 知识分享 听力障碍/概况 听力障碍是指“由于各种原因导致双耳不同程度的永久性听力障碍&#xff0c;听不到或听不清周围环境及言语声&#xff0c;以致影响日常生活和社会参与”。 聋儿的语言器官本身并不存在问题&#xff0c;通过现代科学…