6 希爾排序

2021-09-25 01:20:22 字數 3794 閱讀 8415

(1)插入排序的基本方法是:每步將乙個待排序的元素,按其排序碼大小插入到前面已經排好序的一組元素的適當位置上去,直到元素全部插入為止。

(2)可以選擇不同的方法在已經排好序的有序資料表中尋找插入位置,依據查詢方法的不同,有多種插入排序方法。下面是常用的三種。

1>直接插入排序

2>折半插入排序

3>希爾排序

(3)直接插入排序基本思想:當插入第i(i>1)個元素時,前面的data[0],data[1]……data[i-1]已經排好序。這時用data[i]的排序碼與data[i-1],data[i-2],……的排序碼順序進行比較,找到插入位置即將data[i]插入,原來位置上的元素向後順序移動。

(4)折半插入排序基本思想:設元素序列data[0],data[1],……data[n-1]。其中data[0],data[1],……data[i-1]是已經排好序的元素。在插入data[i]時,利用折半搜尋法尋找data[i]的插入位置。

(5)希爾排序的過程相比前兩種有些不同,下面我們主要介紹希爾排序的過程實現。

(1)希爾排序(shell sort)這個排序方法又稱為縮小增量排序,是2023年d·l·shell提出來的。該方法的基本思想是:設待排序元素序列有n個元素,首先取乙個整數increment(小於n)作為間隔將全部元素分為increment個子序列,所有距離為increment的元素放在同乙個子串行中,在每乙個子串行中分別實行直接插入排序。然後縮小間隔increment,重複上述子串行劃分和排序工作。直到最後取increment=1,將所有元素放在同乙個子串行中排序為止。

(2)由於開始時,increment的取值較大,每個子串行中的元素較少,排序速度較快,到排序後期increment取值逐漸變小,子串行中元素個數逐漸增多,但由於前面工作的基礎,大多數元素已經基本有序,所以排序速度仍然很快。

(3)希爾排序舉例:

1>下面給出乙個資料列: 

2>第一趟取increment的方法是:n/3向下取整+1=3(關於increment的取法之後會有介紹)。將整個資料列劃分為間隔為3的3個子序列,然後對每乙個子串行執行直接插入排序,相當於對整個序列執行了部分排序調整。**如下:

3>第二趟將間隔increment= increment/3向下取整+1=2,將整個元素序列劃分為2個間隔為2的子串行,分別進行排序。**如下: 

4>第3趟把間隔縮小為increment= increment/3向下取整+1=1,當增量為1的時候,實際上就是把整個數列作為乙個子串行進行插入排序,**如下: 

5>直到increment=1時,就是對整個數列做最後一次調整,因為前面的序列調整已經使得整個序列部分有序,所以最後一次調整也變得十分輕鬆,這也是希爾排序效能優越的體現。 

(4)希爾排序演算法的**實現(c++)

//函式功能,希爾排序演算法對數字遞增排序

//函式引數,數列起點,數列終點

hell_sort(const int start,const int end)

; do

while (j >= start && numbers[j] > temp);

numbers[j + increment] = temp; //插入元素}}

}while(increment >1)

}

上面的函式的第乙個do……while控制increment每次的縮小,其內部便是直接插入排序演算法的使用,與直接插入排序演算法稍有不同的一點是:其j每次的變化量是increment而不是1。 

(5)關於希爾排序increment(增量)的取法。 

增量increment的取法有各種方案。最初shell提出取increment=n/2向下取整,increment=increment/2向下取整,直到increment=1。但由於直到最後一步,在奇數字置的元素才會與偶數字置的元素進行比較,這樣使用這個序列的效率會很低。後來knuth提出取increment=n/3向下取整+1.還有人提出都取奇數為好,也有人提出increment互質為好。應用不同的序列會使希爾排序演算法的效能有很大的差異。

(6)希爾排序應該注意的問題

從上面**希爾排序的過程可以看到,相等的排序碼25在排序前後的順序發生了顛倒,所以希爾排序是一種不穩定的排序演算法。

(1)對希爾排序的時間複雜度分析很困難,在特定情況下可以準確的估算排序碼的比較次數和元素移動的次數,但要想弄清楚排序碼比較次數和元素移動次數與增量選擇之間的依賴關係,並給出完整的數學分析,還沒有人能夠做到。

2)這裡我們把3種常用的插入排序做乙個程式測試,通過每種演算法測試所執行的時間,來定性的認識希爾排序的效能優劣。測試的思路是通過生成1000個1——1000之間的隨機數,令三種排序演算法分別對其進行排序,輸出排序所花費的時間。 

測試:

/*

* 插入排序演算法

*/#include #include #include #include using namespace std;

//vectornumbers;

//vectornumbers;

//vectornumbers;

vectornumbers;

//函式功能,直接插入演算法對數字排序

//函式引數,數列起點,數列終點

void dinsert_sort(const int start, const int end) while (j >= start && numbers[j] > temp);

numbers[j + 1] = temp; //插入元素}}

}//函式功能,折半插入演算法對數字排序

//函式引數,數列起點,數列終點

void binsert_sort(const int start, const int end)

else

}for (int k = i - 1; k >= low; --k)

numbers[low] = temp; //插入元素

}}//函式功能,希爾排序演算法對數字遞增排序

//函式引數,數列起點,數列終點

void shell_sort(const int start, const int end) ;

do while (j >= start && numbers[j] > temp);

numbers[j + increment] = temp; //插入元素}}

} while (increment > 1);

}//函式功能,隨機產生amount個start——end內的隨機數並存入指定容器

//函式引數,隨機數範圍起點,隨機數範圍終點,隨機數生成數量

void producerandomnumbers(const int start, const int end, const int amount)

}int main()

system("pause");

return 0;

}

4,寫在最後

關於數字的排序演算法的研究是乙個樂此不疲的話題,對於這些基本的排序演算法應該常記、常用。也希望大家對文中不當之處給予指正。

**:

排序 希爾排序

希爾排序 shell sort 又稱為縮小增量排序,輸入插入排序演算法,是對直接排序演算法的一種改進。本文介紹希爾排序演算法。對於插入排序演算法來說,如果原來的資料就是有序的,那麼資料就不需要移動,而插入排序演算法的效率主要消耗在資料的移動中。因此可知 如果資料的本身就是有序的或者本身基本有序,那麼...

排序 希爾排序

縮小增量排序 待排序列按關鍵字基本有序時,直接插入排序的效率很高 希爾排序思想 將整個待排記錄分割為若干子串行分別進行直接插入排序,待整個序列中的記錄基本有序時,再對全體記錄進行一次直接插入排序,就可以完成整個排序工作 增量序列中的值沒有除1以外的公因子,且最後乙個增量必須等於1 子串行的構成不是逐...

排序 希爾排序

希爾排序是插入排序中的乙個分支,但是較簡單插入排序又有較大的改進,這使得它成為了歷史上第一批突破二次時間屏障的排序演算法之一哦。它是通過比較一定間隔的元素來工作的。因此希爾排序又稱為縮小增量排序。直接插入排序對於原始資料基本有序的情況下,效率較高。在此的基礎上。我們可以想辦法,使資料基本有序,然後利...