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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

排序算法——希尔排序(缩小增量排序)

發布時間:2024/4/17 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 排序算法——希尔排序(缩小增量排序) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.希爾排序思想:

希爾排序就是把數據分成若干份子序列,從第一個元素開始,和每間隔為n的元素分成一個子序列,對每一份子序列實行直接插入排序,然后合并成一個新序列,繼續對新序列以間隔m分成若干份,繼續重復步驟,直至一個元素一份,對所有元素實行直接插入排序。如下步驟(注意,實際增量并不是按照-1變化的,我們這里只是為了觀看過程,以達到理解希爾排序思想的目的)
第一次分解排序
我們畫圖舉例,比如我們一開始有下列數據,且第一次以間隔4(即增量為4)分成若干子序列:

如上圖,間隔為4,分若干個子序列,顏色相同的為一個子序列,那么上圖就會分成下面的四個子序列:
子序列1:

子序列2:

子序列3:

子序列4:

對每個子序列進行直接插入排序,使得每個子序列都有序,然后再組合成新的數組如下:

第二次分解排序
繼續對上面數組分成子序列,比如第二次以間隔3(即增量為3)分成若干子序列,顏色相同的為一個子序列:

對每個子序列直接插入排序然后組合成新序列為(由于巧合,分解后的每個子序列都有序,所以組合后和第一步組合后的數組一樣):

第三次分解排序
把第二次分解排序后的數組分成子序列,比如第三次以間隔2(即增量為2)分成若干子序列,那么分解后的子序列為:

如上圖,紅色為一個子序列,紫色為一個子序列,對這兩個子序列分別進行直接插入排序,然后數組變成如下圖:

第四分解排序
我們增量為1,那么第一個和第二個…一直到最后一個,整個數組是一個子序列,對其進行直接插入排序。此時數組已經接近有序了,所以此時插入排序會更接近O(n)。

總結:不難看出,思想很巧妙,而且一開始的時候,交換次數會多,到后面越來越有序,調用直接插入排序時,時間復雜度也越來越接近O(n)。其實我個人覺得希爾排序歸并排序有異曲同工之妙。
我覺得,歸并排序和希爾排序的區別就在于一開始的時候。
歸并排序一開始是一個元素為一個序列,然后倆倆合并成一個有序的子序列,再倆倆子序列合并,最后生成一個有序的子序列。
希爾排序是一開始依靠增量將數組分成若干個子序列,然后將子序列排序合并(注意是在原數組上操作,實際是對下標的掌控,進而對值的掌控,在下面代碼中體現出來),增量變小,繼續分,繼續排,增量越來越小,子序列越來越長,到最后只剩一個子序列(即增量為1),簡單使用直接插入排序就完成了。

2.希爾排序的增量選擇

增量increment的取法有各種方案。最初shell提出取increment=n/2向下取整,increment=increment/2向下取整,直到increment=1。但由于直到最后一步,在奇數位置的元素才會與偶數位置的元素進行比較,這樣使用這個序列的效率會很低。后來Knuth提出取increment=n/3向下取整+1。還有人提出都取奇數為好,也有人提出increment互質為好。應用不同的序列會使希爾排序算法的性能有很大的差異。(此段話摘自博客為此處)

3.希爾排序代碼

void ShowArr(int* arr, int len) {for (int i = 0; i < len; ++i){printf("%d ", arr[i]);}printf("\n"); }void ShellSort(int* arr,int start,int end) {int increment = (end - start + 1);//初始化劃分增量int flg = 1;//注意:此變量對希爾排序無意義,我們這里只是為了統計數組第幾次排序while(increment != 1)//劃分增量==1是最后一次排序,過后數組有序,結束排序{increment = increment / 3 + 1;//劃分增量每次都用上次的劃分增量除以三向上取整for (int i = start + increment; i <= end; i++)//從start+increment開始,后面就是各子序列的非有序數據{int tmp = arr[i];//保存子序列未排序的部分的最左邊的元素while (i - increment >= 0 && arr[i - increment] > tmp)//找非有序數據在有序數據應該放置的位置{arr[i] = arr[i - increment];i = i - increment;//間隔increment的數據才為同一個子序列的數據,所以找子序列元素需要跳著找 }arr[i] = tmp;}printf("第%d次排序、增量為%d后數組:\n", flg++,increment);ShowArr(arr, end+1);} }int main() {int arr[] = { 23,34,13,25,67,74,65,42,31,13,79 };ShellSort(arr, 0, sizeof(arr) / sizeof(arr[0])-1);return 0; }

運行結果:

觀察每一次排序后數組的元素變化,和我們最開始討論希爾排序思想過程一樣。

總結

以上是生活随笔為你收集整理的排序算法——希尔排序(缩小增量排序)的全部內容,希望文章能夠幫你解決所遇到的問題。

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