您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“Java集合和數(shù)據(jù)結(jié)構(gòu)排序的實例介紹”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“Java集合和數(shù)據(jù)結(jié)構(gòu)排序的實例介紹”吧!
概念
插入排序
直接插入排序
代碼實現(xiàn)
性能分析
希爾排序
代碼實現(xiàn)
性能分析
選擇排序
直接選擇排序
代碼實現(xiàn)
性能分析
堆排序
代碼實現(xiàn)
性能分析
交換排序
冒泡排序
代碼實現(xiàn)
性能分析
快速排序
代碼實現(xiàn)
性能分析
非遞歸實現(xiàn)快速排序
代碼實現(xiàn)
性能分析
歸并排序
歸并排序
代碼實現(xiàn)
性能分析
非遞歸實現(xiàn)歸并排序
代碼實現(xiàn)
性能分析
海量數(shù)據(jù)的排序問題
排序,就是使一串記錄,按照其中的某個或某些關(guān)鍵字的大小,遞增或遞減的排列起來的操作。
平時的上下文中,如果提到排序,通常指的是排升序(非降序)。
通常意義上的排序,都是指的原地排序(in place sort)。
穩(wěn)定性: 兩個相等的數(shù)據(jù),如果經(jīng)過排序后,排序算法能保證其相對位置不發(fā)生變化,則我們稱該算法是具備穩(wěn)定性的排序算法。
整個區(qū)間被分為
有序區(qū)間
無序區(qū)間
每次選擇無序區(qū)間的第一個元素,在有序區(qū)間內(nèi)選擇合適的位置插入
邏輯代碼:
public class InsertSort { 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; } } }
調(diào)試代碼:
public class TestDemo { public static void main(String[] args) { int[] array = {10,3,2,7,19,78,65,127}; System.out.println("排序前:" + Arrays.toString(array)); InsertSort.insertSort(array); System.out.println("排序后:" + Arrays.toString(array)); } }
該代碼的執(zhí)行結(jié)果為:
可見,實現(xiàn)了對原數(shù)組的升序排序。
時間復(fù)雜度:
最好情況:O(n)【數(shù)據(jù)有序】
平均情況:O(n2)
最壞情況:O(n2)【數(shù)據(jù)逆序】
空間復(fù)雜度:O(1)
穩(wěn)定性:穩(wěn)定
對于直接插入排序:越有序越快。另外,直接插入排序會用在一些排序的優(yōu)化上。
希爾排序法又稱縮小增量法。希爾排序法的基本思想是:先選定一個整數(shù),把待排序文件中所有記錄分成個組,所有距離為的記錄分在同一組內(nèi),并對每一組內(nèi)的記錄進(jìn)行排序。然后,取,重復(fù)上述分組和排序的工作。當(dāng)?shù)竭_(dá)=1時, 所有記錄在統(tǒng)一組內(nèi)排好序。
希爾排序是對直接插入排序的優(yōu)化。
當(dāng)gap > 1時都是預(yù)排序,目的是讓數(shù)組更接近于有序。當(dāng)gap == 1時,數(shù)組已經(jīng)接近有序的了,這樣就會很快。這樣整體而言,可以達(dá)到優(yōu)化的效果。我們實現(xiàn)后可以進(jìn)行性能測試的對比。
邏輯代碼:
public class ShellSort { public static void shell(int[] array,int gap) { for (int i = gap; i < array.length; i = i + gap) { int temp = array[i]; int j = i-gap; for (; j >= 0; j = j-gap) { if (array[j] > temp) { array[j+gap] = array[j]; }else { break; } } array[j+gap] = temp; } } public static void shellSort(int[] array) { int[] drr = {5,3,1};//增量數(shù)組-->沒有明確的規(guī)定,但保證為素數(shù)的增量序列 for (int i = 0; i < drr.length; i++) { shell(array,drr[i]); } } }
測試代碼:
public class TestDemo { public static void main(String[] args) { int[] array = {10,3,2,7,19,78,65,127}; System.out.println("排序前:" + Arrays.toString(array)); ShellSort.shellSort(array); System.out.println("排序后:" + Arrays.toString(array)); } }
該代碼的執(zhí)行結(jié)果為:
可見,實現(xiàn)了對原數(shù)組的升序排序。
時間復(fù)雜度:
最好情況:O(n)【數(shù)據(jù)有序】
平均情況:O(n1.3)
最壞情況: O(n2) 【比較難構(gòu)造】
空間復(fù)雜度:O(1)
穩(wěn)定性:不穩(wěn)定
每一次從無序區(qū)間選出最大(或最?。┑囊粋€元素,存放在無序區(qū)間的最后(或最前),直到全部待排序的數(shù)據(jù)元素排完 。
邏輯代碼:
public class SelectSort { public static void selectSort(int[] array) { for (int i = 0; i < array.length-1; i++) { for (int j = i+1; j < array.length; j++) { if (array[i] > array[j]) { int temp = array[j]; array[j] = array[i]; array[i] = temp; } } } } }
測試代碼:
public class TestDemo { public static void main(String[] args) { int[] array = {10,3,2,7,19,78,65,127}; System.out.println("排序前:" + Arrays.toString(array)); SelectSort.selectSort(array); System.out.println("排序后:" + Arrays.toString(array)); } }
該代碼的執(zhí)行結(jié)果為:
可見,實現(xiàn)了對原數(shù)組的升序排序。
時間復(fù)雜度 : 不管是最好情況還是最壞情況都是O(n2) 【數(shù)據(jù)不敏感】
空間復(fù)雜度: O(1)
穩(wěn)定性:不穩(wěn)定
基本原理也是選擇排序,只是不在使用遍歷的方式查找無序區(qū)間的最大的數(shù),而是通過堆來選擇無序區(qū)間的最大的數(shù)。
注意:排升序要建大堆;排降序要建小堆。
邏輯代碼:
public class HeapSort { public static void heapSort(int[] array) { PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1-o2; } }); for (int i = 0; i < array.length; i++) { priorityQueue.add(array[i]); } for (int i = 0; i < array.length; i++) { array[i] = priorityQueue.poll(); } } }
測試代碼:
public class TestDemo { public static void main(String[] args) { int[] array = {10,3,2,7,19,78,65,127}; System.out.println("排序前:" + Arrays.toString(array)); HeapSort.heapSort(array); System.out.println("排序后:" + Arrays.toString(array)); } }
該代碼的執(zhí)行結(jié)果為:
可見,實現(xiàn)了對原數(shù)組的升序排序。
時間復(fù)雜度:不管是最好的情況還是最壞的情況都是O(n * log(n)) 。
空間復(fù)雜度:O(1)。
穩(wěn)定性:不穩(wěn)定
在無序區(qū)間,通過相鄰數(shù)的比較,將最大的數(shù)冒泡到無序區(qū)間的最后,持續(xù)這個過程,直到數(shù)組整體有序。
邏輯代碼:
public class BubbleBort { public static void bubbleBort(int[] array) { for (int i = 0; i < array.length-1; i++) { for (int j = 0; j < array.length-i-1; j++) { if (array[j] > array[j+1]) { int temp = array[j]; array[j] = array[j+1]; array[j+1] = temp; } } } } }
測試代碼:
public class TestDemo { public static void main(String[] args) { int[] array = {10,3,2,7,19,78,65,127}; System.out.println("排序前:" + Arrays.toString(array)); BubbleBort.bubbleBort(array); System.out.println("排序后:" + Arrays.toString(array)); } }
該代碼的執(zhí)行結(jié)果為:
可見,實現(xiàn)了對原數(shù)組的升序排序。
時間復(fù)雜度:
最好情況:O(n)【數(shù)據(jù)有序】
平均情況:O(n2)
最壞情況: O(n2) 【數(shù)據(jù)逆序】
空間復(fù)雜度:O(1)。
穩(wěn)定性:穩(wěn)定
從待排序區(qū)間選擇一個數(shù),作為基準(zhǔn)值(pivot);
Partition: 遍歷整個待排序區(qū)間,將比基準(zhǔn)值小的(可以包含相等的)放到基準(zhǔn)值的左邊,將比基準(zhǔn)值大的(可以包含相等的)放到基準(zhǔn)值的右邊;
采用分治思想,對左右兩個小區(qū)間按照同樣的方式處理,直到小區(qū)間的長度 = 1,代表已經(jīng)有序,或者小區(qū)間的長度 = 0,代表沒有數(shù)據(jù)。
邏輯代碼:
public class QuickSort { public static void quick(int[] array,int low,int high) { if (low < high) { int piv = piovt(array,low,high);//找基準(zhǔn) quick(array,low,piv-1); quick(array,piv+1,high); } } private static int piovt(int[] array,int start,int end) { int temp = array[start]; while (start < end) { while (start < end && array[end] >= temp) { end--; } array[start] = array[end]; while (start < end && array[start] < temp) { start++; } array[end] = array[start]; } array[start] = temp; return start; } public static void quickSort(int[] array) { quick(array,0,array.length-1); } }
測試代碼:
public class TestDemo { public static void main(String[] args) { int[] array = {10,3,2,7,19,78,65,127}; System.out.println("排序前:" + Arrays.toString(array)); QuickSort.quickSort(array); System.out.println("排序后:" + Arrays.toString(array)); } }
該代碼的執(zhí)行結(jié)果為:
可見,實現(xiàn)了對原數(shù)組的升序排序。
時間復(fù)雜度:
最好情況:O(n * log(n))
平均情況:O(n * log(n))
最壞情況: O(n2)
空間復(fù)雜度:
最好情況:O(log(n))
平均情況:O(log(n))
最壞情況:O(n)
穩(wěn)定性:不穩(wěn)定
邏輯代碼:
/** * 非遞歸實現(xiàn)快速排序 */ public class QuickSortNor { public static void quickSortNor(int[] array) { int low = 0; int high = array.length - 1; int piv = piovt(array, low, high); Stack<Integer> stack = new Stack<>(); if (piv > low + 1) { stack.push(low); stack.push(piv - 1); } if (piv < high - 1) { stack.push(piv + 1); stack.push(high); } while (!stack.isEmpty()) { high = stack.pop(); low = stack.pop(); piv = piovt(array, low, high); if (piv > low + 1) { stack.push(low); stack.push(piv - 1); } if (piv < high - 1) { stack.push(piv + 1); stack.push(high); } } } private static int piovt(int[] array, int start, int end) { int temp = array[start]; while (start < end) { while (start < end && array[end] >= temp) { end--; } array[start] = array[end]; while (start < end && array[start] < temp) { start++; } array[end] = array[start]; } array[start] = temp; return start; } }
測試代碼:
public class TestDemo { public static void main(String[] args) { int[] array = {10,3,2,7,19,78,65,127}; System.out.println("排序前:" + Arrays.toString(array)); QuickSortNor.quickSortNor(array); System.out.println("排序后:" + Arrays.toString(array)); } }
該代碼的執(zhí)行結(jié)果為:
可見,實現(xiàn)了對原數(shù)組的升序排序。
時間復(fù)雜度: O(n * log(n))
空間復(fù)雜度:
最好情況:O(log(n))
最壞情況:O(n)
穩(wěn)定性:不穩(wěn)定
歸并排序(MERGE-SORT)是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer)的一個非常典型的應(yīng)用。將已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合并成一個有序表,稱為二路歸并。
邏輯代碼:
public class MergeSort { public static void merge(int[] array, int start, int mid, int end) { int s1 = start; int s2 = mid + 1; int[] temp = new int[end - start + 1]; int k = 0; while (s1 <= mid && s2 <= end) { if (array[s1] <= array[s2]) { temp[k++] = array[s1++]; } else { temp[k++] = array[s2++]; } } while (s1 <= mid) { temp[k++] = array[s1++]; } while (s2 <= end) { temp[k++] = array[s2++]; } for (int i = 0; i < temp.length; i++) { array[i + start] = temp[i]; } } public static void mergeSortInternal(int[] array, int low, int high) { if (low >= high) return; //先分解 int mid = (low + high) / 2; mergeSortInternal(array, low, mid); mergeSortInternal(array, mid + 1, high); //再合并 merge(array, low, mid, high); } public static void mergeSort(int[] array) { mergeSortInternal(array, 0, array.length - 1); } }
測試代碼:
public class TestDemo { public static void main(String[] args) { int[] array = {10,3,2,7,19,78,65,127}; System.out.println("排序前:" + Arrays.toString(array)); MergeSort.mergeSort(array); System.out.println("排序后:" + Arrays.toString(array)); } }
該代碼的執(zhí)行結(jié)果為:
可見,實現(xiàn)了對原數(shù)組的升序排序。
時間復(fù)雜度: O(n * log(n))
空間復(fù)雜度:O(n)
穩(wěn)定性:穩(wěn)定
邏輯代碼:
/** * 非遞歸實現(xiàn)歸并排序 */ public class MergeSortNor { public static void merge(int[] array, int gap) { int s1 = 0; int e1 = s1 + gap - 1; int s2 = e1 + 1; int e2 = s2 + gap - 1 < array.length ? s2 + gap - 1 : array.length - 1; int[] temp = new int[array.length]; int k = 0; while (s2 < array.length) { while (s1 <= e1 && s2 <= e2) { if (array[s1] <= array[s2]) { temp[k++] = array[s1++]; } else { temp[k++] = array[s2++]; } } while (s1 <= e1) { temp[k++] = array[s1++]; } while (s2 <= e2) { temp[k++] = array[s2++]; } s1 = e2+1; e1 = s1+gap-1; s2 = e1+1; e2 = s2 + gap - 1 < array.length ? s2 + gap - 1 : array.length - 1; } while (s1 < array.length) { temp[k++] = array[s1++]; } for (int i = 0; i < temp.length; i++) { array[i] = temp[i]; } } public static void mergeSortNor(int[] array) { for (int i = 1; i < array.length; i *= 2) { merge(array, i); } } }
測試代碼:
public class TestDemo { public static void main(String[] args) { int[] array = {10,3,2,7,19,78,65,127}; System.out.println("排序前:" + Arrays.toString(array)); MergeSortNor.mergeSortNor(array); System.out.println("排序后:" + Arrays.toString(array)); } }
該代碼的執(zhí)行結(jié)果為:
可見,實現(xiàn)了對原數(shù)組的升序排序。
時間復(fù)雜度: O(n * log(n))
空間復(fù)雜度:O(n)
穩(wěn)定性:穩(wěn)定
外部排序:排序過程需要在磁盤等外部存儲進(jìn)行的排序
前提:內(nèi)存只有 1G,需要排序的數(shù)據(jù)有 100G
因為內(nèi)存中因為無法把所有數(shù)據(jù)全部放下,所以需要外部排序,而歸并排序是最常用的外部排序。
先把文件切分成 200 份,每個 512 M
分別對 512 M 排序,因為內(nèi)存已經(jīng)可以放的下,所以任意排序方式都可以
進(jìn)行 200 路歸并,同時對 200 份有序文件做歸并過程,最終結(jié)果就有序了
排序總結(jié)
到此,相信大家對“Java集合和數(shù)據(jù)結(jié)構(gòu)排序的實例介紹”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。