插入排序,歸併排序,快速排序的實現和速度比較(包含二分法查詢所有匹配元素)
最近在學習排序演算法,實現後比較了花費時間情況,現在總結一下
插入排序的時間複雜度是O(n²),是一種很直觀的排序方式。歸併排序為O(nlogn),實現起來也比較簡單。快速排序平均時間複雜度也是O(nlogn),實現起來比歸併複雜一些。經過比較發現快速排序比歸併排序要快一些,大概一倍的時間,資料越大,效果越明顯。我嘗試用5000萬長度的隨機陣列成的陣列進行排序,歸併排序大概用了50s左右,期間出現過oom,比較消耗堆疊的空間,而快速排序則很穩定,實現的時候的不會額外建立陣列,全是在原陣列之上的操作,主要是swap操作,多次測試大概只用了20s左右的時間,也是5000萬長度的資料。然後做了簡單的二分查詢,實現了對排序陣列的指定的相等元素全部查找出來。
這是歸併排序花費的時間:
這是快速排序花費的時間
下面是具體程式碼實現:
import java.util.ArrayList; import java.util.List; import java.util.Random; public class MergeSort { private static <T extends Comparable<? super T>> void mergeSort(T [] arr){ // T [] tempArr= (T []) new Comparable[arr.length]; mergeSort(arr, 0, arr.length - 1); } private static <T extends Comparable<? super T>> void mergeSort(T[] arr, int left, int right) { if (left < right){ int mid = (left + right) / 2; mergeSort(arr, left, mid); mergeSort(arr, mid + 1, right); merge(arr, left, mid, right); } } private static <T extends Comparable<? super T>> void merge(T[] arr, int left, int mid, int rightEnd) { T [] temp = (T []) new Comparable[rightEnd - left + 1]; // System.out.println(temp); int leftEnd = mid; int right = mid + 1; int tempPos = 0; int numOfObj = rightEnd - left + 1; while(left <= leftEnd && right <= rightEnd){ if (arr[left].compareTo(arr[right]) <= 0){ temp[tempPos ++] = arr[left ++]; }else { temp[tempPos ++] = arr[right ++]; } } while (left <= leftEnd) { temp[tempPos++] = arr[left++]; } while (right <= rightEnd) { temp[tempPos++] = arr[right++]; } for (int i = numOfObj - 1; i >= 0;){ arr[rightEnd--] = temp[i--]; } } private static <T extends Comparable<? super T>> void quickSort(T [] arr){ quickSort(arr, 0, arr.length - 1); } private static <T extends Comparable<? super T>> void quickSort(T[] arr, int start, int end) { if (end - start < 8) { insertSort(arr, start, end); } else { T key = prepQuickSort(arr, start, end); int leftIndex = start; int rightIndex = end - 1; for ( ; ;) { while (arr[++leftIndex].compareTo(key) < 0) { } while (arr[--rightIndex].compareTo(key) > 0) { } if (leftIndex > rightIndex) { break; } else { swapByReference(arr, leftIndex, rightIndex); } } swapByReference(arr, leftIndex, end - 1); quickSort(arr, start, leftIndex - 1); quickSort(arr, leftIndex + 1, end); } } private static <T extends Comparable<? super T>> T prepQuickSort(T[] arr, int left, int right) { int mid = (left + right) / 2; if (arr[left].compareTo(arr[mid]) > 0) swapByReference(arr, left, mid); if (arr[left].compareTo(arr[right]) > 0) swapByReference(arr, left, right); if (arr[mid].compareTo(arr[right]) > 0) swapByReference(arr, mid, right); swapByReference(arr, mid, right - 1); return arr[right -1]; } private static <T extends Comparable<? super T>> void insertSort(T[] arr) { insertSort(arr, 0, arr.length); } private static <T extends Comparable<? super T>> void insertSort(T[] arr, int start, int end) { T min; int index; for (int i = start; i < end -1; i ++){ min = arr[i]; index = i; for (int j = i + 1; j < end; j++){ if (min.compareTo(arr[j]) > 0){ min = arr[j]; index = j; } } swapByReference(arr, i, index); } } private static <T extends Comparable<? super T>> void swapByReference(T[] arr, int before, int after) { if (before == after) return; else { T tmp; tmp = arr[before]; arr[before] = arr[after]; arr[after] = tmp; } } public static <T extends Comparable<? super T>> List binarySearch(T [] arr, T goal){ if (arr == null || arr.length < 1 ) return null; int left = 0; int right = arr.length -1; if (arr[left].compareTo(goal) > 0 || arr[right].compareTo(goal) < 0) return null; int mid = right / 2; while(left < right){ if (arr[mid].compareTo(goal) == 0){ List list = new ArrayList<Integer>(); int eqLeft = getEqualsBound(arr, mid, false); int eqRight = getEqualsBound(arr, mid, true); for (int index = eqLeft; index <= eqRight; index ++){ list.add(index); } return list; } else if (arr[mid].compareTo(goal) > 0) right = mid - 1; else left = mid + 1; mid = (left + right) / 2; } return null; } private static <T extends Comparable<? super T>> int getEqualsBound(T[] arr, int location, boolean sequence) { int result = location; if (sequence){ while(arr[location].compareTo(arr[++result]) == 0){ } return result - 1; }else { while(arr[location].compareTo(arr[--result]) == 0){ } return result + 1; } } public static void main(String[] args) { Integer[] arr = {16,2,4,3,1,5,6,0,2,4,3,11,14,16,12,9,8,11,13,15,18,20,19,11,22,23,9,6,3,4,5,1,1,0,7,4,3,4,5,1,14,16}; Integer[] arr1 = {2,2,2,2,2,2,2,2,2,2}; List<Integer> list = new ArrayList<Integer>(); Random random = new Random(); for (int i= 0; i< 50000000; i++){ list.add(random.nextInt(10000000)); } Integer [] mkArr = list.toArray(new Integer[0]); long startTime = System.currentTimeMillis(); System.out.println("start time is " + startTime + " ms"); quickSort(mkArr); System.out.println("first node is " + mkArr[0] + " , mid node is " + mkArr[mkArr.length/2] + " , last node is " + mkArr[mkArr.length -1]); System.out.println(binarySearch(mkArr, 4000000)); long stopTime = System.currentTimeMillis(); System.out.println("end time is " + stopTime + " ms"); System.out.println("cost time is " + (stopTime - startTime) + " ms"); }
相關推薦
插入排序,歸併排序,快速排序的實現和速度比較(包含二分法查詢所有匹配元素)
最近在學習排序演算法,實現後比較了花費時間情況,現在總結一下插入排序的時間複雜度是O(n²),是一種很直觀的排序方式。歸併排序為O(nlogn),實現起來也比較簡單。快速排序平均時間複雜度也是O(nlogn),實現起來比歸併複雜一些。經過比較發現快速排序比歸併排序要快一些,大
排序演算法整理:氣泡排序、堆排序、插入排序、歸併操作、快速排序、希爾排序、選擇排序
SortUtils.java package prms.utils.sort; import java.util.Arrays; /** * @ClassName: SortUtils * @Description: <p> 排序演算法 工具類 &l
有一個整數陣列,請你根據快速排序的思路,找出陣列中第K大的數。 給定一個整數陣列a,同時給定它的大小n和要找的K(K在1到n之間),請返回第K大的數,保證答案存在。
一, 原快速排序的實現 http://blog.csdn.net/taotaoah/article/details/50987837 using System; namespace taotao {
主元素,中位數以及快速排序問題(分治法問題)
IBM最後有道求主元素的題目,一個數組有N個元素,其中有超過N/2的元素相同,請找出這個元素。時間複雜度為O(n) 方法1: 如果一個元素的個數超過N/2則這個元素必然是這N個元素的中位數。則這個題目是找中位數。方法是通過快速排序變化的來的演算法。 程式碼如下: #incl
氣泡排序,選擇排序、二分法查詢圖示以及程式碼實現
氣泡排序 請看下面的這個栗子: 需要排序的陣列arr = {99,88,77,55,66,44}; 具體排序細節各位客官請看圖: 程式碼實現: public class BubbleSort { public static void main(String[] ar
高階排序演算法【2】--快速排序、歸併排序、堆排序
4、快速排序 從數列中挑出一個元素,稱為基準; 重新排列數列,所有元素比基準小的擺放在基準前面,所有元素比基準大的擺在基準後面; 在這個分割槽結束之後,該基準就位於數列的中間位置; 遞迴地對基準左右兩邊的數列進行排序。 快速排序程式碼——第一步 def qui
常見的演算法:二分法查詢,氣泡排序和選擇排序
今天主要說一下常見的演算法 ,於是我百度了一下點進那 “ 牛逼 ” 的知乎看了一眼 ,完蛋了 ,這都是些神馬 ??? 我怎麼一個都不會呢 ,我要的可是那種很常見的演算法啊 ,好吧 ,無形中又被深深的傷了一刀 ,好在我迅速調節狀態 。管他呢 ,我就按照自己 low
排序演算法02——插入排序(直接、折半)、快速排序
插入排序:插入排序的思路就是,前面的陣列已經有序(從第二個數看來,第一個數已經有序了,它只要找到自己的插入點插入就行了;然後第三個數看前兩個數都已經有序了....以此類推),下標為i的這個值依次與前面的值比較,找到合適的地方就可以直接插入了。但是,陣列的插入是需要插入位以後的
歸併排序(包含逆序數對的個數51Nod1019)
歸併排序是效率很好的排序方式,和快排效率一樣高,但在穩定性上優於快排,下面我們來介紹歸併排序。 歸併排序運用遞迴將序列不斷二分(其原理就是分治),就像一棵樹不斷向下分支,最後分到只剩一個元素,這樣這個元素就可當做有序的,因為只有一個元素嘛。然後是合併,怎麼分出來就怎麼合併回去,不過既然是排序,
PHP二分法查詢、快速排序、氣泡排序
二分法查詢: /* 遞迴呼叫實現二分法查詢 //$search 函式 $array為陣列,$K為要找的值,$low為查詢範圍的最小鍵值,$high為查詢範圍的最大鍵值 //intval返回整數值*/ function search($array,$k,$low=0,$high=0){
python中的冒泡、快速、堆排序及二分法查詢
氣泡排序 它重複地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果他們的順序(如從大到小、首字母從A到Z)錯誤就把他們交換過來。走訪元素的工作是重複地進行直到沒有相鄰元素需要交換,也就是說該元素已經排序完成。 第一種 def bubble_sort(
快速排序演算法原理及實現(單軸快速排序、三向切分快速排序、雙軸快速排序)
歡迎探討,如有錯誤敬請指正 1. 單軸快速排序的基本原理 快速排序的基本思想就是從一個數組中任意挑選一個元素(通常來說會選擇最左邊的元素)作為中軸元素,將剩下的元素以中軸元素作為比較的標準,將小於等於中軸元素的放到中軸元素的左邊,將大於中軸元素的放到中軸元素的右邊,然後以當前中軸元素的位置為界,將左半部分子
雙路快速排序演算法及三路快速排序演算法視覺化
雙路快速排序演算法 工具類 import java.awt.*; import java.awt.geom.Ellipse2D; import java.awt.geom.Rectangle2D; import java.lang.Interrup
五十道程式設計小題目 --- 28 八大排序演算法 java 之 06快速排序
6. 交換排序—快速排序(Quick Sort) 快速排序演算法介紹 快速排序和歸併排序都使用分治法來設計演算法,區別在於歸併排序把陣列分為兩個基本等長的子陣列,分別排好序之後還要進行歸併(Merge)操作,而快速排序拆分子陣列的時候顯得更有藝術,取一
排序演算法c語言描述-快速排序隨機化
今天在做資料結構排序實驗的時候,使用的快速排序。按理,我印象中快排是很高效的,不過,這次400w的資料,排了2659秒,有點意想不到,讓我一度懷疑了演算法是否寫錯了。 不過,認真分析,認真想想後, 也就釋然了。 快排其實就是冒泡的升級版。 每次遞迴,把當前序列分成兩部分,
資料結構 8 基礎排序演算法詳解、快速排序的實現、瞭解分治法
## 快速排序 快速排序與氣泡排序一樣,同樣是屬於`交換排序` 叫做快速排序也是有原因的。因為它採用了**分治法的概念** ![image.png](https://file.chaobei.xyz/blogs/image_1588862421197.png_imagess) 其中最重要的一個概念就是
Java中陣列的補充方法(增強版遍歷、逆序、氣泡排序、二分法查詢)
陣列的補充方法 在《陣列》文章中簡單的介紹了陣列的基本格式和實現案例,此處不做說明,此文主要是補充一些陣列的使用方法。例如:增強版的遍歷、逆序、氣泡排序、二分法查詢。 增強版遍歷: 1.與普通遍歷的區別: 普通的遍歷給人的直觀感覺不是很好,輸出的元素都是排列不好看,所以需
常見排序演算法的基本原理、程式碼實現和時間複雜度分析
排序演算法無論是在實際應用還是在工作面試中,都扮演著十分重要的角色。最近剛好在學習演算法導論,所以在這裡對常見的一些排序演算法的基本原理、程式碼實現和時間複雜度分析做一些總結 ,也算是對自己知識的鞏固。 說明: 1.本文所有的結果均按照非降序排列; 2.本文所有的程式均用c++實現,
Java之陣列排序及二分法查詢
首先先介紹兩種最基本的陣列排序方法:冒泡法和選擇法。 冒泡法排序:依次比較相鄰的兩個元素,如果第一個比第二個大,則交換他們兩個,如此一輪比較下來會產生一個最大的數位於陣列末尾,第二次比較則進行到陣列長度-1個元素,以此類推。 /** *
如何使用雲效看板,讓需求持續快速地流動和交付
雲效看板支援看板方法標準實踐,幫助團隊更好的協作和管理交付過程。通過雲效看板功能可以幫助團隊: 更好地視覺化端到端價值(需求)流動,確保產品、開發、測試等職能的前後拉通; 支援任務按所屬模組或不同端展開為子列,確保不同模組或不同端任務向所屬的需求對齊;