datatable的数据进行组内排序_排序算法学习分享(四)希尔排序
排序,也稱為排序算法,可以說(shuō)是我們學(xué)習(xí)算法的過(guò)程中遇到的第一個(gè)門(mén)檻,也是實(shí)際應(yīng)用中使用得較為頻繁的算法,我將自己對(duì)所學(xué)的排序算法進(jìn)行一個(gè)歸納總結(jié)與分享,如有錯(cuò)誤,歡迎指正!
排序算法學(xué)習(xí)分享(一)選擇排序
排序算法學(xué)習(xí)分享(二)交換排序---冒泡排序與快速排序
排序算法學(xué)習(xí)分享(三)插入排序
(一)排序的分類(lèi)
排序算法主要分為內(nèi)部排序與外部排序,當(dāng)數(shù)據(jù)量大時(shí),數(shù)據(jù)無(wú)法全部加載到內(nèi)存中,因此需要接抓外部存儲(chǔ)(文件、磁盤(pán)等)進(jìn)行排序。而內(nèi)部排序則是指將要處理的所有數(shù)據(jù)加載到內(nèi)部存儲(chǔ)器中,并在內(nèi)存中就完成排序。
本文針對(duì)的為內(nèi)部排序。
(二)內(nèi)部排序
4 希爾排序
前文我介紹了插入排序,但是插入排序會(huì)出現(xiàn)一個(gè)問(wèn)題。如果我們拿到的是一個(gè)較小的數(shù)進(jìn)行插入排序,那么元素后移的次數(shù)會(huì)明顯增加,那么就會(huì)嚴(yán)重影響整個(gè)排序的效率。
接下來(lái)介紹的希爾排序就是經(jīng)典的對(duì)插入排序的一種優(yōu)化。
希爾排序,也稱遞減增量排序,是插入排序的一種更高效的改進(jìn)版本。我們都知道,插入排序?qū)σ呀?jīng)有序的或者是有序程度高的序列排序是非常快的,但一般情況下,由于插入排序每插入一個(gè)元素都只能一個(gè)一個(gè)元素地進(jìn)行移動(dòng),因此它的效率是十分低下的。
顯然要優(yōu)化插入排序的移動(dòng)是很困難的,而希爾排序取巧地不去優(yōu)化它的移動(dòng),希爾排序的思想我用一句話去概括:盡可能的在數(shù)組進(jìn)行下一輪的排序時(shí),提高數(shù)組的有序程度。
先記住一點(diǎn):在序列的排序中,元素越少,需要交換的次數(shù)越少,排序越快。
那么怎么去提高一個(gè)數(shù)組的有序程度呢?用一個(gè)很有趣的東西——增量。
這類(lèi)似于分治思想,但它又不是。希爾排序利用增量這一個(gè)東西去將序列分割成若干個(gè)子序列,再將每個(gè)子序列分別排好。 那么究竟什么是增量?又要怎么利用增量?
增量就是一個(gè)等差數(shù)列的差值,比如1,3,5,7,9。它們的增量是2。一開(kāi)始盡可能使用一個(gè)大的增量,使得每個(gè)子序列中的元素少,比如第一輪就盡量使得一個(gè)子序列的元素只有兩個(gè)。
增量越大,那么分的組就會(huì)越多,每個(gè)組中的元素?cái)?shù)目就會(huì)小。每一輪都比上一輪的增量按照一定的規(guī)律遞減,那么分的組就會(huì)比上一輪的分的組少,而每個(gè)組中的元素就要比上一輪的元素要多,當(dāng)增量一直減到1的時(shí)候,我們就會(huì)發(fā)現(xiàn)只有一個(gè)組了,而這個(gè)組中的元素就是整個(gè)序列的所有元素,這就是遞減增量。
利用增量這樣子分割序列是為了什么呢?是為了使下一輪的有序程度變高。為什么我說(shuō)希爾排序是一種取巧呢?就是因?yàn)樗Y嚻?#xff0c;有序程度低的時(shí)候,增量就大,分組就多,組內(nèi)元素就少,排序就快。當(dāng)這一輪排序完成的時(shí)候,全體序列的有序程度一定是要比上一輪的有序程度要高的(有一些特殊情況,嚴(yán)謹(jǐn)?shù)貞?yīng)該說(shuō)是不低于)。
增量每一次發(fā)生遞減,那么序列的有序程度就提高了那么一點(diǎn),當(dāng)增量遞減到1的時(shí)候,序列的有序程度就已經(jīng)很高的,這時(shí)再進(jìn)行一輪插入排序,就很快了。
這么將還是有些抽象,我們舉一個(gè)實(shí)例,上一些圖來(lái)說(shuō)明。
這是一個(gè)原始數(shù)組,可以看到它的有序程度并不高。
我們對(duì)它進(jìn)行第一次增量分組,使得每組中的元素盡可能少。最少的話是一個(gè)元素一個(gè)組,但是如果組中只有一個(gè)元素,那么組內(nèi)的排序根本沒(méi)有意義,因此第一次的這個(gè)盡可能少,就是兩兩一組。此時(shí)的增量為4。
我們對(duì)每個(gè)子數(shù)組內(nèi)進(jìn)行排序。由于每個(gè)子數(shù)組內(nèi)的元素很少,因此排序很快,排序完如下:
我們已經(jīng)可以看到只是經(jīng)過(guò)簡(jiǎn)單的幾個(gè)交換后數(shù)組的有序程度就已經(jīng)顯著提升了,那么接下來(lái)就是進(jìn)入到下一輪。
遞減增量,直接使增量減半(希爾增量),新的增量為4 / 2 = 2,將2作為新的增量重新進(jìn)行分組,分組如下。
我們對(duì)每個(gè)分組內(nèi)進(jìn)行排序,因?yàn)榻?jīng)過(guò)了上一輪的排序,可以看到每個(gè)組內(nèi)的有序程度比上一輪如果也按照這個(gè)增量分組的有序程度要高。
這就達(dá)到了希爾排序的目的,就是每一輪都要比上一輪的有序程度要高,這很像我們做產(chǎn)品時(shí)候的不斷迭代。
排序好后如下:
這一輪結(jié)束后增量再遞減就變成1了,最后再進(jìn)行一輪插入排序即可,此時(shí)需要移動(dòng)的數(shù)僅僅就是5和3,8和9。有序程度比原數(shù)組高到不知道哪里去了。再來(lái)一輪插入排序就完成啦!
其實(shí)遞減增量的規(guī)則有很多種,不止折半這一種,有時(shí)候根據(jù)需求改變遞減增量的方式會(huì)取得更優(yōu)的性能。
下面嘗試用代碼實(shí)現(xiàn)希爾排序:
希爾排序使用的增量是折半的方式遞減的,這種方式的增量叫做希爾增量。希爾排序利用增量分組粗調(diào)一般情況下是減少了插入排序的工作量,使得插入排序的時(shí)間復(fù)雜度低于O(n2)。
但是,在一種極端的情況下,希爾排序所做的粗略調(diào)整不但沒(méi)有減少插入排序的工作量,反而增大的插入排序的工作量。
舉一個(gè)例子:
我們利用希爾增量來(lái)分組,當(dāng)增量為4時(shí),分組為:(2,7),(1,6),(5,9),(3,8)。我們可以看到它在組內(nèi)是有序的,再折半減少增量為2,分組為(2,5,7,9),(1,3,6,8),還是有序的,經(jīng)過(guò)兩輪增量排序,它的有序程度并沒(méi)有提高,比起直接插入排序反而還增加分組排序的這一個(gè)步驟,增加了工作量。
會(huì)出現(xiàn)這種情況的原因在于希爾增量,希爾增量之間是等比的,這代表著等比之間是可以出現(xiàn)一定的盲區(qū)的,就像上面這個(gè)例子,就完美地處在了希爾增量之間的盲區(qū)。
那么才能使得增量之間沒(méi)有盲區(qū)呢?最好的方式就是使得每一輪彼此的增量“互質(zhì)”。而增量的方式很多,最為典型的就是Hibbard增量和Sedgewick增量。因?yàn)楸疚闹v的是希爾排序,就不繼續(xù)往下介紹了。
希爾排序是一個(gè)不穩(wěn)定的排序算法,是因?yàn)樵诜纸M的過(guò)程中,兩個(gè)元素的交換的跨度有時(shí)候是會(huì)很大的。比如m > i = j > k,而原數(shù)組是( i ,j ,k ,m ),那么第一輪希爾排序后,i 就到 j 后面了。
希爾排序的介紹就到這里啦!希爾排序的中心思想就是: 盡可能的在數(shù)組進(jìn)行下一輪的排序前,提高數(shù)組的有序程度。即每一輪都比上一輪時(shí)候的有序程度要高。
總結(jié)
以上是生活随笔為你收集整理的datatable的数据进行组内排序_排序算法学习分享(四)希尔排序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: mysql聚簇索引 和主键的区别_[My
- 下一篇: esc键没反应_有机人名反应——Brow