<使用生成式AI对四种冒泡排序实现形式分析解释的探讨整理>
文章目录
前言:在笔者学习的不同时期阶段,曾遇到多种冒泡排序算法的实现形式,这些形式纷繁多样,在一定时期阶段带给笔者些许疑惑,然而通过深入学习理解之后,发现其本质却都满足冒泡排序算法的思想和基本定义。对其归纳总结所得四种冒泡排序算法实现形式使用生成式AI进行分析解释探讨整理。
1.冒泡排序实现形式总结
//冒泡排序实现1——不常用(这个版本两层for循环分别是i++、j++)voidbubbleSort(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--)//交换voidswap(int&a,int&b){int temp = a;
a = b;
b = temp;}//冒泡排序voidbubbleSort(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++)voidbubbleSort(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++)voidbubbleSort(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进行无引导分析:
//排序实现1voidSort(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//交换voidswap(int&a,int&b){int temp = a; a = b; b = temp;}//排序voidSort(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;// 本趟遍历后没有发生交换,说明表已经有序}}//排序实现3voidSort(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;}}}}//排序实现4voidSort(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(通义千问)给出的传统冒泡排序和优化后的冒泡排序
//传统冒泡排序//传统冒泡排序的基本思想是通过多次遍历数组,每次将相邻的两个元素进行比较并交换,使得每一轮遍历后最大的元素“冒泡”到数组的末尾。#include<iostream>usingnamespace std;// 传统冒泡排序voidBubbleSortTraditional(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;}}}}// 主函数,用于测试排序功能intmain(){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;return0;}//优化后的冒泡排序//优化后的冒泡排序增加了早期退出机制。如果在某一轮遍历中没有发生任何交换,说明数组已经有序,可以提前结束排序。#include<iostream>usingnamespace std;// 交换函数voidswap(int&a,int&b){int temp = a;
a = b;
b = temp;}// 优化后的冒泡排序voidBubbleSortOptimized(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;// 提前退出}}}// 主函数,用于测试排序功能intmain(){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;return0;}
观察发现主要算法逻辑是不是同实现4一样? 因为即使是其它AI的解释答案,也是建立在网络搜索基础之上…
总结:应该按照各种排序的定义区分相应排序类型。俗话说:“尽信书,不如无书”,迁移到此处就是“尽信AI,不如多理解”。在当今,其实应该辩证的使用AI工具,不能全然依托AI,而是将其作为辅助,同时自身也要多去学习,提升自身的判断和理解。
后记:由于时间仓促,上述探讨在整理过程中亦有思维逻辑有误之处,然而在计算机这类学科中,“定义”不是绝对的衡量标尺,笔者更是在计算机研究生全国统考408的《数据结构》、《操作系统》、《计算机网络》、《计算机组成原理》的学习中就有深刻体会。因此,世间纷繁、事事接踵绵延,应抓住主要矛盾,有时切不能再耗费大量精力在一些琐事之上了…
此刻已是10月1日凌晨3点33分。今天正值祖国成立75周年,笔者在此向祖国致以最诚挚最衷心的祝福与敬意!向无数前辈致以崇高的敬意!中华人民共和国万岁!世界人民大团结万岁!
版权归原作者 新晓·故知 所有, 如有侵权,请联系我们删除。