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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

排序算法:插入排序

發(fā)布時(shí)間:2023/12/15 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 排序算法:插入排序 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

微信搜索【程序員囧輝】,關(guān)注這個(gè)堅(jiān)持分享技術(shù)干貨的程序員。

前言

上一次,我們介紹了排序算法中“龜速三兄弟”的大哥“冒泡排序”。今天,我們繼續(xù)介紹“龜速三兄弟”中的二哥——“插入排序”。“冒泡排序”的過(guò)程和代碼相信大多數(shù)人都比較熟悉,但是“插入排序”就不見(jiàn)得了。由于同樣是“龜速三兄弟”中的一員,但是處理過(guò)程沒(méi)有“冒泡排序”那么簡(jiǎn)單明了,因此有不少人可能都沒(méi)接觸過(guò)“插入排序”,本文將通過(guò)例子來(lái)介紹“插入排序”的完整過(guò)程。

?

基本思想

將一個(gè)數(shù)插入一個(gè)已經(jīng)排好序的數(shù)據(jù)中。

  • 第一次循環(huán)時(shí),從第2個(gè)數(shù)開(kāi)始處理。我們將第1個(gè)數(shù)作為已經(jīng)排好序的數(shù)據(jù):當(dāng)?shù)?個(gè)數(shù) > 第1個(gè)數(shù)時(shí),將第2個(gè)數(shù)放在第1個(gè)數(shù)后面一個(gè)位置;否則,將第2個(gè)數(shù)放在第1個(gè)數(shù)前面。此時(shí),前兩個(gè)數(shù)形成了一個(gè)有序的數(shù)據(jù)。
  • 第二次循環(huán)時(shí),我們處理第3個(gè)數(shù)。此時(shí),前兩個(gè)數(shù)形成了一個(gè)有序的數(shù)據(jù):首先比較第3個(gè)數(shù)和第2個(gè)數(shù),當(dāng)?shù)?個(gè)數(shù) > 第2個(gè)數(shù)時(shí),將第3個(gè)數(shù)放在第2個(gè)數(shù)后面一個(gè)位置并結(jié)束此次循環(huán);否則,再和第1個(gè)數(shù)比較。如果第3個(gè)數(shù) > 第1個(gè)數(shù),則將第3個(gè)數(shù)插入第1個(gè)數(shù)和第2個(gè)數(shù)中間;否則,第3個(gè)數(shù) < 第1個(gè)數(shù),則將第3個(gè)數(shù)放在第1個(gè)數(shù)前面。此時(shí),前三個(gè)數(shù)形成了一個(gè)有序的數(shù)據(jù)。
  • 后續(xù)的數(shù)據(jù)同理處理,直至結(jié)束。
  • ?

    例子

    下面通過(guò)一個(gè)例子來(lái)看看插入排序是怎么工作的。原數(shù)組如下。

    第一次循環(huán):

    1.從第2個(gè)數(shù)開(kāi)始處理,即array[1]。比較array[1]和arary[0],即15和19。因?yàn)?5 < 19,所以將arary[1]放在array[0]的前面,放完后的數(shù)組如下。

    由于是從第2個(gè)數(shù)開(kāi)始處理,一直處理到最后一個(gè)數(shù)。因此,最外層的循環(huán)可以寫(xiě)成如下:

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

    至此,第一次循環(huán)結(jié)束。

    ?

    第二次循環(huán):

    1.處理第3個(gè)數(shù),即array[2]。首先比較array[2]和array[1],即37和19。因?yàn)?7 > 19,并且前面2個(gè)數(shù)經(jīng)過(guò)第一次循環(huán)后是有序的。因此,直接將37放在array[1]后面的1個(gè)位置即array[2]原位置,放完后的數(shù)組如下。

    至此,第二次循環(huán)結(jié)束。

    ?

    第三次循環(huán):

    1.處理第4個(gè)數(shù),即array[3]。首先比較array[3]和array[2],即12和37。因?yàn)?2 < 37,所以37此時(shí)在前4個(gè)數(shù)中可以確定是最大的。因此此時(shí)array[3]是37的正確位置,但是array[3]此時(shí)被12占著,所以我們需要用一個(gè)臨時(shí)變量temp存儲(chǔ)arary[3]的值,然后將37填入array[3],填完后的數(shù)組如下。

    結(jié)合比較語(yǔ)句,此時(shí)的代碼可以寫(xiě)成如下,在當(dāng)前循環(huán) i = 3。

    if (array[i] < array[i - 1]) {// 臨時(shí)變量存儲(chǔ)array[i]的值int temp = array[i]; // array[i - 1]填入此時(shí)屬于它的位置array[i] = array[i - 1]; }

    ?

    填充完array[3]后,我們需要將下標(biāo)向前移動(dòng)一個(gè)位置,好將temp(原來(lái)的array[3])跟array[1]進(jìn)行比較,但是此時(shí)下標(biāo) i 代表著循環(huán)的位置不能移動(dòng)。因此,我們需要再定義一個(gè)變量 j 來(lái)記錄比較的位置,因此將上述代碼優(yōu)化成如下:

    // 當(dāng)array[i]比arra[i - 1]小時(shí)才進(jìn)入處理 if (array[i] < array[i - 1]) {// 臨時(shí)變量存儲(chǔ)array[i]的值int temp = array[i]; // 定義變量j記錄比較的位置int j = i; // 將比temp大的數(shù)往后挪一個(gè)位置,為temp騰出一個(gè)合適位置while (j > 0 && temp < array[j - 1]) { array[j] = array[j - 1]; j--; // 填充完后, 繼續(xù)向前比較 } }

    ?

    2.此時(shí) j 移動(dòng)到下標(biāo)2,比較temp和array[1],即12和19。因?yàn)?2 < 19,并且原來(lái)array[2]位置的數(shù)37此時(shí)已經(jīng)填入array[3],因此此時(shí)array[2]相當(dāng)于一個(gè)坑,直接將19填入即可。將19填入array[2]時(shí),array[1]又形成了一個(gè)新的坑,此時(shí)的數(shù)組如下。

    填完后,將下標(biāo) j 繼續(xù)向前移動(dòng)一個(gè)位置。

    ?

    3.此時(shí) j 移動(dòng)到下標(biāo)1,此時(shí)比較temp和array[0],即12和15。因?yàn)?2 < 15,并且原來(lái)array[1]位置的數(shù)19此時(shí)已經(jīng)填入array[2],因此直接將15填入array[1],此時(shí)array[0]又形成了一個(gè)新的坑,此時(shí)的數(shù)組如下。

    4.此時(shí) j 移動(dòng)到下標(biāo)0,已經(jīng)沒(méi)有前面的數(shù)可以比較了。因此,array[0]即為temp的位置,將temp填入array[0]后結(jié)束此次循環(huán),此時(shí)的數(shù)組如下。

    結(jié)合上面的代碼,將temp填入對(duì)應(yīng)位置的代碼也加上后,代碼如下:

    // 當(dāng)array[i]比arra[i - 1]小時(shí)才進(jìn)入處理 if (array[i] < array[i - 1]) {// 臨時(shí)變量存儲(chǔ)array[i]的值int temp = array[i]; // 從當(dāng)前位置開(kāi)始處理int j = i; // 將比temp大的數(shù)往后挪一個(gè)位置,為temp騰出一個(gè)合適位置while (j > 0 && temp < array[j - 1]) { array[j] = array[j - 1]; j--; // 填充完后, 繼續(xù)向前比較 } // 將temp放在屬于它的位置上array[j] = temp; }

    ?

    第四次循環(huán)

    1.處理第5個(gè)數(shù),即array[4]。首先比較array[4]和array[3],即25和37。因?yàn)?5 < 37,所以將25賦值給temp,并將37填入array[4]的位置,并將下標(biāo) j 向前移動(dòng)一個(gè)位置,此時(shí)的數(shù)組如下。

    2.此時(shí) j 移動(dòng)到下標(biāo)3,此時(shí)比較temp和array[2],即25和19。因?yàn)?5 > 19,所以array[3]即為25的位置,將25填入array[3]后結(jié)束此次循環(huán)。

    至此,整個(gè)排序過(guò)程結(jié)束。

    ?

    完整過(guò)程

    最后我們通過(guò)以下動(dòng)圖來(lái)看插入排序的整個(gè)過(guò)程,圖中紅色的柱子為當(dāng)前要插入的數(shù),橘黃色的柱子為當(dāng)前已經(jīng)排好序的數(shù)據(jù),綠色的柱子為正在跟紅色的柱子比較的數(shù),淺藍(lán)色的柱子為還未插入的數(shù)。

    ?

    整合

    上文的例子中已經(jīng)基本將邏輯代碼都寫(xiě)清了,我們將外層循環(huán)和里面的處理邏輯代碼結(jié)合到一起,代碼如下。

    public class InsertSort {public static void insertSort(int array[]) {if (array == null || array.length == 0) {return;}for (int i = 1; i < array.length; i++) {// 當(dāng)array[i]比arra[i - 1]小時(shí)才進(jìn)入處理if (array[i] < array[i - 1]) {// 臨時(shí)變量存儲(chǔ)array[i]的值int temp = array[i];// 從當(dāng)前位置開(kāi)始處理int j = i;// 將比temp大的數(shù)往后挪一個(gè)位置,為temp騰出一個(gè)合適位置while (j > 0 && temp < array[j - 1]) {array[j] = array[j - 1];j--; // 填充完后, 繼續(xù)向前比較}// 將temp放在屬于它的位置上array[j] = temp;}}} }

    ?

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

    在最壞的情況下,即整個(gè)數(shù)組是倒序的,比較次數(shù) = 1 + 2 + 3 + ... + (n - 2) + (n - 1) = n * (n - 1) / 2,此時(shí)的時(shí)間復(fù)雜度為:O(n^2)。

    在最好的情況下,即整個(gè)數(shù)組是正序的,比較次數(shù) = n - 1,此時(shí)的時(shí)間復(fù)雜度為:O(n)。

    ?

    使用場(chǎng)景

    插入排序和冒泡排序一樣。在進(jìn)行量比較大的排序時(shí),最好不要使用。在1000個(gè)數(shù)字以內(nèi)的排序,用插入排序是可以接受的。1000個(gè)隨機(jī)數(shù)使用插入排序耗時(shí)一般在5毫秒以內(nèi),但是當(dāng)數(shù)字個(gè)數(shù)達(dá)到10000個(gè)時(shí),耗時(shí)會(huì)達(dá)到30+毫秒,有比較明顯的耗時(shí),需要慎重使用。

    ?

    相關(guān)閱讀

    排序算法:冒泡排序

    ?

    總結(jié)

    以上是生活随笔為你收集整理的排序算法:插入排序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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