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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

sort降序shell_排序之希尔排序(shell sort)

發布時間:2025/3/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 sort降序shell_排序之希尔排序(shell sort) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

本篇博客是在伍迷兄的博客基礎上進行的,其博客地址點擊就可以進去,里面好博客很多,我的排序算法都來自于此;一些數據結構方面的概念我就不多闡述了,伍迷兄的博客中都有詳細講解,而我寫這些博客只是記錄自己學習過程,加入了一些自己的理解,同時也希望給別人提供幫助。

前提故事

騷年在上次與博主進行了直接插入排序的討論后,找到了博主,說:“博主,對于直接插入排序,我有重大的發現”,博主想了想,就問:“什么發現?”,騷年:“我發現了如下兩點”

1)當序列的個數比較少時,直接插入排序效率高;這個好理解,個數比較少,那么插入的次數也就少了,博主就說:“恩,這個發現不難,卻也需要細心”。

2)如果序列本身就是基本有序,那么直接插入排序效率高;博主:“嗯?”,騷年解釋道:“你看直接插入排序的核心代碼:”

for(int i=1; i=0&&arr[j]>arr[j+1]; j--){

swap(arr,j,j+1);

}

}

騷年接著道:“如果序列有序,那么j>=0&&arr[j]>arr[j+1]條件就是不滿足的,插入操作就不會執行,效率自然就高了。”

博主:“然后了?”。

騷年:“那么我們是不是可以在這兩點上做點事,來提高直接插入排序在普通序列上的效率了?”。

上述兩個條件過于苛刻,現實中記錄少或者基本有序都屬于特殊情,有條件當然是好,條件不存在,我們創造條件,也是可以去做的;騷年與博主進行了研究與討論,我們可以對序列進行分組,分割成若干個子序列,然后對每個子序列分別進行直接插入排序,當整個序列都基本有序時,注意只是基本有序時,再對全體記錄進行一次直接插入排序。

此時一定有人開始疑惑了。這不對呀,比如我們現在有序列是{5,3,7,9,1,6,4,8,2},現在將它分成三組,{5,3,7}, {9,1,6},{4,8,2},哪怕將它們各自排序排好了,變成{3,5,7},{1,6,9},{2,4,8},再合并它們成 {3,5,7,1,6,9,2,4,8},此時,這個序列還是雜亂無序,談不上基本有序,要排序還是重來一遍直接插入有序,這樣做有用嗎?需要強調一下, 所謂的基本有序,就是小的關鍵字基本在前面,大的基本在后面,不大不小的基本在中間,像{2,1,3,6,4,7,5,8,9}這樣可以稱為基本有序了。 但像{3,5,7,1,6,9,2,4,8}這樣的7在第三位,2在倒數第三位就談不上基本有序。

那么問題就來了,我們分割待排序記錄的目的是減少待排序記錄的個數,并使整個序列向基本有序發展。而如上面這樣分完組后,就各自排序的方法達不到我們的要求。因此,我們需要采取跳躍分割的策略:將相距某個“增量”的記錄組成一個子序列,這樣才能保證在子序列內分別進行直接插入排序后得到的結果是基本有序而不是局部有序。

基本思想

將整個序列按照相距某個“增量”進行拆分,然后逐個對子序列進行直接插入排序,使得得到的結果基本有序,最后對基本有序的序列進行一次直接插入排序,使得整個序列有序

代碼實現

java實現

/*** 希爾排序

*@paramarr 目標序列*/

public static void shellSort(int[] arr){int len =arr.length;for(int gap=len/2; gap>=1; gap=gap/2){ //拆分整個序列,元素間距為gap(也就是增量)//對子序列進行直接插入排序

for(int i=gap+1; i=0&&arr[j]>arr[j+gap]; j=j-gap){

swap(arr,j,j+gap);

}

}

}

}

View Code

執行過程模擬

1)程序開始執行,初始序列為{5,3,7,9,1,6,4,8,2},如下圖:

2)初始gap=len/2=4

2.1)i=gap=4,初始j=0;比較arr[j]與arr[j+gap],即arr[0]與arr[4],如下圖:

j=j-gap=-4,跳出,i++,i=5

2.2)i=5,j=i-gap=1,arr[1]=3 < arr[5]=6,不交換數據,如下圖:

j=j-gap=-3,跳出,i++,i=6

2.3)同理,當i=6,7時,序列如下圖:

2.4)當i=8時,序列如下:

那么gap=4時,最終序列為

3)gap=gap/2=2

3.1)i=gap=2,j=i-gap=0,arr[0]=1 < arr[2]=4不交換,j=j-gap=-2,i++,此時序列為:

3.2)i=3,j=i-gap=1,arr[1]=3 < arr[3]=8,不交換,j=j-gap=-1,i++,此時序列為:

3.3)同理,i=4時:

3.4)i=5時:

3.5)i=6時:

3.6)i=7時:

3.7)i=8時:

4)gap=gap/2=1,此時

for(int gap=len/2; gap>=1; gap=gap/2){ //拆分整個序列,元素間距為gap(也就是增量)//對子序列進行直接插入排序

for(int i=gap; i=0&&arr[j]>arr[j+gap]; j=j-gap){

swap(arr,j,j+gap);

}

}

就是

//對子序列進行直接插入排序

for(int i=1; i=0&&arr[j]>arr[j+1]; j=j-1){

swap(arr,j,j+1);

}

}

相信大家都發現了,上面代碼就是我們的直接插入排序,那么具體的模擬過程我也就不再贅述了,不懂的可以去看排序之直接插入排序

至此,整個序列就有序了。

難解之處

通過這段代碼的剖析,相信大家有些明白,希爾排序的關鍵并不是隨便的分組后各自排序,而是將相隔某個“增量”的記錄組成一個子序列,實現跳躍式的移動,使得排序的效率提高。這里“增量”的選取就非常關鍵了,本例中是以gap=gap/2的方式選取增量的,可究竟應該選取什么樣的 增量才是最好,目前還是一個數學難題,迄今為止還沒有人找到一種最好的增量序列。不過大量的研究表明,當增量序列為dlta[k]=2t-k+1-1(0≤k≤t≤?log2(n+1)?)時,可以獲得不錯的效率。需要注意的是,增量序列的最后一個增量值必須等于1才行。

總結

以上是生活随笔為你收集整理的sort降序shell_排序之希尔排序(shell sort)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。