<使用生成式AI对四种冒泡排序实现形式分析解释的探讨整理>

<使用生成式AI对四种冒泡排序实现形式分析解释的探讨整理>

文章目录

前言:在笔者学习的不同时期阶段,曾遇到多种冒泡排序算法的实现形式,这些形式纷繁多样,在一定时期阶段带给笔者些许疑惑,然而通过深入学习理解之后,发现其本质却都满足冒泡排序算法的思想和基本定义。对其归纳总结所得四种冒泡排序算法实现形式使用生成式AI进行分析解释探讨整理。

1.冒泡排序实现形式总结

cpp 复制代码
//冒泡排序实现1------不常用(这个版本两层for循环分别是i++、j++)
void bubbleSort(int A[], int n) {
    int i, j, temp; // 声明三个整型变量i、j和temp用于循环控制和交换元素
    for (i = 0; i < n - 1; i++) { // 外层循环,从数组的第一个元素开始遍历到倒数第二个元素
        for (j = i+1; j < n; j++) { // 内层循环,从当前外层循环位置的下一个元素开始遍历到最后一个元素
            if (A[i] > A[j]) { // 如果当前元素大于下一个元素
                temp = A[i]; // 将当前元素存储到临时变量temp中
                A[i] = A[j]; // 将下一个元素赋值给当前元素
                A[j] = temp; // 将临时变量temp的值(原当前元素的值)赋值给下一个元素
            }
        }
    }
}

//冒泡排序实现2------王道考研指导书及课件(这个版本两层for循环分别是i++、j--)
//交换
void swap(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}
//冒泡排序
void bubbleSort(int A[], int n) {
    for (int i = 0; i < n - 1; i++) {
        bool flag = false; // 表示本趟冒泡是否发生交换的标志
        for (int j = n - 1; j > i; j--) { // 一趟冒泡过程
            if (A[j - 1] > A[j]) { // 若为逆序
                swap(A[j - 1], A[j]); // 交换
                flag = true;
            }
        }
        if (flag == false)
            return; // 本趟遍历后没有发生交换,说明表已经有序
    }
}

//冒泡排序实现3------不常用(这个版本两层for循环分别是i--、j++)
void bubbleSort(int A[], int n) {
    for (int i = n - 1; i > 1; i--) {
        for (int j = 1; j < i; j++) {
            if (A[j] > A[j + 1]) {
                int temp = A[j];
                A[j] = A[j + 1];
                A[j + 1] = temp;
            }
        }
    }
}

//冒泡排序实现4------典型(或标准)冒泡排序,未优化(这个版本两层for循环分别是i++、j++)
void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        // 一趟冒泡排序的过程
        for (int j = 0; j < n - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                // 交换
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}
//注:上述除了实现2之外,均为未优化的冒泡排序
//实现2 在冒泡排序的基础上增加了一个优化,即通过标志位 flag 来判断在某一趟排序过程中是否发生了元素交换。如果在某趟排序过程中没有发生任何交换,说明数组已经有序,可以提前结束排序过程。这种优化在最好情况下(输入数组已经有序)可以将时间复杂度降低到 O(n),但在最坏情况下(逆序数组)时间复杂度仍然是 O(n^2)。即总结:A.包含了一个早期退出机制(flag变量),可以在数组已经有序的情况下提前结束排序。B:减少了不必要的比较和交换操作。
//相比之下,实现1、3和4都是一般的冒泡排序或其变种实现形式,它们的时间复杂度在所有情况下都是 O(n^2)。因此,从理论上讲,实现2在最好情况下比实现1、3和4更优。
//然而,在实际应用中,这种优化带来的性能提升可能并不明显,因为大多数情况下输入数据不会是完全有序的。此外,这种优化也增加了代码的复杂性。因此,是否使用实现2 取决于具体的应用场景和需求。在某些情况下,简单的标准冒泡排序可能已经足够满足需求。
//空间复杂度:所有的实现都具有O(1)的空间复杂度,因为它们只使用了常数级的额外空间。
1.1关于冒泡排序实现形式1的来源:

通义千问回答:

该解释比较有说服力。

讯飞星火回答:

该解释有些不全面。

ChatGPT-4o回答:

该解释比较有说服力(与通义千问解释近似)。

1.2对四种排序实现形式使用AI进行无引导分析:
cpp 复制代码
//排序实现1
void Sort(int A[], int n) {
int i, j, temp; // 声明三个整型变量i、j和temp用于循环控制和交换元素
for (i = 0; i < n - 1; i++) { // 外层循环,从数组的第一个元素开始遍历到倒数第二个元素
  for (j = i+1; j < n; j++) { // 内层循环,从当前外层循环位置的下一个元素开始遍历到最后一个元素
      if (A[i] > A[j]) { // 如果当前元素大于下一个元素
          temp = A[i]; // 将当前元素存储到临时变量temp中
          A[i] = A[j]; // 将下一个元素赋值给当前元素
          A[j] = temp; // 将临时变量temp的值(原当前元素的值)赋值给下一个元素
      }
  }
}
}

//排序实现2
//交换
void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
//排序
void Sort(int A[], int n) {
for (int i = 0; i < n - 1; i++) {
  bool flag = false; 
  for (int j = n - 1; j > i; j--) { 
      if (A[j - 1] > A[j]) { // 若为逆序
          swap(A[j - 1], A[j]); // 交换
          flag = true;
      }
  }
  if (flag == false)
      return; // 本趟遍历后没有发生交换,说明表已经有序
}
}
//排序实现3
void Sort(int A[], int n) {
for (int i = n - 1; i > 1; i--) {
  for (int j = 1; j < i; j++) {
      if (A[j] > A[j + 1]) {
          int temp = A[j];
          A[j] = A[j + 1];
          A[j + 1] = temp;
      }
  }
}
}

//排序实现4
void Sort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
  for (int j = 0; j < n - 1 - i; j++) {
      if (arr[j] > arr[j + 1]) {
          int tmp = arr[j];
          arr[j] = arr[j + 1];
          arr[j + 1] = tmp;
      }
  }
}
}
请详细分析上述四个算法实现,分别逐行解释?分别属于哪种排序?并分析时间复杂度和空间复杂度?以及各自的优缺点,总结和对比四种算法实现。

ChatGPT-4o:

该分析较为有说服力!但对算法类型的总结有误!

讯飞星火:

该解释尚可!主要不够详细!

通义千问:

该解释尚可!但其认为实现1为选择排序,然后询问其"是否满足选择排序的定义"之后,又给出前后矛盾的解释!

对于上述四种实现形式三种AI给出的解释分析总结:

(1)通义千问和ChatGPT-4o首先认为实现1为选择排序的变种,在质问"符合哪种排序定义"之后,两者均改称其为冒泡排序的变种,给出的解释前后矛盾,多次从不同角度询问,其回答左右摇摆!

(2)讯飞星火坚称四种实现均属于冒泡排序,只是实现的形式不同。(注:这些实现形式是笔者在不同的学习阶段遇到,在此汇总探讨整理,笔者较认可讯飞星火的解释)

一些关于冒泡排序不同实现形式在不同AI的分析回答详情:(链接如下)

通义千问-关于冒泡排序几种不同实现分析2024/10/01

讯飞星火-关于冒泡排序几种不同实现分析2024/10/01

ChatGPT-4o(科学上网打开)-关于冒泡排序几种不同实现分析2024/10/01

注:上述问答是笔者在进行多次实验之后汇总整理(即经过多次实验),可以感受到笔者被其分析解释的前后矛盾,左右摇摆带来的无奈与折腾。

1.3AI(通义千问)给出的传统冒泡排序和优化后的冒泡排序
cpp 复制代码
//传统冒泡排序
//传统冒泡排序的基本思想是通过多次遍历数组,每次将相邻的两个元素进行比较并交换,使得每一轮遍历后最大的元素"冒泡"到数组的末尾。
#include <iostream>
using namespace std;

// 传统冒泡排序
void BubbleSortTraditional(int A[], int n) {
    for (int i = 0; i < n - 1; i++) { // 外层循环,从第一个元素到倒数第二个元素
        for (int j = 0; j < n - 1 - i; j++) { // 内层循环,从第一个元素到未排序部分的倒数第二个元素
            if (A[j] > A[j + 1]) { // 如果当前元素大于下一个元素
                // 交换
                int temp = A[j];
                A[j] = A[j + 1];
                A[j + 1] = temp;
            }
        }
    }
}

// 主函数,用于测试排序功能
int main() {
    int A[] = {64, 34, 25, 12, 22, 11, 90};
    int n = sizeof(A) / sizeof(A[0]);

    cout << "Original array: ";
    for (int i = 0; i < n; ++i) {
        cout << A[i] << " ";
    }
    cout << endl;

    BubbleSortTraditional(A, n);

    cout << "Sorted array: ";
    for (int i = 0; i < n; ++i) {
        cout << A[i] << " ";
    }
    cout << endl;

    return 0;
}
//优化后的冒泡排序
//优化后的冒泡排序增加了早期退出机制。如果在某一轮遍历中没有发生任何交换,说明数组已经有序,可以提前结束排序。
#include <iostream>
using namespace std;

// 交换函数
void swap(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}

// 优化后的冒泡排序
void BubbleSortOptimized(int A[], int n) {
    for (int i = 0; i < n - 1; i++) { // 外层循环,从第一个元素到倒数第二个元素
        bool swapped = false; // 标志变量,用于检测本轮是否有交换
        for (int j = 0; j < n - 1 - i; j++) { // 内层循环,从第一个元素到未排序部分的倒数第二个元素
            if (A[j] > A[j + 1]) { // 如果当前元素大于下一个元素
                swap(A[j], A[j + 1]); // 交换
                swapped = true; // 设置标志变量
            }
        }
        if (!swapped) { // 如果本轮没有发生交换,说明数组已经有序
            break; // 提前退出
        }
    }
}

// 主函数,用于测试排序功能
int main() {
    int A[] = {64, 34, 25, 12, 22, 11, 90};
    int n = sizeof(A) / sizeof(A[0]);

    cout << "Original array: ";
    for (int i = 0; i < n; ++i) {
        cout << A[i] << " ";
    }
    cout << endl;

    BubbleSortOptimized(A, n);

    cout << "Sorted array: ";
    for (int i = 0; i < n; ++i) {
        cout << A[i] << " ";
    }
    cout << endl;

    return 0;
}

观察发现主要算法逻辑是不是同实现4一样? 因为即使是其它AI的解释答案,也是建立在网络搜索基础之上...


总结:应该按照各种排序的定义区分相应排序类型。俗话说:"尽信书,不如无书",迁移到此处就是"尽信AI,不如多理解"。在当今,其实应该辩证的使用AI工具,不能全然依托AI,而是将其作为辅助,同时自身也要多去学习,提升自身的判断和理解。
后记:由于时间仓促,上述探讨在整理过程中亦有思维逻辑有误之处,然而在计算机这类学科中,"定义"不是绝对的衡量标尺,笔者更是在计算机研究生全国统考408的《数据结构》、《操作系统》、《计算机网络》、《计算机组成原理》的学习中就有深刻体会。因此,世间纷繁、事事接踵绵延,应抓住主要矛盾,有时切不能再耗费大量精力在一些琐事之上了...

此刻已是10月1日凌晨3点33分。今天正值祖国成立75周年,笔者在此向祖国致以最诚挚最衷心的祝福与敬意!向无数前辈致以崇高的敬意!中华人民共和国万岁!世界人民大团结万岁!

相关推荐
IT19956 分钟前
Docker笔记-Docker磁盘空间清理
笔记·docker·eureka
发奋图强强强26 分钟前
10/1 力扣 49.字母异位词分组
算法·leetcode·职场和发展
不拱地的猪40 分钟前
想知道为什么有DICOM格式,YAML格式,XML格式,JSON格式吗?
xml·java·c++·opencv·json
yi碗汤园1 小时前
【一文读懂】C#如何实现通用的排序功能
开发语言·数据结构·算法·c#
AutoAutoJack1 小时前
C# 字符串(String)的应用说明一
开发语言·数据结构·算法·架构·c#
熙曦Sakura1 小时前
【算法竞赛】堆
算法
master cat1 小时前
C++中数据类型的大小
开发语言·c++
工一木子1 小时前
十大排序算法集锦
数据结构·算法·排序算法
不是编程家2 小时前
C++第五讲(2):STL--string--string的模拟实现+知识加餐
开发语言·c++·算法
仟濹2 小时前
原来还有【快速排序】 qsort() 函数
java·c语言·开发语言·数据结构·python·学习·算法