LeetCode-多語言實現冒泡排序以及算法優化改進

目錄

一、冒泡排序算法

二、應用場景/前提條件

🌈 優點

📢 缺點

三、經典算法實現并優化改進

方法一:記錄最后一次交換位置,下一輪只遍歷到該位置

方法二:添加標志位跟蹤是否發生交換,無交換則提前終止(針對大部分有序的數組)

方法三 :雞尾酒排序(雙向冒泡排序)

四、習題演練

測驗


一、冒泡排序算法

????????冒泡排序(Bubble Sort)是一種簡單直觀的排序算法,其基本思想是:在待排序的一組數中,將相鄰的兩個數進行比較,若前面的數比后面的數大就交換兩數,否則不交換;如此重復遍歷下去,直到沒有再需要交換的元素,最終完成排序。由此可得,在排序過程中,大的數據往下沉,小的數據往上浮,就像水中氣泡上升一樣,于是將這種排序算法形象地稱為冒泡排序。

時間復雜度: 最佳 O(n) | 平均 O(n2) | 最差 O(n2)

空間復雜度: O(1)

穩定性:穩定(相等元素不交換)

二、應用場景/前提條件

  • 適用于小規模數據
  • 對幾乎已排序的數據效率較高

🌈 優點

  • 代碼簡單,容易實現
  • 適合小規模數據排序
  • 對于幾乎已經排好序的數據,效率較高
  • 穩定的排序算法

📢 缺點

  • 時間復雜度高,為O(n2)
  • 隨著元素數量增加,效率急劇下降
  • 每次只能將一個元素移動到其最終位置,效率不高

三、經典算法實現并優化改進

相較于傳統的實現方法來說,有幾個可以優化的點,以下使用JS實現演示:

方法一:記錄最后一次交換位置,下一輪只遍歷到該位置

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>JavaScript 冒泡排序</title>
</head>
<script>function bubbleSort(arr) {let i = arr.length - 1;//設置初始比較范圍到數組末尾while(i > 0){ // 外層循環控制排序輪數,當i = 0時,表示沒有發生交換,排序完成let position = 0;for (let j = 0; j < i; j++) { // 遍歷未排序部分if(arr[j] > arr[ j+ 1]){ // 比較相鄰元素position = j; //記錄最后一次交換的位置let temp = arr[j + 1];arr[j + 1] = arr[j];arr[j] = temp; // 使用臨時變量temp交換兩個元素的位置}}i = position; // 下一輪只需比較到上次最后交換的位置,后續每輪都會將當前未排序部分的最大值"冒泡"到正確位置,比較范圍逐漸縮小(由i = position控制)console.log(arr.toString());}return arr;}let array = [59 , 34 , 25 , 67 ,15 ,87 ,10 ,99 ,3 ,45]let res_arr = bubbleSort(array)console.log("使用冒泡排序算法的最終排序結果是:"+ res_arr)
</script>
</html>

初始數組:[59, 34, 25, 67, 15, 87, 10, 99, 3, 45]

第1輪遍歷(i=9):

  • 比較59和34 → 交換 → [34,59,25,67,15,87,10,99,3,45]
  • 比較59和25 → 交換 → [34,25,59,67,15,87,10,99,3,45]
  • 比較59和67 → 不交換
  • 比較67和15 → 交換 → [34,25,59,15,67,87,10,99,3,45]
  • 比較67和87 → 不交換
  • 比較87和10 → 交換 → [34,25,59,15,67,10,87,99,3,45]
  • 比較87和99 → 不交換
  • 比較99和3 → 交換 → [34,25,59,15,67,10,87,3,99,45]
  • 比較99和45 → 交換 → [34,25,59,15,67,10,87,3,45,99]
    最后一次交換位置:8(99和45交換的位置)

第2輪遍歷(i=8):

  • 比較34和25 → 交換 → [25,34,59,15,67,10,87,3,45,99]
  • 比較34和59 → 不交換
  • 比較59和15 → 交換 → [25,34,15,59,67,10,87,3,45,99]
  • 比較59和67 → 不交換
  • 比較67和10 → 交換 → [25,34,15,59,10,67,87,3,45,99]
  • 比較67和87 → 不交換
  • 比較87和3 → 交換 → [25,34,15,59,10,67,3,87,45,99]
  • 比較87和45 → 交換 → [25,34,15,59,10,67,3,45,87,99]
    最后一次交換位置:7(87和45交換的位置)

依次類推.......

第7輪遍歷(i=2):

  • 比較10和15 → 不交換
  • 比較15和3 → 交換 → [10,3,15,25,34,45,59,67,87,99]
    最后一次交換位置:1(15和3交換的位置)

第8輪遍歷(i=1):

  • 比較10和3 → 交換 → [3,10,15,25,34,45,59,67,87,99]
    最后一次交換位置:0(10和3交換的位置)

最終排序結果:[3,10,15,25,34,45,59,67,87,99]

整個過程共進行了8輪遍歷,每次遍歷都會將當前未排序部分的最大值"冒泡"到正確位置。隨著排序的進行,需要比較的元素越來越少,效率逐漸提高。(這段代碼的優化在于記錄了最后一次交換的位置,避免了不必要的比較,提高了效率。每次循環后都會打印當前數組狀態,方便觀察排序過程。)

方法二:添加標志位跟蹤是否發生交換,無交換則提前終止(針對大部分有序的數組)

function optimizedBubbleSort(arr) {const n = arr.length;for (let i = 0; i < n - 1; i++) {let swapped = false;for (let j = 0; j < n - i - 1; j++) {if (arr[j] > arr[j + 1]) {[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];swapped = true;}}// 如果沒有交換操作,數組已排序完成if (!swapped) break;}return arr;
}

方法三 :雞尾酒排序(雙向冒泡排序)

雞尾酒排序是冒泡排序的一種變體,它從低到高然后從高到低來回排序,比冒泡排序的效率稍微高一點,在每次排序中進行正向和反向兩遍冒泡的方法一次可以得到兩個最終值(最大值和最小值),從而使排序次數幾乎減少了一半。


<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>JavaScript 雙向冒泡排序</title>
</head>
<script>function bubbleSort(arr) {let low = 0;let high = arr.length - 1;let temp;while (low < high) {// 正向遍歷:找最大值for (let j = low; j < high; j++) {if (arr[j] > arr[j + 1]) {temp = arr[j + 1];arr[j + 1] = arr[j];arr[j] = temp;}}--high;console.log("正向結果:" + arr.toString());// 反向遍歷:找最小值for (let j = high; j > low; j--) {if (arr[j] < arr[j - 1]) {temp = arr[j - 1];arr[j - 1] = arr[j];arr[j] = temp;}}++low;console.log("反向結果:" + arr.toString());}return arr;}let array = [59, 34, 25, 67, 15, 87, 10, 99, 3, 45];let res_arr = bubbleSort(array);console.log("最終排序結果:" + res_arr);
</script>
</html>

以下是數組?[59, 34, 25, 67, 15, 87, 10, 99, 3, 45]?的完整雞尾酒手動排序過程:


?排序過程?

  1. ?初始數組?
    [59, 34, 25, 67, 15, 87, 10, 99, 3, 45]

  2. ?第1輪正向遍歷?(從左到右找最大值)

    • 比較并交換:59?34, 59?25, 59?67(不交換), 67?15, 67?87(不交換), 87?10, 87?99(不交換), 99?3, 99?45
    • ?結果?:[34, 25, 59, 15, 67, 10, 87, 3, 45, 99](最大值99到末尾)
  3. ?第1輪反向遍歷?(從右到左找最小值)

    • 比較并交換:45?3, 45?87(不交換), 87?10, 87?67(不交換), 67?15, 67?59(不交換), 59?25, 59?34(不交換)
    • ?結果?:[3, 34, 25, 59, 15, 67, 10, 87, 45, 99](最小值3到開頭)
  4. ?第2輪正向遍歷?

    • 比較并交換:34?25, 34?59(不交換), 59?15, 59?67(不交換), 67?10, 67?87(不交換), 87?45
    • ?結果?:[3, 25, 34, 15, 59, 10, 67, 45, 87, 99]
  5. ?第2輪反向遍歷?

    • 比較并交換:45?67(不交換), 67?10, 67?59(不交換), 59?15, 59?34(不交換), 34?25
    • ?結果?:[3, 10, 25, 15, 34, 59, 45, 67, 87, 99]
  6. ?第3輪正向遍歷?

    • 比較并交換:10?25(不交換), 25?15, 25?34(不交換), 34?59(不交換), 59?45, 59?67(不交換)
    • ?結果?:[3, 10, 15, 25, 34, 45, 59, 67, 87, 99]
  7. ?第3輪反向遍歷?

    • 比較并交換:59?45(不交換), 45?34(不交換), 34?25(不交換), 25?15(不交換)
    • ?無交換發生,排序完成?。

?最終結果?

[3, 10, 15, 25, 34, 45, 59, 67, 87, 99]?

  1. ?交替優化?:每輪正向遍歷將最大值推向右端,反向遍歷將最小值推向左端。
  2. ?提前終止?:若某輪遍歷無交換,說明數組已有序(如第3輪反向遍歷后終止)。
  3. ?效率對比?:比傳統冒泡排序減少約50%的輪次(本例僅需3輪雙向遍歷)。

優化思路:?

  1. ?雙向遍歷?:傳統冒泡排序只單向比較(從左到右),而這里同時從左到右和從右到左遍歷,可以更快地將最大值和最小值"冒泡"到正確位置。
  2. ?縮小范圍?:每次遍歷后,未排序部分的邊界(lowhigh)會動態調整,減少不必要的比較次數。

對于雙向冒泡排序(雞尾酒排序)的時間復雜度和空間復雜度分析如下:

? 時間復雜度

💾 空間復雜度

  • ?原地排序?:僅使用常數級臨時變量(如?templowhigh
  • 額外空間與輸入規模無關 → ?O(1)?

🧠 核心結論

指標雙向冒泡排序
?最壞時間復雜度?O(n2)
?最好時間復雜度?O(n)
?平均時間復雜度?O(n2)
?空間復雜度?O(1)(原地排序)

?? ?說明?:盡管雙向遍歷優化了部分場景(如兩端元素有序時效率更高),但時間復雜度量級與傳統冒泡排序一致。

四、習題演練

2023下半年軟件設計師上午題——冒泡排序_冒泡排序選擇題

下面推薦一些可以用來練手的 LeetCode 題目:

  • 75. 顏色分類?- 可使用冒泡排序解決,但有更優的解法
  • 283. 移動零?- 可用冒泡排序的思想將零元素"冒泡"到數組末尾
  • 912. 排序數組?- 可使用冒泡排序,但因為數據規模較大,可能會超時

需要注意的是,使用冒泡排序不一定是最優解,僅使用冒泡排序也可能無法解決問題,不過這些題目都能夠直接或間接體現冒泡排序核心思想,可以熟悉這個算法。

測驗

  1. 冒泡排序是穩定的排序算法嗎,為什么 ?
  2. 對于已經排好序的數組,優化版冒泡排序的時間復雜度是多少?
  3. 冒泡排序每一輪遍歷后,數組尾部會有什么特點?
  4. 如何優化冒泡排序以提高效率?

測驗答案

  1. 是的,冒泡排序是穩定的排序算法。因為只有當前一個元素大于后一個元素時才交換,相等元素不會改變相對位置。
  2. 對于已經排好序的數組,優化版冒泡排序的時間復雜度是O(n)。因為第一輪遍歷不會發生交換,優化版會檢測到這點并提前終止。
  3. 冒泡排序每一輪遍歷后,數組尾部會有一個元素到達其最終位置,且是當前未排序部分中的最大元素。第i輪結束后,末尾i個元素已排好序。
  4. 優化冒泡排序的方法:
    • 添加標志位跟蹤是否發生交換,無交換則提前終止
    • 記錄最后一次交換位置,下一輪只遍歷到該位置
    • 使用雙向冒泡(雞尾酒排序),同時將最大值上浮和最小值下沉

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/86608.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/86608.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/86608.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JAVA畢業設計227—基于SpringBoot+hadoop+spark+Vue的大數據房屋維修系統(源代碼+數據庫)

畢設所有選題&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于SpringBoothadoopsparkVue的大數據房屋維修系統(源代碼數據庫)227 一、系統介紹 本項目前后端分離&#xff0c;分為業主、維修人員、管理員三種角色 1、業主&#xff1a; 登…

MADlib —— 基于 SQL 的數據挖掘解決方案(9)—— 數據探索之概率統計

目錄 一、概率 1. 概率的定義 2. 概率質量函數與概率密度函數 3. 條件概率 4. 期望值 二、MADlib 的概率相關函數 1. 函數語法 2. 示例 &#xff08;1&#xff09;求標準正態分布下&#xff0c;1 的概率密度函數 &#xff08;2&#xff09;求標準正態分布下&#xff…

耳蝸里的春天

早春的鄭州飄著細雨&#xff0c;我牽著女兒小滿的手走進市殘疾人康復中心時&#xff0c;玻璃門內突然傳來一陣清脆的笑聲。穿天藍色毛衣的小女孩戴著粉色耳蝸&#xff0c;正踮腳拍打著墻上的卡通貼畫&#xff0c;銀色的連接線在她耳后晃動&#xff0c;像一只折翼卻仍在起舞的蝴…

OCR(光學字符識別)算法

OCR&#xff08;光學字符識別&#xff09;算法在景區護照閱讀器中的應用是核心技術之一&#xff0c;它通過圖像處理和機器學習快速提取護照信息&#xff0c;顯著提升自動化水平。以下是其具體應用場景、技術實現及優化方向&#xff1a; 一、OCR在護照閱讀器中的核心作用 關鍵信…

html打印合同模板

概述&#xff08;吐槽&#xff09;&#xff1a;記錄一個html打印合同模板的功能&#xff0c;技術棧有點雜&#xff0c;千禧年出產老系統的數據庫是sqlserver2008&#xff0c;原系統框架是c#&#xff0c;無法二開&#xff0c;因為原系統的合同生成功能出現bug&#xff0c;沒有供…

DeepCritic: SFT+RL兩階段訓練突破LLM自我監督!顯著提升大模型的自我批判能力!!

摘要&#xff1a;隨著大型語言模型&#xff08;LLMs&#xff09;的迅速發展&#xff0c;對其輸出進行準確反饋和可擴展監督成為一個迫切且關鍵的問題。利用LLMs作為批評模型以實現自動化監督是一個有前景的解決方案。在本研究中&#xff0c;我們專注于研究并提升LLMs在數學批評…

【深度學習】深度學習中的張量:從多維數組到智能計算單元

? 一、n維數組&#xff08;張量&#xff0c;Tensor&#xff09; 1. 定義 張量&#xff08;Tensor&#xff09;是一個通用的n維數組數據結構。 它的維度&#xff08;維數&#xff09;決定了它的形狀&#xff0c;例如&#xff1a; 維度名稱舉例說明0維標量&#xff08;scalar…

以太網MDI信號PCB EMC設計要點

1. PHY側和RJ45連接器側通用MDI布局建議 1. MDI差分對保持對稱走線&#xff0c;走線上的焊盤封裝應一致&#xff0c;焊盤放置位置也應對稱。可以減少EMI測試中的模式轉換。 ??2. MDI走線應保持阻抗匹配&#xff0c;從而減少信號線上的反射。 ??3. MDI走線下需有連續完整的接…

深入淺出WebGL:在瀏覽器中解鎖3D世界的魔法鑰匙

WebGL&#xff1a;在瀏覽器中解鎖3D世界的魔法鑰匙 引言&#xff1a;網頁的邊界正在消失 在數字化浪潮的推動下&#xff0c;網頁早已不再是靜態信息的展示窗口。如今&#xff0c;我們可以在瀏覽器中體驗逼真的3D游戲、交互式數據可視化、虛擬實驗室&#xff0c;甚至沉浸式的V…

pysnmp模塊中 GET、SET、WALK操作詳細分步解析

1. SNMP GET 操作詳解 1.1 核心代碼結構 from pysnmp.hlapi import *# 定義參數 community public # SNMPv2c 社區名 target_ip 192.168.1.1 # 目標設備 IP oid 1.3.6.1.2.1.1.1.0 # 要查詢的 OID# 發起 GET 請求 error_indication, error_status, error_index, …

接收rabbitmq消息

以下是一個使用純Java&#xff08;非Spring Boot&#xff09;接收RabbitMQ消息的完整實現&#xff0c;包含Maven依賴和持續監聽消息的循環&#xff1a; 1. 首先添加Maven依賴 (pom.xml) <dependencies><!-- RabbitMQ Java Client --><dependency><group…

SQL進階之旅 Day 23:事務隔離級別與性能優化

【SQL進階之旅 Day 23】事務隔離級別與性能優化 文章簡述 在數據庫系統中&#xff0c;事務是確保數據一致性和完整性的核心機制。隨著業務復雜度的提升&#xff0c;如何合理設置事務隔離級別以平衡并發性能與數據一致性成為開發人員必須掌握的關鍵技能。本文深入解析事務隔離級…

六.原型模式

一.原型模式的定義 原型模式是一種創建型設計模式&#xff0c;通過復制現有對象&#xff08;原型&#xff09;生成新對象&#xff0c;避免重復初始化成本。需了解以下關鍵概念&#xff1a; ?淺拷貝?&#xff1a;復制基本類型字段&#xff0c;引用類型字段共享內存地址&#…

【筆記】LoRA 理論與實現|大模型輕量級微調

論文鏈接&#xff1a;LoRA: Low-Rank Adaptation of Large Language Models 官方實現&#xff1a;microsoft/LoRA 非官方實現&#xff1a;huggingface/peft、huggingface/diffusers 這篇文章要介紹的是一種大模型/擴散模型的微調方法&#xff0c;叫做低秩適應&#xff08;也就是…

Cilium動手實驗室: 精通之旅---15.Isovalent Enterprise for Cilium: Network Policies

Cilium動手實驗室: 精通之旅---15.Isovalent Enterprise for Cilium: Network Policies 1. 環境信息2. 測試環境部署3. 默認規則3.1 測試默認規則3.2 小測驗 4. 網絡策略可視化4.1 通過可視化創建策略4.2 小測試 5. 測試策略5.1 應用策略5.2 流量觀測5.3 Hubble觀測5.4 小測試 …

opencv RGB圖像轉灰度圖

這段代碼的作用是將一個 3通道的 RGB 圖像&#xff08;CV_8UC3&#xff09;轉換為灰度圖像&#xff08;CV_8UC1&#xff09;&#xff0c;并使用 OpenCV 的 parallel_for_ 對圖像處理進行并行加速。 &#x1f50d; 一、函數功能總結 if (CV_8UC3 img.type()) {// 創建灰度圖 d…

React Hooks 的原理、常用函數及用途詳解

1. ??Hooks 是什么&#xff1f;?? Hooks 是 React 16.8 引入的函數式組件特性&#xff0c;允許在不編寫 class 的情況下使用 state 和其他 React 特性&#xff08;如生命周期、副作用等&#xff09;。??本質是一類特殊函數??&#xff0c;它們掛載到 React 的調度系統中…

學習路之PHP--webman協程學習

學習路之PHP--webman協程學習 一、準備二、配置三、啟動四、使用 協程是一種比線程更輕量級的用戶級并發機制&#xff0c;能夠在進程中實現多任務調度。它通過手動控制掛起和恢復來實現協程間的切換&#xff0c;避免了進程上下文切換的開銷 一、準備 PHP > 8.1 Workerman &g…

linux libusb使用libusb_claim_interface失敗(-6,Resource busy)解決方案

linux libusb使用libusb_claim_interface失敗&#xff08;-6&#xff0c;Resource busy&#xff09;解決方案 ? 問題原因&#x1f6e0;? 解決方案&#x1f538; 方法一&#xff1a;分離內核驅動 libusb_detach_kernel_driver()&#x1f538; 方法二&#xff1a;使用 usb-devi…

使用mpu6500/6050, PID,互補濾波實現一個簡單的飛行自穩控制系統

首先&#xff0c;參考ai給出的客機飛機的比較平穩的最大仰府&#xff0c;偏轉&#xff0c;和防滾角度&#xff0c;如下&#xff1a; 客機的最大平穩仰俯&#xff08;Pitch&#xff09;、偏轉&#xff08;Yaw&#xff09;和防滾&#xff08;Roll&#xff09;角度&#xff0c;通…