Java 中的排序算法詳解

目錄

一、冒泡排序(Bubble Sort)

原理?

二、選擇排序(Selection Sort)

原理?

三、插入排序(Insertion Sort)

原理?

四、快速排序(Quick Sort)

原理?

五、歸并排序(Merge Sort)

原理?

六、希爾排序(Shell Sort)

原理?

七、總結


作為一名 Java 初學者,掌握排序算法是編程路上的重要一步。排序算法不僅能幫助我們更好地理解數據處理邏輯,還能在實際開發中解決各種問題。

一、冒泡排序(Bubble Sort)

泡排序是最基礎的排序算法之一,它的核心思想是通過重復遍歷要排序的數組,每次比較相鄰的兩個元素,如果它們的順序錯誤就把它們交換過來。

原理?

就像水中的氣泡會逐漸上浮一樣,越大的元素會經由交換慢慢 “浮” 到數組的末端。具體來說,每一輪遍歷都會將當前未排序部分中最大的元素移動到正確的位置。

public class BubbleSort {public static void bubbleSort(int[] arr) {int n = arr.length;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;}}}}public static void main(String[] args) {int[] arr = {64, 34, 25, 12, 22, 11, 90};bubbleSort(arr);System.out.println("排序后的數組:");for (int num : arr) {System.out.print(num + " ");}}
}

?排序后的數組:
?11 12 22 25 34 64 90?

優缺點?:

  • 優點:實現簡單,易于理解,是入門排序算法的好選擇。?
  • 缺點:效率較低,時間復雜度為 O (n2),在處理大規模數據時性能不佳。

二、選擇排序(Selection Sort)

選擇排序的思路相對直觀,它每次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,直到全部待排序的數據元素排完。

原理?

首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續尋找最小元素,放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

public class SelectionSort {public static void selectionSort(int[] arr) {int n = arr.length;for (int i = 0; i < n - 1; i++) {// 找到未排序部分的最小元素索引int minIndex = i;for (int j = i + 1; j < n; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}// 將最小元素與未排序部分的第一個元素交換int temp = arr[minIndex];arr[minIndex] = arr[i];arr[i] = temp;}}public static void main(String[] args) {int[] arr = {64, 25, 12, 22, 11};selectionSort(arr);System.out.println("排序后的數組:");for (int num : arr) {System.out.print(num + " ");}}
}

排序后的數組:
11 12 22 25 64?

優缺點?:

  • 優點:實現簡單,相較于冒泡排序,交換次數更少。?
  • 缺點:時間復雜度仍為 O (n2),不適合處理大量數據。

三、插入排序(Insertion Sort)

插入排序的工作方式類似于我們整理手中的撲克牌,它將數組分為已排序和未排序兩部分,每次從為排序部分中取出一個元素,插入到已排序部分的正確位置。

原理?

從第一個元素開始,該元素可以認為已經被排序;取出下一個元素,在已經排序的元素序列中從后向前掃描;如果該元素(已排序)大于新元素,將該元素移到下一位置;重復上一步驟,直到找到已排序的元素小于或者等于新元素的位置;將新元素插入到該位置后;重復以上步驟。

public class InsertionSort {public static void insertionSort(int[] arr) {int n = arr.length;for (int i = 1; i < n; i++) {int key = arr[i];int j = i - 1;// 將大于key的元素向后移動一位while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j = j - 1;}arr[j + 1] = key;}}public static void main(String[] args) {int[] arr = {12, 11, 13, 5, 6};insertionSort(arr);System.out.println("排序后的數組:");for (int num : arr) {System.out.print(num + " ");}}
}

?排序后的數組:
5 6 11 12 13?

優缺點?:

  • 優點:對于近乎有序的數組,插入排序的效率很高,時間復雜度可接近 O (n);實現也較為簡單。?
  • 缺點:在處理完全無序的大規模數據時,時間復雜度仍為 O (n2)。

四、快速排序(Quick Sort)

快速排序是一種高效的排序算法,它采用了分治法的思想,通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,然后分別對這兩部分記錄繼續進行排序,以達到整個序列有序的目的。

原理?

選擇一個元素作為 “基準”(pivot),通常選擇數組的第一個元素、最后一個元素或中間元素。然后將所有比基準值小的元素放在基準前面,所有比基準值大的元素放在基準后面,這個過程稱為分區(partition)操作。接著,對基準前后的兩個子數組分別重復上述過程,直到子數組的長度為 1 或 0。

public class QuickSort {public static void quickSort(int[] arr, int low, int high) {if (low < high) {// 分區操作,得到基準元素的正確位置int pi = partition(arr, low, high);// 遞歸排序基準元素左邊和右邊的子數組quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}}private static int partition(int[] arr, int low, int high) {// 選擇最右邊的元素作為基準int pivot = arr[high];// i表示小于基準元素的區域的邊界int i = low - 1;for (int j = low; j < high; j++) {// 如果當前元素小于或等于基準元素,將其放入小于基準的區域if (arr[j] <= pivot) {i++;// 交換元素int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}// 將基準元素放到正確的位置int temp = arr[i + 1];arr[i + 1] = arr[high];arr[high] = temp;return i + 1;}public static void main(String[] args) {int[] arr = {10, 7, 8, 9, 1, 5};int n = arr.length;quickSort(arr, 0, n - 1);System.out.println("排序后的數組:");for (int num : arr) {System.out.print(num + " ");}}
}

排序后的數組:
1 5 7 8 9 10?

優缺點?:

  • 優點:平均時間復雜度為 O (n log n),效率高,在實際應用中廣泛使用。?
  • 缺點:在最壞情況下(如數組已經有序),時間復雜度會退化為 O (n2);不穩定,可能會改變相等元素的相對順序。

五、歸并排序(Merge Sort)

歸并排序同樣基于分治法,它的核心是將兩個或兩個以上的有序表合并成一個新的有序表。?

原理?

將待排序數組不斷二分,直到每個子數組只包含一個元素(此時子數組自然有序)。然后,將這些有序的子數組兩兩合并,每次合并都得到一個更大的有序數組,重復這個過程,直到最終得到一個完整的有序數組。

public class MergeSort {// 合并兩個有序子數組public static void merge(int[] arr, int left, int mid, int right) {// 計算兩個子數組的長度int n1 = mid - left + 1;int n2 = right - mid;// 創建臨時數組int[] L = new int[n1];int[] R = new int[n2];// 將數據復制到臨時數組for (int i = 0; i < n1; ++i) {L[i] = arr[left + i];}for (int j = 0; j < n2; ++j) {R[j] = arr[mid + 1 + j];}// 合并臨時數組int i = 0, j = 0;int k = left;while (i < n1 && j < n2) {if (L[i] <= R[j]) {arr[k] = L[i];i++;} else {arr[k] = R[j];j++;}k++;}// 復制剩余元素while (i < n1) {arr[k] = L[i];i++;k++;}while (j < n2) {arr[k] = R[j];j++;k++;}}// 歸并排序主方法public static void mergeSort(int[] arr, int left, int right) {if (left < right) {// 找到中間點int mid = left + (right - left) / 2;// 遞歸排序左右兩部分mergeSort(arr, left, mid);mergeSort(arr, mid + 1, right);// 合并已排序的兩部分merge(arr, left, mid, right);}}public static void main(String[] args) {int[] arr = {12, 11, 13, 5, 6, 7};int n = arr.length;mergeSort(arr, 0, n - 1);System.out.println("排序后的數組:");for (int num : arr) {System.out.print(num + " ");}}
}

排序后的數組:
5 6 7 11 12 13?

優缺點?

  • 優點:時間復雜度穩定為 O (n log n),不受輸入數據的影響;是穩定的排序算法。?
  • 缺點:需要額外的存儲空間,空間復雜度為 O (n)。

六、希爾排序(Shell Sort)

希爾排序是插入排序的一種改進版本,它通過將數組按照一定的間隔分組,對每組進行插入排序,然后逐漸縮小間隔,直到間隔為 1,此時進行最后一次插入排序,使數組完全有序。?

原理?

先確定一個增量序列,增量序列可以有多種選擇,常見的有初始增量為數組長度的一半,之后每次減半,直到增量為 1。對于每個增量,將數組中所有距離為該增量的元素組成一個子數組,對每個子數組進行插入排序。隨著增量逐漸減小,子數組的長度逐漸增大,當增量為 1 時,整個數組就是一個子數組,此時進行一次插入排序,數組就會變得有序。

public class ShellSort {public static void shellSort(int[] arr) {int n = arr.length;// 初始增量為數組長度的一半,之后每次減半for (int gap = n / 2; gap > 0; gap /= 2) {// 對每個子數組進行插入排序for (int i = gap; i < n; i++) {int temp = arr[i];int j;// 移動同組中比temp大的元素for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {arr[j] = arr[j - gap];}arr[j] = temp;}}}public static void main(String[] args) {int[] arr = {12, 34, 54, 2, 3};shellSort(arr);System.out.println("排序后的數組:");for (int num : arr) {System.out.print(num + " ");}}
}

排序后的數組:
2 3 12 34 54?

優缺點?

  • 優點:相較于插入排序,希爾排序在處理大規模數據時效率更高,平均時間復雜度優于 O (n2),具體取決于增量序列的選擇。?
  • 缺點:時間復雜度受增量序列影響較大,不同的增量序列可能會導致不同的性能;是不穩定的排序算法。

七、總結

以上六種排序算法各有特點,適用于不同的場景。

冒泡排序、選擇排序和插入排序是基礎的排序算法,實現簡單但效率較低,適合處理小規模數據或作為學習排序算法的入門內容。?

快速排序、歸并排序和希爾排序是更高級的排序算法,它們在處理大規模數據時表現更出色。快速排序平均效率高,應用廣泛;歸并排序時間穩定且穩定,但需要額外空間;希爾排序是插入排序的改進,性能優于基礎的插入排序。

同時,Java 類庫中提供的 Arrays.sort () 方法內部采用了多種高效排序算法的組合,在大多數情況下能滿足我們的需求,但了解各種排序算法的原理和實現,能幫助我們更好地理解和使用這些工具。

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

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

相關文章

Gitee如何成為國內企業DevOps轉型的首選平臺?

Gitee如何成為國內企業DevOps轉型的首選平臺&#xff1f; 在數字化轉型浪潮中&#xff0c;DevOps已成為提升企業研發效能的關鍵引擎。作為國內領先的代碼托管與協作平臺&#xff0c;Gitee憑借本土化優勢與全流程支持能力&#xff0c;正成為越來越多企業DevOps實踐的核心載體。本…

?Excel——SUMPRODUCT 函數

SUMPRODUCT 是 Excel 中最強大的函數之一&#xff0c;可以用于 ?多條件求和、加權計算、數組運算? 等復雜場景。下面通過 ?基礎語法 實用案例? 徹底講透它的用法&#xff01;?一、基礎語法?SUMPRODUCT(數組1, [數組2], [數組3], ...)?功能?&#xff1a;將多個數組的對…

告別虛函數性能焦慮:深入剖析C++多態的現代設計模式

?? 引言:當多態遇上性能瓶頸 我經常被問到這樣一個問題:“既然virtual函數這么方便,為什么在一些高性能場景下,大家卻避之不及?” 答案很簡單:性能。 在我參與的多個HPC項目和游戲引擎開發中,virtual函數調用往往成為性能分析工具中最顯眼的那個紅點。一個看似無害…

k8s-MongoDB 副本集部署

前提準備一套 k8s 集群worker 節點上的 /nfs/data 目錄掛載到磁盤一、NFS 高可用方案&#xff08;NFSkeepalivedSersync&#xff09;本方案 NFS 的高可用方案&#xff0c;應用服務器為 Client &#xff0c;兩臺文件服務器分別 Master 和 Slave&#xff0c;使用 keepalived 生成…

BI 系統數據看板全解析:讓數據可視化驅動業務決策

BI 系統數據看板全解析&#xff1a;讓數據可視化驅動業務決策在 BI 系統中&#xff0c;數據看板是連接原始數據與業務洞察的 “橋梁”。它將零散的業務指標轉化為直觀的可視化圖表&#xff0c;讓產品經理、運營人員等角色能快速把握業務動態。一個設計精良的數據看板&#xff0…

圖機器學習(14)——社交網絡分析

圖機器學習&#xff08;14&#xff09;——社交網絡分析0. 前言1. 數據集分析1.1 數據集介紹1.2 使用 networkx 加載數據集2. 網絡拓撲和社區檢測2.1 網絡拓撲2.2 社區檢測0. 前言 社交網站的崛起是近年來數字媒體領域最活躍的發展趨勢之一&#xff0c;數字社交互動已經融入人…

深入解析Hadoop MapReduce中Reduce階段排序的必要性

MapReduce概述與Reduce階段簡介MapReduce作為Hadoop生態系統的核心計算框架&#xff0c;其設計思想源自Google論文&#xff0c;通過"分而治之"的理念實現海量數據的并行處理。該模型將計算過程抽象為兩個關鍵階段&#xff1a;Map階段負責數據分解和初步處理&#xff…

7月23日華為機考真題第二題-200分

?? 點擊直達筆試專欄 ??《大廠筆試突圍》 ?? 春秋招筆試突圍在線OJ ?? 筆試突圍OJ bishipass.com 02. 圖書館資源分配系統 問題描述 A先生是一位圖書館管理員,負責管理圖書采購和分配工作。圖書館收到了來自不同出版社的圖書批次,同時有多位讀者代表排隊申請圖書…

基于深度學習的圖像分類:使用ResNet實現高效分類

最近研學過程中發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊鏈接跳轉到網站人工智能及編程語言學習教程。讀者們可以通過里面的文章詳細了解一下人工智能及其編程等教程和學習方法。下面開始對正文內容的…

JVM:工具

JVMjpsjstatjmapjhatjstackjconsolejvisualvmjps jps&#xff08; Java Virtual Machine Process Status Tool &#xff09;&#xff0c;是 JDK 中的一個命令行工具&#xff0c;用于列出當前正在運行的 JVM 實例的信息。其對于監控和管理運行在多個 JVM 上的 Java 應用程序特別…

Elasticsearch Circuit Breaker 全面解析與最佳實踐

一、Circuit Breaker 簡介 Elasticsearch 是基于 JVM 的搜索引擎&#xff0c;其內存管理十分重要。為了避免單個操作或查詢耗費過多內存導致節點不可用&#xff0c;Elasticsearch 引入了 Circuit Breaker&#xff08;熔斷器&#xff09;機制。當內存使用達到熔斷器預設閾值時&a…

ARM-定時器-定時器函數封裝配置

以TIMER7為例&#xff0c;對定時器函數進行封裝注意事項&#xff1a;GD32中TIMER7是高級定時器&#xff0c;相關詳細請參考上一篇文章。main.c//main.c#include "gd32f4xx.h" #include "systick.h" #include <stdio.h> #include "main.h" …

【日志】unity俄羅斯方塊——邊界限制檢測

Bug修復記錄 項目場景 嘗試使用Unity獨自制作俄羅斯方塊&#xff08;也許很沒有必要&#xff0c;網上隨便一搜就有教程&#xff09; 問題描述 俄羅斯方塊的邊緣檢測出錯了&#xff0c;對方塊進行旋轉后&#xff0c;無法到達最左側或者最下側的位置&#xff0c;以及其他問題。演…

C++ string:準 STL Container

歷史STL 最初是一套獨立的泛型庫&#xff08;Alexander Stepanov 等人貢獻&#xff09;&#xff0c;后來被吸納進 C 標準庫&#xff1b;std::basic_string 則是早期 C 標準&#xff08;Cfront / ARM 時代&#xff09;就存在的“字符串類”&#xff0c;并非 STL 原生物。std::st…

Golang學習筆記--語言入門【Go-暑假學習筆記】

目錄 基礎語法部分相關概念 基礎語法部分概念詳解 可見性 導包 內部包 運算符 轉義字符 函數 風格 函數花括號換行 代碼縮進 代碼間隔 花括號省略 三元表達式 數據類型部分相關概念 數據類型部分概念詳解 布爾類型 整型 浮點型 復數類型 字符類型 派生類型…

linux中kill 命令使用詳解

在Linux系統里&#xff0c;kill命令的主要功能是向進程發送信號&#xff0c;以此來控制進程的運行狀態。下面為你詳細介紹它的使用方法&#xff1a; 基礎語法 kill [選項] [進程ID]進程ID也就是PID&#xff0c;可通過ps、pgrep或者top等命令來獲取。 常用信號及其含義 信號可以…

Nginx 安裝與 HTTPS 配置指南:使用 OpenSSL 搭建安全 Web 服務器

Nginx 安裝與 HTTPS 配置指南:使用 OpenSSL 搭建安全 Web 服務器 一、Nginx安裝 1. 安裝依賴項 sudo yum groupinstall "Development Tools" -y # 非必須 sudo yum install pcre pcre-devel zlib zlib-devel openssl openssl-devel -y2.下載Nginx wget http://n…

寫個 flask todo app,簡潔,實用

- 此項目雖然看起來簡單&#xff0c;實際上&#xff0c;修改成自己喜歡的樣子&#xff0c;也是費時間的。 - 別人都搞AI 相關的項目&#xff0c;而我還是搞這種基礎的東西。不要灰心。 - 積累。不論項目大小&#xff0c;不論難易&#xff0c;只看是否有用。項目地址&#xff1a…

4麥 360度定位

要在 ESP32 上用 4 個麥克風實現 360 聲源定位&#xff0c;通常思路是通過 時延估計&#xff08;TDOA&#xff09; 幾何計算&#xff0c;核心流程&#xff1a;陣列布置將 4 個麥克風等間距布置成正方形&#xff08;或圓形&#xff09;。記陣列中心為原點&#xff0c;麥克風編號…

使用yolov10模型檢測視頻中出現的行人,并保存為圖片

一、使用yolov10模型檢測視頻中出現的行人&#xff0c;并保存為圖片&#xff0c;detect_person.py代碼如下&#xff1a;from ultralytics import YOLOv10 import glob import os import cv2 import argparsedef detect_person(videoPath, savePath):if not os.path.exists(save…