日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java快速排序直观演示代码,排序算法总结(含动图演示和Java代码实现)

發(fā)布時(shí)間:2023/12/10 java 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java快速排序直观演示代码,排序算法总结(含动图演示和Java代码实现) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文將圍繞冒泡排序、桶排序、計(jì)數(shù)排序、堆排序、插入排序、并歸排序、快速排序和選擇排序,按照描述、時(shí)間復(fù)雜度(最壞情況)、動(dòng)態(tài)圖展示和代碼實(shí)現(xiàn)來講解。本文默認(rèn)排序?yàn)閺男〉酱蟆?/p>

本文相關(guān)代碼已上傳至github,歡迎關(guān)注https://github.com/zhuzhenke/common-algorithms

公用方法

SortUtils

public class SortUtils {

public static void check(int[] sortingData) {

if (sortingData == null || sortingData.length == 0) {

throw new IllegalArgumentException("sortingData can not be empty!");

}

}

public static void swap(int[] swapArray, int i, int j) {

check(swapArray);

if (i < 0 || i > swapArray.length - 1) {

throw new ArrayIndexOutOfBoundsException("illegal index i:" + i);

}

if (j < 0 || j > swapArray.length - 1) {

throw new ArrayIndexOutOfBoundsException("illegal index j:" + j);

}

int temp = swapArray[i];

swapArray[i] = swapArray[j];

swapArray[j] = temp;

}

public static int getMaxValue(int[] sortingData) {

check(sortingData);

int max = sortingData[0];

for (int value : sortingData) {

if (value < 0) {

throw new IllegalArgumentException("value could not be negative:" + value);

}

if (value > max) {

max = value;

}

}

return max;

}

}

冒泡排序

描述

比較前后兩個(gè)數(shù)的大小,如果前者大于后者,則交換兩個(gè)數(shù)的位置

最大的數(shù)字在進(jìn)行一輪比較和交換后,會(huì)出現(xiàn)在數(shù)組的最后一個(gè)位置

每一輪之后,可減少最大數(shù)字的比較。重復(fù)上述操作直到?jīng)]有需要比較的元素為止

時(shí)間復(fù)雜度

O(n^2)

動(dòng)態(tài)圖展示

代碼實(shí)現(xiàn)

github代碼

public int[] sort(int[] sortingData) {

SortUtils.check(sortingData);

for (int j = sortingData.length - 1; j > 0; j--) {

for (int i = 0; i < j; i++) {

if (sortingData[i] > sortingData[i + 1]) {

SortUtils.swap(sortingData, i, i + 1);

}

}

}

return sortingData;

}

桶排序

描述

挑選數(shù)組中最大的數(shù)字,設(shè)置默認(rèn)分配的桶數(shù),得到每個(gè)桶容納的數(shù)字范圍。如最大是10,桶是4個(gè),則每個(gè)桶最大容納3個(gè)數(shù)字。第0個(gè)桶放0、1、2、3,第1個(gè)桶方4、5、6,第2桶方7,8,9,以此類推

對(duì)每個(gè)桶內(nèi)進(jìn)行冒泡排序或選擇排序

遍歷所有桶,依次取出每個(gè)桶中的元素,得到的就是一個(gè)排好序的數(shù)組

時(shí)間復(fù)雜度

O(n^2)

動(dòng)態(tài)圖展示

代碼實(shí)現(xiàn)

github代碼

@Override

public int[] sort(int[] sortingData) {

SortUtils.check(sortingData);

int bucketSize = (int) Math.round(Math.sqrt(sortingData.length)) + 1;

int[][] buckets = new int[bucketSize][];

int max = SortUtils.getMaxValue(sortingData);

double avgContain = Math.ceil((double) max / (double) bucketSize);

for (int value : sortingData) {

int bucketIndex = (int) Math.ceil(value / avgContain) - 1;

if (bucketIndex < 0) {

bucketIndex = 0;

}

int[] bucketIndexs = buckets[bucketIndex];

if (bucketIndexs == null || bucketIndexs.length == 0) {

bucketIndexs = new int[1];

bucketIndexs[0] = value;

buckets[bucketIndex] = bucketIndexs;

} else {

int[] newBucketIndexs = new int[bucketIndexs.length + 1];

System.arraycopy(bucketIndexs, 0, newBucketIndexs, 0, bucketIndexs.length);

newBucketIndexs[bucketIndexs.length] = value;

buckets[bucketIndex] = newBucketIndexs;

}

}

Sort sort = new InsertionSort();

for (int a = 0; a < buckets.length; a++) {

int[] bucket = buckets[a];

if (bucket == null || bucket.length == 0) {

continue;

}

bucket = sort.sort(bucket);

buckets[a] = bucket;

}

int[] result = new int[sortingData.length];

int resultIndex = 0;

for (int[] bucket : buckets) {

if (bucket == null || bucket.length == 0) {

continue;

}

for (int bucketValue : bucket) {

result[resultIndex++] = bucketValue;

}

}

return result;

}

計(jì)數(shù)排序

描述

獲取數(shù)組中最大的值(這個(gè)值需要在可控范圍,最好是在10000以內(nèi))

創(chuàng)建一個(gè)長(zhǎng)度為最大值加1的計(jì)數(shù)數(shù)組,

遍歷待排序數(shù)組,將元素的值落入到計(jì)數(shù)數(shù)組的下標(biāo)元素,將下標(biāo)元素的值加1

遍歷下標(biāo)數(shù)組,將后一個(gè)元素的值標(biāo)為當(dāng)前元素值加前一個(gè)元素的值(用于排序后的數(shù)組下標(biāo))。

創(chuàng)建一個(gè)長(zhǎng)度跟待排序數(shù)組大小相同的結(jié)果數(shù)組

遍歷待排序數(shù)組,取出待排序元素,對(duì)應(yīng)計(jì)數(shù)數(shù)組的下標(biāo)元素,并放在計(jì)數(shù)元素值的前一個(gè)位置,并將計(jì)數(shù)元素值減1

時(shí)間復(fù)雜度

O(n)

動(dòng)態(tài)圖展示

代碼實(shí)現(xiàn)

github代碼

private int[] sort2(int[] sortingData) {

int maxValue = SortUtils.getMaxValue(sortingData);

//get max,check all numbers must be bigger or equal 0

int[] count = new int[maxValue + 1];

//count every number

for (int value : sortingData) {

count[value] = count[value] + 1;

}

for (int i = 1; i < count.length; i++) {

count[i] = count[i] + count[i - 1];

}

//output

int[] result = new int[sortingData.length];

for (int value : sortingData) {

result[count[value] - 1] = value;

count[value] = count[value] - 1;

}

return result;

}

堆排序

描述

為了方便理解,將數(shù)組元素映射成二叉樹,array[0]對(duì)一個(gè)根節(jié)點(diǎn),array[1]為根的左節(jié)點(diǎn),array[2]為根的右節(jié)點(diǎn),一次類推

從最后一個(gè)元素開始遍歷到第一個(gè),讓其與父節(jié)點(diǎn)比較大小,如果子節(jié)點(diǎn)大,則交換位置。(另外一種方式是從中間元素開始比較,得到當(dāng)前元素和子元素的最大值,這樣則遍歷深度為logn,這種方式屬于推薦方式)

遍歷一輪結(jié)束后,則最大值已經(jīng)位于index為0的位置,這時(shí)交換index為0和最后一位的位置,則最大值確定。下一輪比較從最大值的前一個(gè)index下標(biāo)元素開始遍歷,依次進(jìn)行遍歷

最后全部遍歷完成,則得到一個(gè)拍好序的數(shù)組

時(shí)間復(fù)雜度

O(nlogn)

動(dòng)態(tài)圖展示

代碼實(shí)現(xiàn)

github代碼

public int[] sort(int[] sortingData) {

int highIndex = sortingData.length - 1;

while (highIndex > 0) {

for (int i = 1; i <= highIndex; i++) {

sortBiggestToIndex0(sortingData, i);

}

SortUtils.swap(sortingData, 0, highIndex);

highIndex--;

}

return sortingData;

}

public static void sortBiggestToIndex0(int[] sortingData, int sortIndex) {

while (sortIndex > 0 && sortingData[sortIndex] > sortingData[(sortIndex - 1) / 2]) {

SortUtils.swap(sortingData, sortIndex, (sortIndex - 1) / 2);

sortIndex = (sortIndex - 1) / 2;

}

}

插入排序

描述

插入排序類似于撲克摸牌排序

第一次只有一種牌,牌是有序的。當(dāng)摸到第二張牌時(shí),則插入到已有的排好序的牌中,此時(shí)前兩張牌有序

依次進(jìn)行同樣的操作,摸到第n張牌時(shí),前n-1張牌已經(jīng)有序,進(jìn)行插入到合適位置即可

時(shí)間復(fù)雜度

O(n^2)

動(dòng)態(tài)圖展示

代碼實(shí)現(xiàn)

github代碼

public int[] sort(int[] sortingData) {

SortUtils.check(sortingData);

for (int i = 1; i < sortingData.length; i++) {

int currentValue = sortingData[i];

int j = i;

while (j - 1 >= 0 && currentValue < sortingData[j - 1]) {

sortingData[j] = sortingData[j - 1];

j--;

}

sortingData[j] = currentValue;

}

return sortingData;

}

并歸排序

描述

并歸排序利用遞歸思想,遞歸思想的核心在于找到一個(gè)模式,分解為子模式,子模式又可以分解子模式,則對(duì)于最小子模式,可以直接求解。

首先會(huì)將待排序數(shù)組分為兩份,兩份分別排好序后進(jìn)行合并

兩份中的每一份,又可以查分為更小的一份,直到每份只有一個(gè)元素,則此份為已排好序的子數(shù)組。對(duì)兩個(gè)子數(shù)組進(jìn)行合并的排序

時(shí)間復(fù)雜度

O(nlogn)

動(dòng)態(tài)圖展示

代碼實(shí)現(xiàn)

github代碼

@Override

public int[] sort(int[] sortingData) {

SortUtils.check(sortingData);

splitDate(sortingData, 0, sortingData.length - 1);

return sortingData;

}

private void splitDate(int[] sortingData, int start, int end) {

if (end - start < 1) {

return;

}

int middle = (start + end) / 2;

splitDate(sortingData, start, middle);

splitDate(sortingData, middle + 1, end);

mergeData(sortingData, start, middle, end);

}

private void mergeData(int[] sortingData, int start, int middle, int end) {

int[] left = Arrays.copyOfRange(sortingData, start, middle + 1);

int[] right = Arrays.copyOfRange(sortingData, middle + 1, end + 1);

int i = 0;

int j = 0;

for (int k = start; k <= end; k++) {

if (i < left.length && j < right.length) {

if (left[i] <= right[j]) {

sortingData[k] = left[i];

i++;

} else {

sortingData[k] = right[j];

j++;

}

} else {

if (i >= left.length) {

sortingData[k] = right[j];

j++;

} else if (j >= right.length) {

sortingData[k] = left[i];

i++;

}

}

}

}

快速排序

描述

選擇待排序數(shù)組的中元元素,一般選擇第一個(gè)或最后一個(gè)元素,將數(shù)組拆分為兩部分,左邊部分元素小于等于中元元素,右邊部分元素大于中元元素

繼續(xù)將子數(shù)組按中元元素進(jìn)行拆分,直到全部排好序位置

時(shí)間復(fù)雜度

O(n^2)

動(dòng)態(tài)圖展示

代碼實(shí)現(xiàn)

github代碼

@Override

public int[] sort(int[] sortingData) {

SortUtils.check(sortingData);

quickSort(sortingData, 0, sortingData.length - 1);

return sortingData;

}

private void quickSort(int[] sortingData, int start, int end) {

if (start > end) {

return;

}

int middle = getQuickSortMiddle(sortingData, start, end);

quickSort(sortingData, start, middle - 1);

quickSort(sortingData, middle + 1, end);

}

/**

* one side

*/

public int getQuickSortMiddle(int[] sortingData, int start, int end) {

int i = start;

int pivot = end;

for (int j = start; j < end; j++) {

if (sortingData[j] < sortingData[pivot]) {

SortUtils.swap(sortingData, i, j);

i++;

}

}

SortUtils.swap(sortingData, i, pivot);

return i;

}

選擇排序

描述

從第一個(gè)元素開始遍歷,記錄最小值和對(duì)應(yīng)元素下標(biāo),遍歷一輪則可以得到最小值,將這個(gè)值與下標(biāo)為0的元素交換,則完成第一輪最小值輸出

從第2個(gè)進(jìn)行同樣的遍歷操作,遍歷取剩余元素的最小值,將這個(gè)值與下標(biāo)為1的元素交換

從第index個(gè)開始進(jìn)行遍歷操作,遍歷取剩余元素的最小值,將這個(gè)值與下標(biāo)為index的元素交換

遍歷直到最后一個(gè)元素位置,得到一個(gè)排好序的數(shù)組

時(shí)間復(fù)雜度

O(n^2)

動(dòng)態(tài)圖展示

代碼實(shí)現(xiàn)

github代碼

public int[] sort(int[] sortingData) {

SortUtils.check(sortingData);

for (int index = 0; index < sortingData.length; index++) {

int smallestIndex = index;

int smallestValue = sortingData[index];

for (int j = index; j < sortingData.length; j++) {

if (sortingData[j] < smallestValue) {

smallestValue = sortingData[j];

smallestIndex = j;

}

}

sortingData[smallestIndex] = sortingData[index];

sortingData[index] = smallestValue;

}

return sortingData;

}

總結(jié)

以上是生活随笔為你收集整理的java快速排序直观演示代码,排序算法总结(含动图演示和Java代码实现)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。