數據結構Java--7

排序

排序就是使一串記錄,按照其中的某個或某些關鍵字的大小,遞增或遞減的排列起來的操作

排序的穩定性

假若有以下數組,數組中存在兩個5,這里區分標記

如果排序之后,紅色的5仍然在藍色的5前面,我們就認為該排序是穩定的

穩定

反之如果打亂了原本紅色5在前的順序,我們就認為該排序是不穩定的排序

?不穩定

常見的排序

插入排序

把待排序的記錄按其關鍵碼值的大小逐個插入到一個已經排好序的有序序列中,直到所有的記錄插入完為止,得到一個新的有序序列。在生活中我們玩斗地主的時候,洗牌就是用到了插入排序。

具體流程如下

第一個數據本身不用排序,從第二個數據開始,把前面兩個數據看成一組,然后讓1和該組的每一個元素進行比較如果找到合適的位置就插入

然后到第三個數據,這里發現已經有序則不進行改動

然后是第四個數據,一樣的,把第四個數據和該組內的所有數據比較,然后找到合適的位置插入

后面也同理

對數組排序完成之后我們發現,插入排序是一種穩定的排序

插入排序的特性

1. 元素集合越接近有序,直接插入排序算法的時間效率越高

2. 時間復雜度:O(N^2)(此篇幅里說到時間復雜度代表平均復雜度)

3. 空間復雜度:O(1)

4. 穩定性:穩定

代碼實現

 public static void insertSort(int[] array){for (int i = 1; i < array.length; i++) {int temp = array[i];int j = i-1;for (; j >= 0; j--) {if(array[j]>temp){array[j+1] =array[j];}else{break;}}array[j+1]=temp;}}

希爾排序

希爾排序法也叫做,縮小增量法。體現在排序當中就是對待排序列進行分組,每一組內分別排序,然后減少組數,直至減少到為一組,然后整體再進行排序,這樣做的好處是,在縮小為一整組之前,帶排序列的數據會基本趨近于有序的,這樣就可以減小復雜度。

這里有一組待排的數組,我們把數組分為五組,組內數據的間隔為5,然后進行分組排序。

然后再分為兩組,組內數據的間隔為2,然后再進行分組排序

可以發現當分量縮小為2的時候,數組內的數據已經基本趨于有序了,這個時候再縮小增量,就是一整組進行排序

代碼實現

 public static void shellSort(int[] array){int gap = array.length;while(gap>1){gap/=2;Shell(array,gap);}}private static void Shell(int[] array,int gap){for (int i = gap; i < array.length; i++) {int temp = array[i];int j = i-gap;for (; j >= 0; j-=gap) {if(array[j]>temp){array[j+gap] =array[j];}else{break;}}array[j+gap]=temp;}}

希爾排序的特性

1.?希爾排序是對直接插入排序的優化,當gap > 1時都是預排序,目的是讓數組更接近于有序。當gap == 1時,數組已經接近有序的了,這樣就會很 快。這樣整體而言,可以達到優化的效果。

2. 時間復雜度:

最好情況:O(N)

平均情況:O(N^1.3)?希爾排序的時間復雜度并不是穩定的,N的1.3次方是Knuth在進行大量的實驗和測試得出了結論,所以我們認為希爾排序的時間復雜度是O(N^1.3)

最壞情況:O(N^2)

3. 空間復雜度:O(1)

4. 穩定性:不穩定

選擇排序

每一次從待排序的數據元素中選出最小的一個元素,存放在序列的起始位置,放完之后,然后再從第二個元素開始找到后面最小的元素,以此循環,直到全部待排序的數據元素排完。

我們要對這組數據進行選擇排序,先找第一個最小的數據,這里最小的數據為1,然后我們交換1?和 4

然后從第二個位置往后,再找最小的數據,最小數據為2,2?和 6交換

以此往復,得到結果

代碼實現

這里的selectSort2是另一種選擇排序的思路

 public static void selectSort(int[] array){for (int i = 0; i < array.length; i++) {int minIndex = i;for (int j = i+1; j < array.length; j++) {if(array[j]<array[minIndex]){minIndex = j;}}swap(array,i,minIndex);}}public static void selectSort2(int[] array){int left = 0 ;int right = array.length-1;while(left<right){int minIndex = left;int maxIndex = left;for (int i = left+1; i <=right; i++) {if(array[i]<array[minIndex]){minIndex = i;}if(array[i]>array[maxIndex]){maxIndex = i;}}swap(array,left,minIndex);if(maxIndex==left){maxIndex = minIndex;}swap(array,right,maxIndex);left++;right--;}}private static void swap(int[] array,int a,int b){int temp = array[a];array[a] = array[b];array[b] = temp;}

選擇排序的特性

1. 直接選擇排序思考非常好理解,但是效率不是很好,實際中很少使用

2. 時間復雜度:O(N^2)

3. 空間復雜度:O(1)

4. 穩定性:不穩定

堆排序

前面了解堆這種數據結構的時候提到過堆分為大根堆和小根堆,這里要說到的堆排序就是基于大根堆和小根堆的特性來實現的。如果要求數據從小到大排序就建立大根堆,反之小根堆。

流程為:將一組數據建堆,這里以從小到大的排序為目標,建立一個大根堆,然后把堆頂元素和最后的元素進行交換,交換完成之后對堆頂進行向下調整,然后縮小調整的范圍,這樣堆的最后一個元素就是最大的元素了。

這里畫圖舉例,假若有一組數據為 1? 6? 2? 4? 10? 9? 3,對這組數據建立大根堆

然后交換堆頂元素和數組的最后一個元素

交換完成之后我們縮小調整的范圍,這樣10就不會受到后面調整的影響了,這里用紅圈標起來

調整為大根堆

然后再交換堆頂元素和最后一個元素

再對堆進行調整

以此往復

代碼實現

public static void heapSort(int[] array){createBigHeap(array);int end = array.length-1;while(end>0){swap(array,0,end);siftDown(array,0,end);end--;}}private static void createBigHeap(int[] array){for(int parent = (array.length-1-1)/2;parent>=0;parent--){siftDown(array,parent,array.length);}}private static void siftDown(int[] array,int parent,int end){int child=parent*2+1;while(child<end){if(child+1<end&&array[child+1]>array[child]){child++;}if(array[child]>array[parent]){swap(array,child,parent);parent = child;child= parent*2 +1;}else{break;}}}

堆排序的特性

1. 堆排序使用堆來選數,效率就高了很多。

2. 時間復雜度:O(N*logN)

3. 空間復雜度:O(1)

4. 穩定性:不穩定

冒泡排序

冒泡排序很簡單,這里不細細展開

代碼實現

這里進行了一點優化,可以減小復雜度

 public static void bubbleSort(int[] array) {for (int i = 0; i < array.length; i++) {boolean flag = false;//標記for (int j = 0; j < array.length-i-1; j++) {if(array[j]>array[j+1]){swap(array,j+1,j);flag=true;//如果走不到這一步}}if(flag==false){//說明已經有序,則從這里退出方法return ;}}}

冒泡排序的特性

1. 冒泡排序是一種非常容易理解的排序

2. 時間復雜度:O(N^2)

3. 空間復雜度:O(1)

4. 穩定性:穩定

快速排序

快速排序是Hoare于1962年提出的一種二叉樹結構的交換排序方法,其基本思想為:任取待排序元素序列中的某元 素作為基準值,按照該排序碼將待排序集合分割成兩子序列,左子序列中所有元素均小于基準值,右子序列中所有 元素均大于基準值,然后最左右子序列重復該過程,直到所有元素都排列在相應位置上為止。

快速排序的核心圍繞著定基準來進行

先說說第一種方法:Hoare法

以第一個數據為基準,然后定義兩個下標,先移動右下標,找到比key小的元素就停止,然后到左下標,移動左下標,找到比key大的元素就停止。

這里找到了9比6大,5比6小,然后交換兩個元素。

繼續移動,先右再左,找到目標

然后交換,先移動右下標

當左右下標相遇時停止,讓left或者right下標元素和最左邊的元素交換

此時發現以6為基準,6的左邊所有的元素都小于6,6右邊的所有元素都大于6

然后在把數組分為兩個部分,左邊的一組再以4為基準來定基準,右邊的一組再以8為基準來定基準以此循環,最終達到排序的效果。

第二種方法:挖坑法

同樣的順序,先移動右邊,遇到比key小的元素停下

然后把5挖起來蓋住左下標的位置

然后再移動左下標,找到比6大的元素

然后挖起來放到右下標的位置

然后右下標

然后左下標

然后右下標

當左右下標相遇時,把key放入相遇的位置

第三種方法:前后指針法

定義兩個下標,

然后按照以下規則移動和交換

取左邊下標為key,這里是6,如果J下標的元素小于key,移動I下標,如果I下標和J下標重合,則繼續移動J下標,直至不滿足條件位置,最后I下標和左邊的元素交換即可。

可以發現三種方法定基準的左右數據都把一樣,這里更加推薦使用挖坑法進行定基準

代碼實現

 private static int partition2(int[] array,int left ,int right) {//Hoare交換法求基準int key = array[left];//選left下標的數作為基準int i = left;//記錄下左邊下標while(left<right){while(left<right && array[right]>=key){//多加個判斷防止越界right--;//沒遇到比key小的就往前走}while(left<right && array[left]<=key){left++;//沒遇到比key大的就往后走}swap(array,left,right);//遇到大的在前,小的再后,此時就可以交換兩個下標的值}swap(array,i,right);//相遇之后交換基準和相遇的地方return left;//返回基準,這樣就可以做到,調整順序,和找基準}private static int partition(int[] array,int left ,int right) {//挖坑法int key = array[left];//選left下標的數作為基準while(left<right){while(left<right&&array[right]>key){right--;}array[left] = array[right];while(left<right&&array[left]<key){left++;}array[right] = array[left];}array[left]=key;return left;//挖坑法的優先度更高,因為會省去交換的操作,從而達到減小復雜度的效果}private static int partition3(int[] array,int left,int right){//前后指針法int front = left;int rear = left +1;while(rear<=right){if(array[rear]<array[left]&&array[++front]!=array[rear]){swap(array,rear,front);}rear++;}swap(array,front,left) ;return front;}

這里有一種特殊的情況,如果一組數據為 1 2 3 4 5 6 7? 這樣有序或者趨于有序的數據,此時還將左邊的第一個數據作為基準,就會使數據變成一顆單分支的二叉樹結構,此時的時間復雜度會增大,所以我們為了避免這樣的情況,這里需要盡可能的使基準定到數組中間的位置。

public static void quickSort(int[] array) {quick(array,0,array.length-1);}private static void quick(int[] array,int start,int end ){if(start>=end){return ;}int index = midOfThree(array,start,end);swap(array,index,start);int pivot = partition(array,start,end);quick(array,start,pivot-1);quick(array,pivot+1,end);}private static int midOfThree(int[] array, int left , int right){//三數取中,優化基準的位置int mid = (left+right)/2;if (array[left] < array[right]) {if(array[mid]<array[left]){return left;}else if(array[mid]>array[right]){return right;}else{return mid;}}else{if(array[mid]>array[left]){return left;}else if(array[mid]<array[right]){return right;}else{return mid;}}}

快速排序的特性

1. 快速排序整體的綜合性能和使用場景都是比較好的,所以才敢叫快速排序

2. 時間復雜度:O(N*logN)

3. 空間復雜度:O(logN)

4. 穩定性:不穩定

歸并排序

歸并排序是一種二叉樹結構的排序,核心思想就是把一組數據分成多分,然后再合并成有序的數組

代碼實現

public static void mergeSort(int[] array) {mergeSortFunction(array,0,array.length-1);}private static void mergeSortFunction(int[] array , int left ,int right) {if(left >=right){return ;}int mid = (left + right )/2;mergeSortFunction(array,left,mid);mergeSortFunction(array,mid+1,right);merge(array,left,right,mid);}private static void merge(int[] array,int left , int right , int mid) {int[] tempArray = new int[right-left+1];int s1 = left;int s2 = mid +1 ;int i = 0 ;while(s1<=mid&&s2<=right){if(array[s1]>=array[s2]){tempArray[i] = array[s2];i++;s2++;}else{tempArray[i] = array[s1];i++;s1++;}}while (s1<=mid){tempArray[i]=array[s1];i++;s1++;}while (s2<=right){tempArray[i]=array[s2];i++;s2++;}for (int j = 0; j < tempArray.length; j++) {array[j+left] = tempArray[j];}}

歸并排序的特性

1. 歸并的缺點在于需要O(N)的空間復雜度,歸并排序的思考更多的是解決在磁盤中的外排序問題。

2. 時間復雜度:O(N*logN)

3. 空間復雜度:O(N)

4. 穩定性:穩定

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

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

相關文章

《Node.js與 Elasticsearch的全文搜索架構解析》

文檔數量跨越百萬級門檻,傳統數據庫的查詢方式就像在沒有索引的圖書館里逐架翻書,不僅耗費時間,更難以捕捉文字背后的深層關聯。此時,由Node.js與Elasticsearch共同構建的全文搜索系統,便成了梳理信息脈絡的無形之手——它能在毫秒之間,從海量文檔中識別用戶的真實意圖,…

Python人工智能matplotlib中markers屬性介紹

在 Matplotlib 中&#xff0c;marker 用于標記數據點&#xff0c;可通過多種參數自定義樣式。以下是詳細說明及示例&#xff1a; 1. 基礎設置常用 marker 類型&#xff1a; . : 點 , : 像素 o : 圓圈 v : 下三角形 ^ : 上三角形 < : 左三角形 >…

【Mac】MLX:Lora微調工作流

本文詳細介紹如何在Mac電腦上使用Apple的MLX框架&#xff0c;通過LoRA&#xff08;低秩適配&#xff09;技術對大語言模型&#xff08;如Qwen3-4B-Instruct&#xff09;進行微調。以下流程適用于8月9日的Mac mini M4 16GB&#xff0c;涵蓋模型獲取、數據準備、微調、運行及模型…

潤乾報表、帆軟報表的開源替代品—JimuReport(積木報表)

國產報表工具選型指南&#xff1a;潤乾報表 vs 積木報表&#xff08;JimuReport&#xff09; 如果你在尋找潤乾報表、帆軟報表的替代產品&#xff0c;JimuReport&#xff08;積木報表&#xff09;是一個值得考慮的選擇。它不僅功能全面&#xff0c;而且操作簡單&#xff0c;非常…

Tiger任務管理系統-12

今天整了一個老虎網站介紹這套任務管理開源系統&#xff0c;防止鏈接丟失&#xff0c;體驗了一把AI編程&#xff0c;雖說確實省了很多事&#xff0c;但源碼確實不敢恭維&#xff0c;尤其是修改的時候&#xff0c;真心累&#xff0c;所以還是要自己掌握核心&#xff0c;AI一時爽…

智慧農業-無人機視角莊稼倒伏農作物倒伏識別分割數據集labelme格式541張1類別

數據集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;僅僅包含jpg圖片和對應的json文件)圖片數量(jpg文件個數)&#xff1a;541標注數量(json文件個數)&#xff1a;541標注類別數&#xff1a;1標注類別名稱:["fall"]每個類別標注的框數&#xff1a;fall co…

電子電氣架構 --- 電氣/電子架構遷移已拉開帷幕

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 做到欲望極簡,了解自己的真實欲望,不受外在潮流的影響,不盲從,不跟風。把自己的精力全部用在自己。一是去掉多余,凡事找規律,基礎是誠信;二是…

PPT漏斗圖,讓數據更美觀!

PPT漏斗圖制作全攻略&#xff1a;從入門到精通的實用技巧和模板推薦 無論你是職場新人還是PPT老手&#xff0c;在做數據報告或者展示項目進度的時候&#xff0c;你總覺得圖表太單調&#xff0c;數據太復雜嗎&#xff1f;這時&#xff0c;一張邏輯清晰、結構簡單的漏斗圖&#…

深入解析C++流運算符(>>和<<)重載:為何必須使用全局函數與友元機制

目錄 一、為什么需要重載為全局函數 成員函數重載的問題 全局函數的優勢 二、實現細節 1、輸出運算符<<的重載 關鍵部分詳解 1. 類定義部分 2. 運算符重載實現 3. main函數中的使用 為什么這樣設計&#xff1f; 執行流程 輸出結果 2、輸入運算符>>的重…

ENS-317 Modbus TCP / 通用模式網關

在工業自動化的復雜網絡中&#xff0c;以太網設備與串口設備的 “語言不通” 常常成為數據流轉的阻礙。上海泗博自動化推出的 ENS-317 Modbus TCP / 通用模式網關&#xff0c;以強大的協議轉換能力、靈活的配置方式和工業級可靠性&#xff0c;為設備互聯提供一站式解決方案&…

AcWing 6478. 誰進線下了?III

原題鏈接 6478. 誰進線下了&#xff1f;III - AcWing題庫 這是一道睿抗&#xff08;省賽&#xff09;題 一開始睿抗是啥都不知道 然后一看是省賽嚇得我不輕 但讀完題簡簡單單 一道很水的模擬題&#xff08;誰能解釋一下睿抗啥意思&#xff09; 一起開康康 題目 Xepa Le…

openpnp - 不連接設備,只大概測試一下攝像頭是否好使

文章目錄openpnp - 不連接設備&#xff0c;只大概測試一下攝像頭是否好使概述筆記備注備注ENDopenpnp - 不連接設備&#xff0c;只大概測試一下攝像頭是否好使 概述 頂部相機攝像頭在拆裝過程中&#xff0c;可能被手上的靜電打壞了。 現在和電腦連接是正常的&#xff0c;但是…

使用Python提取PDF大綱(書簽)完整指南

&#x1f50d; 一、PDF大綱簡介&#x1f4cc; ?PDF大綱&#xff08;Outline&#xff09;?? 是PDF文檔中的導航結構&#xff0c;通常顯示在閱讀器的側邊欄中&#xff0c;方便用戶快速跳轉到文檔的不同部分。大綱通常以層級結構組織&#xff0c;包含標題和對應的頁面位置。本文…

第39周——訓練自己的數據集

目錄 1. 下載數據 2. 配置開發環境 3. 預處理數據 &#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 1. 下載數據 百度網盤&#xff1a;百度網盤 請輸入提取碼 壓縮文件中有兩個文件夾&#xff0c;分別是Annot…

CentOS7中Docker的安裝與卸載

CentOS7 從零開始:Docker 安裝與卸載全指南(新手友好版) 作為一名剛接觸 Linux 和容器技術的新手,你是否曾在安裝 Docker 時被各種命令和報錯搞得一頭霧水?比如執行 yum install docker 時提示 “倉庫不存在”,或者啟動 Docker 后用 docker version 只顯示 client 不顯示…

解決MinIO上傳圖片后返回URL無法訪問的問題

一、問題現象 上傳接口返回了文件的訪問路徑&#xff0c;比如&#xff1a; http://127.0.0.1:9005/lease/20250808/xxx-uuid.png但是用瀏覽器直接打開該地址卻顯示權限拒絕,前端也訪問不到:二、問題原因分析 桶權限設置不正確: MinIO默認桶權限是私有的&#xff0c;即使瀏覽器能…

系統網絡端口安全掃描腳本及詳解

#!/bin/bash # 系統服務端口安全掃描 - 修正版echo " 系統服務端口安全掃描報告 "# 1. 高風險端口識別 echo "?? 對外開放的高風險端口:" awk /0.0.0.0:21/ {print " 端口 21 - FTP (明文傳輸)\n &#x1f6a8; 嚴重安全風險&#xff0c;建議…

DAY 39 圖像數據與顯存

知識點回顧 圖像數據的格式&#xff1a;灰度和彩色數據模型的定義顯存占用的4種地方 模型參數梯度參數優化器參數數據批量所占顯存神經元輸出中間狀態 batchisize和訓練的關系 一、 圖像數據的介紹 1.1 灰度圖像 從這里開始我們進入到了圖像數據相關的部分&#xff0c;也是默認…

從大數據視角理解時序數據庫選型:為何選擇 Apache IoTDB?

目錄一、什么是時序數據庫&#xff1f;為什么你需要它&#xff1f;&#x1f527;典型應用場景&#xff1a;二、時序數據庫選型維度有哪些&#xff1f;三、為什么推薦 Apache IoTDB&#xff1f;&#x1f9e0; Apache 頂級項目&#xff0c;工業 IoT 場景原生支持&#x1f680; 性…

[ MySQL 數據庫 ] 環境安裝配置和使用

目錄 一. 數據庫(DataBase) 1.定義: 2. 常見的數據庫產品&#xff1a; 3. MySQL數據庫 (1). 介紹 : (2). cmd命令行方式連接 MySQL (3). MySQL的常用命令 二. MySQL數據庫 環境安裝及配置 三. SQL 1.定義 : 2. DDL (1)數據庫 (2)數據表 1. 字段(列)和記錄(行) 2. 表特征 3.…