八大排序演算法JAVA實現(時間複雜度O(n-logn)篇)
本文講述時間複雜度為n*logn的排序演算法:歸併排序、快速排序、堆排序以及希爾排序的原理、Java實現以及變形應用。
一、歸併排序
- 原理:把兩個有序數列合併為一個有序數列。需遞迴實現。
- Java實現:
1 public int[] mergeSort(int[] a, int n) 2 { 3 return doMergeSort(a, n, 0, n - 1); 4 } 5 public int[] doMergeSort(int[] a, int n, int start, int end) 6 { 7 int[] res = new int[n]; 8 if (n <= 1) 9 { 10 res[0] = a[start]; 11 return res; 12 } 13 // n>=2時,對其左右陣列進行處理 14 int half = n / 2; 15 int leftEnd = start + half - 1; 16 int rightStart = leftEnd + 1; 17 //遞迴呼叫本函式,獲取有序的左陣列以及右陣列18 int[] left = doMergeSort(a, half, start, leftEnd); 19 int[] right = doMergeSort(a, n - half, rightStart, end); 20 // 將左右序列合併 21 int k = 0, i = 0, j = 0; 22 while (i < half && j < n - half) 23 {//由前往後比較兩個序列,取較小值填充到res中,取值後該序列往後移動取下一個值比較 24 if(left[i] <= right[j]) 25 { 26 res[k++] = left[i++]; 27 } 28 else 29 { 30 res[k++] = right[j++]; 31 } 32 } 33 // 剩餘的直接放入 34 while (i < half) 35 { 36 res[k++] = left[i++]; 37 } 38 while (j < n - half) 39 { 40 res[k++] = right[j++]; 41 } 42 return res; 43 }
二、快速排序
- 原理:每一次將一個數放在一個左邊的數全部比它小,且右邊的數全部比它大的位置,然後遞迴呼叫函式,將其左右序列排好。這邊有一個比較好理解的做法:在陣列的左邊維護一個小於區間,在遍歷的時候,發現比當前數小的數字的時候,將,擴增小於區間,並其放到小於區間內,結束後將當前數填充在小於區間後即可。
- Java實現:
1 public int[] quickSort(int[] a, int n) 2 { 3 doQuickSort(a, n, 0, n - 1); 4 return a; 5 } 6 public void doQuickSort(int[] a, int n, int start, int end) 7 { 8 if (n > 1) 9 { 10 int current = a[end]; 11 int minLen = 0;// 小於區間的長度 12 int i = start; 13 for (; i < end; i++) 14 { 15 if (a[i] < current) 16 {//發現比當前數小的數,擴充小於區間 17 int temp = a[start + minLen]; 18 a[start + minLen] = a[i]; 19 a[i] = temp; 20 minLen++; 21 } 22 } 23 a[end] = a[start + minLen]; 24 a[start + minLen] = current; 25 //當前位置已經確定,排左右序列 26 doQuickSort(a, minLen, start, start + minLen - 1); 27 doQuickSort(a, n - minLen - 1, start + minLen + 1, end); 28 } 29 }
-
變形應用:三色排序練習題
有一個只由0,1,2三種元素構成的整數陣列,請使用交換、原地排序而不是使用計數進行排序。給定一個只含0,1,2的整數陣列A及它的大小,請返回排序後的陣列。保證陣列大小小於等於500。
測試樣例:
[0,1,1,0,2,2],6
返回:[0,0,1,1,2,2] |
三、堆排序
- 原理:維護一個大根堆(小根堆同理),即維護一棵二叉樹,該數子節點永遠比父節點小。每次在大根堆中取出根,根為此時待排序列最大值,放在待排序列最後,然後調整大根堆,重複上訴過程即可。
- Java實現:博主不太會插圖,關於大小根堆的調整細節可自行百度。原理總結來說是從最後一個非葉子節點開始,往前調整。設當前調整的非葉子節點為n,選舉n,n的左,n的右三個節點的最大值作為父節點。且每次調整了靠前的非葉子節點的值後,可能會破壞下面的數的大根堆規則,需要再次調整。嗯我覺得我並沒有講清楚,百度看看圖就好。
public int[] heapSort(int[] a, int n) { for (int len = n; len > 0; len--) {// len為構建的堆的大小 for (int i = len / 2 - 1; i >= 0; i--) {// 從後往前遍歷非葉子節點 while (2 * i + 1 < len) { int j = 2 * i + 1;// 左節點序號 if (j + 1 < len && a[j] < a[j + 1]) { j++; } if (a[i] < a[j]) { int temp = a[j]; a[j] = a[i]; a[i] = temp; i = j; } else { break; } } } int temp = a[len - 1]; a[len - 1] = a[0]; a[0] = temp; } return a; }
- 變形應用:常規應用如在1000+個數中找出最大的10個數之類的。
已知一個幾乎有序的陣列,幾乎有序是指,如果把陣列排好順序的話,每個元素移動的距離可以不超過k,並且k相對於陣列來說比較小。請選擇一個合適的排序演算法針對這個資料進行排序。 給定一個int陣列A,同時給定A的大小n和題意中的k,請返回排序後的陣列。 測試樣例: [2,1,4,3,6,5,8,7,10,9],10,2 返回:[1,2,3,4,5,6,7,8,9,10] 解析:維護一個大小為k的小根堆,每次調整完這個小根堆後,最小值就會出現在第一位,此時移除第一位,新增後一位數進來,繼續調整這個小根堆即可。可以想象為一個從前往後移動的滑動視窗,滑動視窗中是一個小根堆。 |
四、希爾排序
- 原理:變形後的插入排序,每個數只與它前面固定步長的倍數的位置進行比對。如:步長step,當前數與它前面step,step*2,step*3....位置進行比較,插入到合適的位置。
- Java實現:
public int[] shellSort(int[] a, int n) { // 步長選擇 for (int k = 1, step = 10; step > 1; k++) { step = n / (2 * k); for (int i = step; i < n; i++) { if (a[i] < a[i - step]) { int temp = a[i]; a[i] = a[i - step]; a[i - step] = temp; int pre = i - step; while (pre - step > 0) { if (a[pre] < a[pre - step]) { temp = a[pre]; a[pre] = a[pre - step]; a[pre - step] = temp; pre -= step; } else { break; } } } } } return a; }
相關推薦
八大排序演算法JAVA實現(時間複雜度O(n-logn)篇)
本文講述時間複雜度為n*logn的排序演算法:歸併排序、快速排序、堆排序以及希爾排序的原理、Java實現以及變形應用。 一、歸併排序 原理:把兩個有序數列合併為一個有序數列。需遞迴實現。 Java實現: 1 public int[] mergeSort(in
八大排序演算法JAVA實現(時間複雜度O(n-n)篇)
本文主要描述3個時間複雜度為n2的排序演算法:氣泡排序、選擇排序、插入排序。 1.氣泡排序:由陣列頭部開始,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。每次交換完成後,當前陣列最大值就會被放在最後。 1 public int[] bubbleSort
C語言八大排序演算法(包括穩定性、時間複雜度等)(收藏)
C語言八大排序演算法 概述 排序有內部排序和外部排序,內部排序是資料記錄在記憶體中進行排序,而外部排序是因排序的資料很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存。我們這裡說說八大排序就是內部排序。 當n較大,則應採用時間複雜度為O(nlog2n)的排序方法:快速排序、堆排
堆排序的JAVA實現及時間複雜度分析
堆排序是一個比較常用的排序方式,下面是其JAVA的實現: 1. 建堆 // 對輸入的陣列進行建堆的操作 private static void buildMaxHeap(int[] array, int length) { // 遍歷所有
尋找主元素演算法(時間複雜度O(N),C#)
主元素問題:大小為N的陣列A,其主要元素是一個出現次數超過N/2的元素。 最近在學習演算法,書上發現這樣一道題,並且提供了一種遞迴演算法的概要,但是感覺不是特別好(遞迴判斷(時間複雜度大於O(N)了),還要對N的奇偶做出判斷以及使用附加陣列B),網上看了一下有一個SEO排行最靠前的(不說名字了,
Morris遍歷詳解——二叉樹先序中序後序遍歷( 時間複雜度O(N),空間複雜度O(1) )
Morris二叉樹遍歷: 來到當前的節點:Cur 如果Cur無左孩子,Cur向右移動 (Cur = Cur.right) 如果Cur有左孩子,找到Cur左子樹上最右的節點,記為 mostright
1134 最長遞增子序列(時間複雜度O(n*log(n))
基準時間限制:1 秒 空間限制:131072 KB 分值: 0 難度:基礎題 Description 給出長度為N的陣列,找出這個陣列的最長遞增子序列。(遞增子序列是指,子序列的元素是遞增的) 例如:5 1 6 8 2 4 5 10,最長遞增
【資料結構與演算法-java實現】二 複雜度分析(下):最好、最壞、平均、均攤時間複雜度的概念
上一篇文章學習了:如何分析、統計演算法的執行效率和資源消耗? 點選連結檢視上一篇文章:複雜度分析上 今天的文章學習以下內容: 最好情況時間複雜度 最壞情況時間複雜度 平均情況時間複雜度 均攤時間複雜度 1、最好與最壞情況時間複雜度 我們首先
連結串列排序演算法java實現(連結串列的快速排序、插入排序、歸併排序)
難易程度:★★ 重要性:★★★ 連結串列的排序相對陣列的排序更為複雜些,也是考察求職者是否真正理解了排序演算法(而不是“死記硬背”) 連結串列的插入排序 public class LinkedInsertSort { static cla
基礎排序演算法 java 實現(冒泡、選擇、插入、快排、歸併、堆排)
package demo; import java.util.Arrays; public class SortUtil { private static void printArr(int[] arr) { System.out.println
有1,2...一直到n的無序陣列,求排序演算法,並且要求時間複雜度為O(n),時間複雜度為O(1)
提示:用陣列值作為下標 分析: 對於一般陣列的排序顯然 O(n) 是無法完成的。 既然題目這樣要求,肯定原先的陣列有一定的規律,讓人們去尋找一種機會。 例如:原始陣列: a = [ 10, 6,9, 5,2
常見排序演算法及對應的時間複雜度和空間複雜度
轉載請註明出處: 排序演算法經過了很長時間的演變,產生了很多種不同的方法。對於初學者來說,對它們進行整理便於理解記憶顯得很重要。每種演算法都有它特定的使用場合,很難通用。因此,我們很有必要對所有常見的排序演算法進行歸納。 排序大的分類可以分為兩種:內
BFPRT演算法:時間複雜度O(n)求第k小的數字(分治演算法+快排)
去年寫了一篇《分治演算法 求第 k k k小元素
並行排序演算法——時間複雜度O(n)的排序法
最近老師講了並行的排序演算法,讓我對這個原來不是很瞭解的排序演算法產生了濃厚的興趣。並行排序方法,是指採用平行計算的方法對一組資料進行排序,理論上是在類似內排序的環境下,採用多核並行的方法讓時間降低,排序的複雜度最好的情況下能降低至O(n)左右。 排序的實質
一個時間複雜度O(n),空間複雜度為O(1)的排序演算法
其實就是利用Hash的思想,開闢一個固定長度的hash陣列用於標記待排序陣列的資料元素是否出現過。由於固定長度的hash陣列,所以空間複雜度與待排序陣列資料規模n沒有關係,也就是說空間複雜度為O(1)。
計數排序,傳說中時間複雜度O(n+k)的排序演算法
基本思想 假設數序列中小於元素a的個數為n,則直接把a放到第n+1個位置上。當存在幾個相同的元素時要做適當的調整,因為不能把所有的元素放到同一個位置上。計數排序假設輸入的元素都是0到k之間的整數。 回到頂部 參考程式碼 #include &
找出大陣列array中第k大的元素(要求時間複雜度O(n))
具體的程式碼實現:import java.util.Stack; /** * @author wuwh * @date createTime:2016年3月6日 上午12:23:14 */ public class KthBiggest { public static
最大子序列的和演算法-時間複雜度O(n)
#include<iostream> using namespace std; int MaxSubseqSum(int ar[],int n){ int ThisSum=0,MaxSu
Manacher演算法,最長迴文串,時間複雜度O(n)
最長迴文子串 問題 對於一個字串,請設計一個高效演算法,計算其中最長迴文子串的長度。 給定字串A以及它的長度n,請返回最長迴文子串的長度。 測試樣例: “abc1234321ab”,12 返回:7 中心擴充套件到Manache
php多維陣列的去重(針對任意的鍵值進行去重)--二維陣列的唯一--時間複雜度~O(n)
以二維陣列為例,來說明針對任意鍵值的去重,時間複雜度為~O(n),只用一個foreach迴圈: <?php $arr = array( '0'=>array(