Java集合和數(shù)據(jù)結(jié)構(gòu)排序?qū)嵗斀?/h1>
更新時(shí)間:2021年08月20日 09:33:42 作者:頭發(fā)都哪去了
Java的集合其實(shí)就是各種基本的數(shù)據(jù)結(jié)構(gòu)(棧,隊(duì)列,hash表等),基于業(yè)務(wù)需求進(jìn)而演變出的Java特有的數(shù)據(jù)結(jié)構(gòu)(因?yàn)椴粌H僅是基本數(shù)據(jù)結(jié)構(gòu)),這篇文章主要給大家介紹了關(guān)于Java集合和數(shù)據(jù)結(jié)構(gòu)排序的相關(guān)資料,需要的朋友可以參考下
概念
排序,就是使一串記錄,按照其中的某個(gè)或某些關(guān)鍵字的大小,遞增或遞減的排列起來(lái)的操作。
平時(shí)的上下文中,如果提到排序,通常指的是排升序(非降序)。
通常意義上的排序,都是指的原地排序(in place sort)。
穩(wěn)定性: 兩個(gè)相等的數(shù)據(jù),如果經(jīng)過(guò)排序后,排序算法能保證其相對(duì)位置不發(fā)生變化,則我們稱該算法是具備穩(wěn)定性的排序算法。


插入排序
直接插入排序
整個(gè)區(qū)間被分為
- 有序區(qū)間
- 無(wú)序區(qū)間
每次選擇無(wú)序區(qū)間的第一個(gè)元素,在有序區(qū)間內(nèi)選擇合適的位置插入
代碼實(shí)現(xiàn)
邏輯代碼:
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é)果為:

可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度:
最好情況:O(n)【數(shù)據(jù)有序】
平均情況:O(n2)
最壞情況:O(n2)【數(shù)據(jù)逆序】
空間復(fù)雜度:O(1)
穩(wěn)定性:穩(wěn)定
對(duì)于直接插入排序:越有序越快。另外,直接插入排序會(huì)用在一些排序的優(yōu)化上。
希爾排序
希爾排序法又稱縮小增量法。希爾排序法的基本思想是:先選定一個(gè)整數(shù),把待排序文件中所有記錄分成個(gè)組,所有距離為的記錄分在同一組內(nèi),并對(duì)每一組內(nèi)的記錄進(jìn)行排序。然后,取,重復(fù)上述分組和排序的工作。當(dāng)?shù)竭_(dá)=1時(shí), 所有記錄在統(tǒng)一組內(nèi)排好序。
希爾排序是對(duì)直接插入排序的優(yōu)化。
當(dāng)gap > 1時(shí)都是預(yù)排序,目的是讓數(shù)組更接近于有序。當(dāng)gap == 1時(shí),數(shù)組已經(jīng)接近有序的了,這樣就會(huì)很快。這樣整體而言,可以達(dá)到優(yōu)化的效果。我們實(shí)現(xiàn)后可以進(jìn)行性能測(cè)試的對(duì)比。
代碼實(shí)現(xià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ù)組-->沒(méi)有明確的規(guī)定,但保證為素?cái)?shù)的增量序列
for (int i = 0; i < drr.length; i++) {
shell(array,drr[i]);
}
}
}
測(cè)試代碼:
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é)果為:

可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度:
最好情況:O(n)【數(shù)據(jù)有序】
平均情況:O(n1.3)
最壞情況: O(n2) 【比較難構(gòu)造】
空間復(fù)雜度:O(1)
穩(wěn)定性:不穩(wěn)定
選擇排序
直接選擇排序
每一次從無(wú)序區(qū)間選出最大(或最?。┑囊粋€(gè)元素,存放在無(wú)序區(qū)間的最后(或最前),直到全部待排序的數(shù)據(jù)元素排完 。
代碼實(shí)現(xiàn)
邏輯代碼:
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;
}
}
}
}
}
測(cè)試代碼:
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é)果為:

可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度 : 不管是最好情況還是最壞情況都是O(n2) 【數(shù)據(jù)不敏感】
空間復(fù)雜度: O(1)
穩(wěn)定性:不穩(wěn)定
堆排序
基本原理也是選擇排序,只是不在使用遍歷的方式查找無(wú)序區(qū)間的最大的數(shù),而是通過(guò)堆來(lái)選擇無(wú)序區(qū)間的最大的數(shù)。
注意:排升序要建大堆;排降序要建小堆。
代碼實(shí)現(xiàn)
邏輯代碼:
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();
}
}
}
測(cè)試代碼:
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é)果為:

可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度:不管是最好的情況還是最壞的情況都是O(n * log(n)) 。
空間復(fù)雜度:O(1)。
穩(wěn)定性:不穩(wěn)定
交換排序
冒泡排序
在無(wú)序區(qū)間,通過(guò)相鄰數(shù)的比較,將最大的數(shù)冒泡到無(wú)序區(qū)間的最后,持續(xù)這個(gè)過(guò)程,直到數(shù)組整體有序。
代碼實(shí)現(xiàn)
邏輯代碼:
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;
}
}
}
}
}
測(cè)試代碼:
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é)果為:

可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度:
最好情況:O(n)【數(shù)據(jù)有序】
平均情況:O(n2)
最壞情況: O(n2) 【數(shù)據(jù)逆序】
空間復(fù)雜度:O(1)。
穩(wěn)定性:穩(wěn)定
快速排序
- 從待排序區(qū)間選擇一個(gè)數(shù),作為基準(zhǔn)值(pivot);
- Partition: 遍歷整個(gè)待排序區(qū)間,將比基準(zhǔn)值小的(可以包含相等的)放到基準(zhǔn)值的左邊,將比基準(zhǔn)值大的(可以包含相等的)放到基準(zhǔn)值的右邊;
- 采用分治思想,對(duì)左右兩個(gè)小區(qū)間按照同樣的方式處理,直到小區(qū)間的長(zhǎng)度 = 1,代表已經(jīng)有序,或者小區(qū)間的長(zhǎng)度 = 0,代表沒(méi)有數(shù)據(jù)。
代碼實(shí)現(xiàn)
邏輯代碼:
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);
}
}
測(cè)試代碼:
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é)果為:

可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(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)定
非遞歸實(shí)現(xiàn)快速排序
代碼實(shí)現(xiàn)
邏輯代碼:
/**
* 非遞歸實(shí)現(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;
}
}
測(cè)試代碼:
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é)果為:

可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度: O(n * log(n))
空間復(fù)雜度:
最好情況:O(log(n))
最壞情況:O(n)
穩(wěn)定性:不穩(wěn)定
歸并排序
歸并排序
歸并排序(MERGE-SORT)是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer)的一個(gè)非常典型的應(yīng)用。將已有序的子序列合并,得到完全有序的序列;即先使每個(gè)子序列有序,再使子序列段間有序。若將兩個(gè)有序表合并成一個(gè)有序表,稱為二路歸并。

代碼實(shí)現(xiàn)
邏輯代碼:
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);
}
}
測(cè)試代碼:
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é)果為:

可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度: O(n * log(n))
空間復(fù)雜度:O(n)
穩(wěn)定性:穩(wěn)定
非遞歸實(shí)現(xiàn)歸并排序
代碼實(shí)現(xiàn)
邏輯代碼:
/**
* 非遞歸實(shí)現(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);
}
}
}
測(cè)試代碼:
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é)果為:

可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度: O(n * log(n))
空間復(fù)雜度:O(n)
穩(wěn)定性:穩(wěn)定
海量數(shù)據(jù)的排序問(wèn)題
外部排序:排序過(guò)程需要在磁盤等外部存儲(chǔ)進(jìn)行的排序
前提:內(nèi)存只有 1G,需要排序的數(shù)據(jù)有 100G
因?yàn)閮?nèi)存中因?yàn)闊o(wú)法把所有數(shù)據(jù)全部放下,所以需要外部排序,而歸并排序是最常用的外部排序。
- 先把文件切分成 200 份,每個(gè) 512 M
- 分別對(duì) 512 M 排序,因?yàn)閮?nèi)存已經(jīng)可以放的下,所以任意排序方式都可以
- 進(jìn)行 200 路歸并,同時(shí)對(duì) 200 份有序文件做歸并過(guò)程,最終結(jié)果就有序了
排序總結(jié)


總結(jié)
到此這篇關(guān)于Java集合和數(shù)據(jù)結(jié)構(gòu)排序的文章就介紹到這了,更多相關(guān)Java集合和數(shù)據(jù)結(jié)構(gòu)排序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
-
詳解java WebSocket的實(shí)現(xiàn)以及Spring WebSocket
這篇文章主要介紹了詳解java WebSocket的實(shí)現(xiàn)以及Spring WebSocket ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。 2017-01-01
-
MybatisPlus自定義Sql實(shí)現(xiàn)多表查詢的示例
這篇文章主要介紹了MybatisPlus自定義Sql實(shí)現(xiàn)多表查詢的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧 2020-08-08
-
Feign實(shí)現(xiàn)跨服務(wù)文件上傳下載
這篇文章主要為大家詳細(xì)介紹了Feign實(shí)現(xiàn)跨服務(wù)文件上傳下載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下 2019-04-04
-
Springmvc ViewResolver設(shè)計(jì)實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了Springmvc ViewResolver設(shè)計(jì)實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下 2020-10-10
-
Spring Data JPA 如何使用QueryDsl查詢并分頁(yè)
這篇文章主要介紹了Spring Data JPA 如何使用QueryDsl查詢并分頁(yè),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教 2021-11-11
-
解決SpringBoot配置文件application.yml遇到的坑
這篇文章主要介紹了解決SpringBoot配置文件application.yml遇到的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教 2022-02-02
-
Windows下安裝ElasticSearch的方法(圖文)
這篇文章主要介紹了Windows下安裝ElasticSearch的方法(圖文),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧 2018-01-01
-
SpringMVC文件上傳原理及實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了SpringMVC文件上傳原理及實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下 2020-07-07
最新評(píng)論
概念
排序,就是使一串記錄,按照其中的某個(gè)或某些關(guān)鍵字的大小,遞增或遞減的排列起來(lái)的操作。
平時(shí)的上下文中,如果提到排序,通常指的是排升序(非降序)。
通常意義上的排序,都是指的原地排序(in place sort)。
穩(wěn)定性: 兩個(gè)相等的數(shù)據(jù),如果經(jīng)過(guò)排序后,排序算法能保證其相對(duì)位置不發(fā)生變化,則我們稱該算法是具備穩(wěn)定性的排序算法。
插入排序
直接插入排序
整個(gè)區(qū)間被分為
- 有序區(qū)間
- 無(wú)序區(qū)間
每次選擇無(wú)序區(qū)間的第一個(gè)元素,在有序區(qū)間內(nèi)選擇合適的位置插入
代碼實(shí)現(xiàn)
邏輯代碼:
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é)果為:
可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度:
最好情況:O(n)【數(shù)據(jù)有序】
平均情況:O(n2)
最壞情況:O(n2)【數(shù)據(jù)逆序】
空間復(fù)雜度:O(1)
穩(wěn)定性:穩(wěn)定
對(duì)于直接插入排序:越有序越快。另外,直接插入排序會(huì)用在一些排序的優(yōu)化上。
希爾排序
希爾排序法又稱縮小增量法。希爾排序法的基本思想是:先選定一個(gè)整數(shù),把待排序文件中所有記錄分成個(gè)組,所有距離為的記錄分在同一組內(nèi),并對(duì)每一組內(nèi)的記錄進(jìn)行排序。然后,取,重復(fù)上述分組和排序的工作。當(dāng)?shù)竭_(dá)=1時(shí), 所有記錄在統(tǒng)一組內(nèi)排好序。
希爾排序是對(duì)直接插入排序的優(yōu)化。
當(dāng)gap > 1時(shí)都是預(yù)排序,目的是讓數(shù)組更接近于有序。當(dāng)gap == 1時(shí),數(shù)組已經(jīng)接近有序的了,這樣就會(huì)很快。這樣整體而言,可以達(dá)到優(yōu)化的效果。我們實(shí)現(xiàn)后可以進(jìn)行性能測(cè)試的對(duì)比。
代碼實(shí)現(xià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ù)組-->沒(méi)有明確的規(guī)定,但保證為素?cái)?shù)的增量序列 for (int i = 0; i < drr.length; i++) { shell(array,drr[i]); } } }
測(cè)試代碼:
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é)果為:
可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度:
最好情況:O(n)【數(shù)據(jù)有序】
平均情況:O(n1.3)
最壞情況: O(n2) 【比較難構(gòu)造】
空間復(fù)雜度:O(1)
穩(wěn)定性:不穩(wěn)定
選擇排序
直接選擇排序
每一次從無(wú)序區(qū)間選出最大(或最?。┑囊粋€(gè)元素,存放在無(wú)序區(qū)間的最后(或最前),直到全部待排序的數(shù)據(jù)元素排完 。
代碼實(shí)現(xiàn)
邏輯代碼:
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; } } } } }
測(cè)試代碼:
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é)果為:
可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度 : 不管是最好情況還是最壞情況都是O(n2) 【數(shù)據(jù)不敏感】
空間復(fù)雜度: O(1)
穩(wěn)定性:不穩(wěn)定
堆排序
基本原理也是選擇排序,只是不在使用遍歷的方式查找無(wú)序區(qū)間的最大的數(shù),而是通過(guò)堆來(lái)選擇無(wú)序區(qū)間的最大的數(shù)。
注意:排升序要建大堆;排降序要建小堆。
代碼實(shí)現(xiàn)
邏輯代碼:
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(); } } }
測(cè)試代碼:
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é)果為:
可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度:不管是最好的情況還是最壞的情況都是O(n * log(n)) 。
空間復(fù)雜度:O(1)。
穩(wěn)定性:不穩(wěn)定
交換排序
冒泡排序
在無(wú)序區(qū)間,通過(guò)相鄰數(shù)的比較,將最大的數(shù)冒泡到無(wú)序區(qū)間的最后,持續(xù)這個(gè)過(guò)程,直到數(shù)組整體有序。
代碼實(shí)現(xiàn)
邏輯代碼:
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; } } } } }
測(cè)試代碼:
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é)果為:
可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度:
最好情況:O(n)【數(shù)據(jù)有序】
平均情況:O(n2)
最壞情況: O(n2) 【數(shù)據(jù)逆序】
空間復(fù)雜度:O(1)。
穩(wěn)定性:穩(wěn)定
快速排序
- 從待排序區(qū)間選擇一個(gè)數(shù),作為基準(zhǔn)值(pivot);
- Partition: 遍歷整個(gè)待排序區(qū)間,將比基準(zhǔn)值小的(可以包含相等的)放到基準(zhǔn)值的左邊,將比基準(zhǔn)值大的(可以包含相等的)放到基準(zhǔn)值的右邊;
- 采用分治思想,對(duì)左右兩個(gè)小區(qū)間按照同樣的方式處理,直到小區(qū)間的長(zhǎng)度 = 1,代表已經(jīng)有序,或者小區(qū)間的長(zhǎng)度 = 0,代表沒(méi)有數(shù)據(jù)。
代碼實(shí)現(xiàn)
邏輯代碼:
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); } }
測(cè)試代碼:
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é)果為:
可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(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)定
非遞歸實(shí)現(xiàn)快速排序
代碼實(shí)現(xiàn)
邏輯代碼:
/** * 非遞歸實(shí)現(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; } }
測(cè)試代碼:
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é)果為:
可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度: O(n * log(n))
空間復(fù)雜度:
最好情況:O(log(n))
最壞情況:O(n)
穩(wěn)定性:不穩(wěn)定
歸并排序
歸并排序
歸并排序(MERGE-SORT)是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer)的一個(gè)非常典型的應(yīng)用。將已有序的子序列合并,得到完全有序的序列;即先使每個(gè)子序列有序,再使子序列段間有序。若將兩個(gè)有序表合并成一個(gè)有序表,稱為二路歸并。
代碼實(shí)現(xiàn)
邏輯代碼:
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); } }
測(cè)試代碼:
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é)果為:
可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度: O(n * log(n))
空間復(fù)雜度:O(n)
穩(wěn)定性:穩(wěn)定
非遞歸實(shí)現(xiàn)歸并排序
代碼實(shí)現(xiàn)
邏輯代碼:
/** * 非遞歸實(shí)現(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); } } }
測(cè)試代碼:
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é)果為:
可見,實(shí)現(xiàn)了對(duì)原數(shù)組的升序排序。
性能分析
時(shí)間復(fù)雜度: O(n * log(n))
空間復(fù)雜度:O(n)
穩(wěn)定性:穩(wěn)定
海量數(shù)據(jù)的排序問(wèn)題
外部排序:排序過(guò)程需要在磁盤等外部存儲(chǔ)進(jìn)行的排序
前提:內(nèi)存只有 1G,需要排序的數(shù)據(jù)有 100G
因?yàn)閮?nèi)存中因?yàn)闊o(wú)法把所有數(shù)據(jù)全部放下,所以需要外部排序,而歸并排序是最常用的外部排序。
- 先把文件切分成 200 份,每個(gè) 512 M
- 分別對(duì) 512 M 排序,因?yàn)閮?nèi)存已經(jīng)可以放的下,所以任意排序方式都可以
- 進(jìn)行 200 路歸并,同時(shí)對(duì) 200 份有序文件做歸并過(guò)程,最終結(jié)果就有序了
排序總結(jié)
總結(jié)
到此這篇關(guān)于Java集合和數(shù)據(jù)結(jié)構(gòu)排序的文章就介紹到這了,更多相關(guān)Java集合和數(shù)據(jù)結(jié)構(gòu)排序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解java WebSocket的實(shí)現(xiàn)以及Spring WebSocket
這篇文章主要介紹了詳解java WebSocket的實(shí)現(xiàn)以及Spring WebSocket ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-01-01MybatisPlus自定義Sql實(shí)現(xiàn)多表查詢的示例
這篇文章主要介紹了MybatisPlus自定義Sql實(shí)現(xiàn)多表查詢的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08Feign實(shí)現(xiàn)跨服務(wù)文件上傳下載
這篇文章主要為大家詳細(xì)介紹了Feign實(shí)現(xiàn)跨服務(wù)文件上傳下載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04Springmvc ViewResolver設(shè)計(jì)實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了Springmvc ViewResolver設(shè)計(jì)實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10Spring Data JPA 如何使用QueryDsl查詢并分頁(yè)
這篇文章主要介紹了Spring Data JPA 如何使用QueryDsl查詢并分頁(yè),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11解決SpringBoot配置文件application.yml遇到的坑
這篇文章主要介紹了解決SpringBoot配置文件application.yml遇到的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02Windows下安裝ElasticSearch的方法(圖文)
這篇文章主要介紹了Windows下安裝ElasticSearch的方法(圖文),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01SpringMVC文件上傳原理及實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了SpringMVC文件上傳原理及實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07