冒泡排序是计算机科学中最简单的排序算法之一。它以每次迭代时较小的元素“冒泡”到列表顶部的方式命名,是教授排序算法基础知识的绝佳工具。虽然对于大型数据集来说不是最有效的,但它的简单性使其成为理解排序算法如何工作的一个很好的起点。
冒泡排序的工作原理是重复遍历列表,比较相邻元素,如果顺序错误则交换它们。重复此过程,直到不再需要交换为止,表明列表已排序。
这是一步一步的细分:
让我们可视化这个过程:
录制的 gif 来自 https://visualgo.net/en/sorting
让我们研究一下 JavaScript 中冒泡排序的三种实现,每种实现的优化级别都在增加。
function bubbleSort(list) { // Outer loop: iterate through the entire list for (let i = 0; i < list.length - 1; i++) { // Inner loop: compare adjacent elements for (let j = 0; j < list.length - 1; j++) { // If the current element is greater than the next one if (list[j] > list[j + 1]) { // Swap the elements using destructuring assignment [list[j], list[j + 1]] = [list[j + 1], list[j]]; } } } // Return the sorted list return list; }
这个基本实现使用嵌套循环来比较和交换相邻元素。外循环确保我们对数组进行了足够的遍历,而内循环则执行比较和交换。
function bubbleSort(list) { // Outer loop: iterate through the entire list for (let i = 0; i < list.length - 1; i++) { // Flag to check if any swaps occurred in this pass let swapped = false; // Inner loop: compare adjacent elements for (let j = 0; j < list.length - 1; j++) { // If the current element is greater than the next one if (list[j] > list[j + 1]) { // Swap the elements using destructuring assignment [list[j], list[j + 1]] = [list[j + 1], list[j]]; // Set the swapped flag to true swapped = true; } } // If no swaps occurred in this pass, the list is sorted if (!swapped) { break; // Exit the outer loop early } } // Return the sorted list return list; }
此版本引入了交换标志来检查一次传递中是否进行了任何交换。如果没有发生交换,则列表已经排序,我们可以提前跳出循环。
function bubbleSort(list) { // Outer loop: iterate through the entire list for (let i = 0; i < list.length - 1; i++) { // Flag to check if any swaps occurred in this pass let swapped = false; // Inner loop: compare adjacent elements // Note: We reduce the upper bound by i in each pass for (let j = 0; j < list.length - 1 - i; j++) { // If the current element is greater than the next one if (list[j] > list[j + 1]) { // Swap the elements using destructuring assignment [list[j], list[j + 1]] = [list[j + 1], list[j]]; // Set the swapped flag to true swapped = true; } } // If no swaps occurred in this pass, the list is sorted if (!swapped) { break; // Exit the outer loop early } } // Return the sorted list return list; }
最终的优化在每次传递中将内部循环的范围减少了 i。这是因为每次传递后,最大的未排序元素“冒泡”到数组末尾的正确位置。
冒泡排序的性能特点如下:
时间复杂度:
空间复杂度:O(1) - 冒泡排序是一种就地排序算法,仅需要恒定量的额外内存。
与快速排序(平均 O(n log n))或合并排序(O(n log n))等更高级的算法相比,冒泡排序的二次时间复杂度使其对于大型数据集效率低下。
优点:
缺点:
鸡尾酒排序,也称为鸡尾酒摇排序或双向冒泡排序,是冒泡排序的改进版本。它双向遍历列表,有助于更有效地将元素移动到正确的位置。
Cocktail Sort is particularly useful in cases where the array has elements that are initially large at the beginning and small at the end, as it can reduce the total number of passes needed compared to traditional Bubble Sort.
Here's a visualization of Cocktail Sort:
Visual from Wikipedia: https://en.wikipedia.org/wiki/Cocktail_shaker_sort
function cocktailSort(list) { let swapped; // The do...while loop ensures the sorting continues until no swaps are needed do { // Reset the swapped flag at the beginning of each complete iteration swapped = false; // First pass: left to right (like standard bubble sort) for (let i = 0; i < list.length - 1; i++) { // If the current element is greater than the next, swap them if (list[i] > list[i + 1]) { [list[i], list[i + 1]] = [list[i + 1], list[i]]; // Mark that a swap occurred swapped = true; } } // If no swaps occurred in the first pass, the array is sorted if (!swapped) { break; // Exit the do...while loop early } // Reset the swapped flag for the second pass swapped = false; // Second pass: right to left (this is what makes it "cocktail" sort) for (let i = list.length - 2; i >= 0; i--) { // If the current element is greater than the next, swap them if (list[i] > list[i + 1]) { [list[i], list[i + 1]] = [list[i + 1], list[i]]; // Mark that a swap occurred swapped = true; } } // The loop will continue if any swaps occurred in either pass } while (swapped); // Return the sorted list return list; }
This implementation alternates between forward and backward passes through the list, potentially reducing the number of iterations needed to sort the array.
While Bubble Sort isn't typically used in production environments for large-scale applications, it can still find use in certain scenarios:
Bubble Sort, despite its inefficiencies with large datasets, offers valuable insights into the world of sorting algorithms and algorithm analysis. Its straightforward approach makes it an excellent teaching tool for beginners in computer science.
Key takeaways are:
While you're unlikely to use Bubble Sort in production code for large-scale applications, the principles behind it are fundamental to many algorithms. The process of optimizing Bubble Sort teaches valuable lessons about algorithm improvement, serving as a stepping stone to more advanced computational problem-solving.
When it comes to algorithms, there's rarely a one-size-fits-all solution. The best algorithm for a given task depends on the specific requirements, constraints, and characteristics of your data. Bubble Sort, with all its limitations, still has its place in this diverse algorithmic ecosystem.
以上是使用 Javascript 进行算法之旅 - 冒泡排序的详细内容。更多信息请关注PHP中文网其他相关文章!