剛開(kāi)始學(xué)習(xí)Java,大家都會(huì)學(xué)習(xí)排序算法,但是只有理解了排序的方法,才能更好的將其轉(zhuǎn)換為代碼。剛開(kāi)始學(xué)習(xí)我也為了理解算法絞盡腦汁,現(xiàn)在我將自己對(duì)排序算法的理解寫(xiě)下來(lái),希望能夠幫助到初入Java殿堂的朋友們。
一、選擇排序
1.對(duì)選擇排序的理解
排序的目的就是要將無(wú)序的數(shù)列轉(zhuǎn)變?yōu)橛行虻臄?shù)列。而有序的數(shù)列中每一個(gè)數(shù)字都對(duì)應(yīng)著一個(gè)相應(yīng)的位置。選擇算法其實(shí)就是根據(jù)位置找到對(duì)應(yīng)的數(shù)字。
假設(shè)我們有這樣一組數(shù)列:
int[] arr = {5, 8, 3, 6, 1};
我們要將它按從小到大的順序進(jìn)行排序。那么第一個(gè)位置也就是arr[0]應(yīng)該對(duì)應(yīng)的是最小的數(shù)字。將原來(lái)的arr[0]與它后面的arr[1]比較,將小的數(shù)留在arr[0],再用新的arr[0]與arr[2]進(jìn)行比較,并將小的數(shù)留在arr[0],以此類推,最后就能確保arr[0]上的數(shù)是最小的。接下來(lái)的工作就和上面一樣,就是在去掉最小數(shù)字的情況下,讓arr[1]對(duì)應(yīng)的是剩余數(shù)字中最小的數(shù)字。這樣依次選定arr[i]上的數(shù)字,一直到倒數(shù)第二個(gè)位置的數(shù)字確定,就完成了排序。
2.代碼
`for (int i = 0; i < arr.length - 1; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}`
因?yàn)橹恍枰_定到倒數(shù)第二個(gè)就完成了排序,所以最外層循環(huán)的只需要執(zhí)行arr.length - 1次。因?yàn)槊總€(gè)位置的數(shù)字都需要與后面的所有數(shù)字進(jìn)行比較,所以j的值要從i + 1取到arr.length。
二、冒泡排序
1.對(duì)冒泡排序的理解
(圖片來(lái)自張朵拉的涂鴉本子)
冒泡排序的“冒泡”兩字非常的形象。魚(yú)吐出的氣泡比水輕,所以它會(huì)不斷上升,并在上升的過(guò)程中將比自己重的水?dāng)D到下面。而冒泡排序中,位于后面的小數(shù)字會(huì)不斷地往前移動(dòng),并把比自己大的數(shù)字?jǐn)D到后面去。
同樣是上面的數(shù)組:
int[] arr = {5, 8, 3, 6, 1};
我們將最后一個(gè)數(shù)字與前面的數(shù)字比較,如果小于前面的數(shù)字就將其擠到后面,這樣較小的數(shù)字就升到了倒數(shù)第二的位置,然后再與前面倒數(shù)第三位置上的數(shù)進(jìn)行比較小數(shù)字向前升,大數(shù)字被擠到后面,這樣向前比較兩兩相鄰的位置上的數(shù)字,最后最小的數(shù)字就會(huì)上升到最前面的位置。緊接著,再?gòu)淖詈笠粋€(gè)數(shù)字開(kāi)始向前比較,第二小的數(shù)就到了第二個(gè)位置。以此類推,確定下來(lái)倒數(shù)第二個(gè)位置上的數(shù)字,就完成了排序。
2.代碼_1
` int[] arr = {5, 8, 3, 6, 1};
for (int i = 0; i < arr.length - 1; i++) {
for (int j = arr.length - 1; j > i; j--) {
if (arr[j] < arr[j - 1]) {
int temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
}
}`
因?yàn)榇_定下來(lái)倒數(shù)第二個(gè)位置上的數(shù)字,就完成了排序,所以最外層循環(huán)只需要進(jìn)行arr.length - 1次。因?yàn)槊看味紡淖詈笠晃槐容^到arr[i],所以里面循環(huán)的條件會(huì)是上面的樣子。
3.代碼_2
` int[] arr = {5, 8, 3, 6, 1};
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j > arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}`
如果代碼_1里面循環(huán)的條件不好理解,可以看看代碼_2。既然冒泡可以理解為氣泡上升,當(dāng)然也可以理解為水下降。重的水在下降的過(guò)程中不斷將氣泡擠到前面去,大的數(shù)字也就像水一樣,將小的數(shù)字?jǐn)D到了前面。
我們將第一個(gè)位置上的數(shù)字,與后面的數(shù)字進(jìn)行比較,大的數(shù)向后下沉,小的數(shù)向前上升,最后最大的數(shù)就沉到了最后面。然后再?gòu)牡谝晃婚_(kāi)始將大數(shù)沉底,就能將第二大的數(shù)沉到倒數(shù)第二的位置。以此類推,這樣操作arr.length - 1次,就完成了排序。而每次需要交換的次數(shù)是arr.length - 1 - i次。所以里層循環(huán)只需要執(zhí)行arr.length - 1 - i次。
三、結(jié)語(yǔ)
這就是我對(duì)選擇排序和冒泡排序的理解,希望能幫助到你。我們?cè)俨恢朗裁磿r(shí)候的未來(lái)再見(jiàn)吧!