国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序

這篇具有很好參考價(jià)值的文章主要介紹了『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

學(xué)習(xí)目標(biāo)

寫在前面

1.插入排序

2.插入排序?qū)崙?zhàn)?

3.插入排序的實(shí)現(xiàn)?

4.插入排序的效率

5.平均情況

6.希爾排序

7.希爾排序的實(shí)現(xiàn)

8.希爾排序的效率

9.總結(jié)?


『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

寫在前面

之前我們衡量一個(gè)算法的效率時(shí),都是著眼于它在最壞情況下需要多少步。原因很簡(jiǎn)單,連最壞的情況都做足準(zhǔn)備了,其他情況自然不在話下。

但是,在我們實(shí)際生活中并不總是面臨最壞情況,更多的是平均情況。本章我們會(huì)見證一種自適應(yīng)性極強(qiáng)的排序算法---希爾排序,還有它的組成它的關(guān)鍵---插入排序。


1.插入排序

我們已經(jīng)學(xué)過兩種排序算法:冒泡排序選擇排序。雖然它們的效率都是 O(N^2 ),但其實(shí)選擇排序比冒泡排序快一倍。

現(xiàn)在來學(xué)第三種排序算法——插入排序(直接插入排序)。你會(huì)發(fā)現(xiàn),顧及最壞情況以外的場(chǎng)景將是多么有用。插入排序包括以下步驟。

插入排序包括以下步驟。

(1) 在第一輪里,暫時(shí)將索引 1(第 2格)的值移走,并用一個(gè)臨時(shí)變量來保存它。這使得該索引處留下一個(gè)空隙,因?yàn)樗话怠?/p>

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

?在之后的輪回,我們會(huì)移走后面索引的值。

(2) 接著便是平移階段,我們會(huì)拿空隙左側(cè)的每一個(gè)值與臨時(shí)變量的值進(jìn)行比較。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

如果空隙左側(cè)的值大于臨時(shí)變量的值,則將該值右移一格。?

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言隨著值右移,空隙會(huì)左移。如果遇到比臨時(shí)變量小的值,或者空隙已經(jīng)到了數(shù)組的最左端,就結(jié)束平移階段。?

(3) 將臨時(shí)移走的值插入當(dāng)前空隙。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

(4) 重復(fù)第(1)至(3)步,直至數(shù)組完全有序。


2.插入排序?qū)崙?zhàn)?

下面嘗試對(duì) [4, 2, 7, 1, 3] 數(shù)組運(yùn)用插入排序。

第 1輪先從索引 1開始,其值為 2。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

準(zhǔn)備工作:暫時(shí)移走 2,并將其保存在變量 tmp 中。圖中被移到數(shù)組上方的就是
tmp。?

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

?第 1步:比較 4與 tmp中的 2。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

第 2步:因?yàn)?4大于 2,所以把 4右移。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

?于是空隙移到了數(shù)組最左端,沒有其他值可以比較了。

?第 3步:將 tmp插回?cái)?shù)組,完成第一輪。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

開始第 2輪。

準(zhǔn)備工作:暫時(shí)移走索引 2的值,并保存到 tmp中。于是 tmp等于 7。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言第 4步:比較 4與 tmp。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言4小于 7,所以無須平移。因?yàn)橛龅搅诵∮?tmp的值,所以平移階段結(jié)束。

第 5步:將 tmp插回到空隙中,結(jié)束第 2輪。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

開始第 3輪。

準(zhǔn)備工作:暫時(shí)移走 1,并將其保存到 tmp中。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

?第 6步:比較 7與 tmp。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

?第 7步:7大于 1,于是將 7右移。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

?第 8步:比較 4與 tmp。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言第 9步:4大于 1,于是也要將 4右移。?

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

第 10步:比較 2與 tmp。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言第 11步:2比較大,所以將 2右移。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

第 12步:空隙到了數(shù)組最左端,因此我們將 tmp插進(jìn)去,結(jié)束這一輪。?

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

開始第 4輪。

準(zhǔn)備工作:暫時(shí)移走索引 4的值 3,保存到 tmp中。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

第 13步:比較 7和 tmp。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言?第 14步:7更大,于是將 7右移。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言第 15步:比較 4與 tmp。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

第 16步:4大于 3,所以將 4右移。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

第 17步:比較 2與 tmp。2 小于 3,于是平移階段完成。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言?第 18步:把 tmp插回到空隙。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

?至此整個(gè)數(shù)組都排好序了。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言


3.插入排序的實(shí)現(xiàn)?

以下使用C語言實(shí)現(xiàn)的直接插入排序:

void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (a[end] > tmp)         //大于tmp,往后挪一個(gè)
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;          //把tmp插入空隙
	}
}

?讓我們一步步來講解:

for (int i = 0; i < n - 1; i++)

?最外層的這個(gè)循環(huán)用來控制end的位置,也就是一個(gè)輪回。

		int end = i;
		int tmp = a[end + 1];

我們通過控制end的位置,使end與end之前的數(shù)列都是有序的,而把end+1索引處的值(也就是tmp)插入到end之前的數(shù)列中。所以,end的值是從0開始的。這樣能保證end與end之前的數(shù)列是有序的(因?yàn)橹挥幸粋€(gè)數(shù)),那么將tmp插入后,前end+1個(gè)數(shù)都是有序的,再依次執(zhí)行下去。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

while (end >= 0)

end索引處的值會(huì)發(fā)生移動(dòng),最壞的情況是tmp的值比之前的有序數(shù)列中每一個(gè)值都要小,那么空隙的位置就在end=0處。例如:

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

            if (a[end] > tmp)         //大于tmp,往后挪一個(gè)
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}

找到空隙,將比tmp大的數(shù)字不斷往后挪,直到找到小于等于tmp的數(shù)字。

a[end + 1] = tmp;          //把tmp插入空隙

將tmp插入空隙。


4.插入排序的效率

插入排序包含 4種步驟:移除、比較、平移和插入。要分析插入算法的效率,就得把每種步驟都統(tǒng)計(jì)一遍。

首先看看比較。每次拿 tmp跟空隙左側(cè)的值比大小就是比較。

在數(shù)組完全逆序的最壞情況下,我們每一輪都要將 tmp左側(cè)的所有值與tmp比較。因?yàn)槟切┲等即笥?tmp,所以每一輪都要等到空隙移到最左端才能結(jié)束。

對(duì)于含有N個(gè)元素的數(shù)組,可以得出比較的總次數(shù)為:

1 + 2 + 3 + … + N -?1 次。

接下來看看其他幾種步驟。

我們每次將值右移一格,就是平移操作。當(dāng)數(shù)組完全逆序時(shí),有多少次比較就要多少次平移,因?yàn)槊看伪容^的結(jié)果都會(huì)使你將值右移。

因而可以得出平移的總次數(shù)為:

1 + 2 + 3 + … + N -?1 次。

tmp的移除跟插入在每一輪里都會(huì)各發(fā)生一次。因?yàn)榭偸怯?N -?1輪,所以可以得出結(jié)論:有 N -?1次移除和 N -?1次插入。

把它們都相加。

N^2 比較和平移的合計(jì)
+ N -?1 次移除
+ N -?1 次插入
=
N^2 + 2N -?2

我們已經(jīng)知道大 O有一條重要規(guī)則——忽略常數(shù),于是你可能會(huì)將其簡(jiǎn)化成 O(N^2 + N)。不過,現(xiàn)在來學(xué)習(xí)一下大 O的另一條重要規(guī)則:

大 O 只保留最高階的 N

換句話說,如果有個(gè)算法需要 N^4 + N^3 + N^2 + N步,我們就只會(huì)關(guān)注其中的 N^4 ,即以 O(N^4 )
來表示。為什么呢?

請(qǐng)看下表。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

隨著 N的變大,N^4 的增長(zhǎng)越來越拋離其他階。當(dāng) N為 1000時(shí),N^4 就比 N^3 大了 1000倍。因
此,我們只關(guān)心最高階的 N。
所以在插入排序的例子中,O(N^2 + N)還得進(jìn)一步簡(jiǎn)化成 O(N^2 )。

不過上一章曾指出,雖然冒泡排序和選擇排序都是 O(N^2 ),但選擇排序?qū)嶋H上是 N^2 / 2步,
比 N 2 步的冒泡排序更快。乍一看,你可能會(huì)覺得插入排序跟冒泡排序一樣,因?yàn)樗鼈兌际?O(N^2 ),其實(shí)插入排序是 N^2 + 2N -?2步。你或許會(huì)認(rèn)為比冒泡排序和插入排序快一倍的選擇排序是三者中最優(yōu)的,但事情并沒有這么簡(jiǎn)單。


5.平均情況

確實(shí),在最壞情況里,選擇排序比插入排序快。但是我們還應(yīng)該考慮平均情況。

最好情況和最壞情況很少發(fā)生。現(xiàn)實(shí)世界里,最常出現(xiàn)的是平均情況。

這是很有道理的。你設(shè)想一個(gè)隨便洗亂的數(shù)組,出現(xiàn)完全升序或完全降序的可能性有多大?最可能出現(xiàn)的情況應(yīng)該是隨機(jī)分布。

下面試試在各種場(chǎng)景中測(cè)試插入排序。

完全降序的最壞情況之前已經(jīng)見過,它每一輪都要比較和平移所遇到的值(這兩種操作合計(jì)N^2 步)。

對(duì)于完全升序的最好情況,因?yàn)樗兄刀家言谄湔_的位置上,所以每一輪只需要一次比較,完全不用平移。

最壞情況是所有數(shù)據(jù)都要比較和平移;最好情況是每輪一次比較、零次平移;對(duì)于平均情況,總的來看,是比較和平移一半的數(shù)據(jù)。

如果說插入排序的最壞情況需要 N 2 步,那么平均情況就是 N 2 / 2步。盡管最終大 O都會(huì)寫成 O(N^2 )。

可以看到插入排序的性能在不同場(chǎng)景中差異很大。最壞、平均、最好情況,分別需要 N^2 、
N^2 / 2、N步。

那么哪種算法更好?選擇排序還是插入排序?答案是:看情況。對(duì)于平均情況(數(shù)組里的值隨機(jī)分布),它們性能相近。如果你確信數(shù)組是大致有序的,那么插入排序比較好。如果是大致逆序,則選擇排序更快。


6.希爾排序

希爾排序是對(duì)插入排序做了簡(jiǎn)單的優(yōu)化,卻產(chǎn)生了質(zhì)的飛躍。直接讓不太起眼的插入排序比肩聞名算法界的快速排序。我們知道對(duì)于插入排序,數(shù)據(jù)的元素越是接近有序,那么它的效率就越高;對(duì)于完全有序的數(shù)組,它甚至可以快到O(N)。

那么希爾排序的主要思想是,我們不斷地對(duì)數(shù)組進(jìn)行預(yù)排序,使數(shù)組里大的元素盡量到數(shù)組的后面,小的元素盡量到數(shù)組的前面。

完成對(duì)數(shù)組的預(yù)排序看,我們采取的方法是對(duì)數(shù)組進(jìn)行分組,把數(shù)組里間隔相同長(zhǎng)度的元素劃分為一組。例如:

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

?接下來我們對(duì)每一組的元素進(jìn)行排序。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

如圖所示,第一趟排序,較大的元素已經(jīng)到了數(shù)組的后面了。接下來再次重新分組,再次預(yù)排序:

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

經(jīng)過第二趟預(yù)排序,我們發(fā)現(xiàn)數(shù)組已經(jīng)大致接近有序了,那么最后一次,我們?nèi)¢g隔為1分組,其實(shí)就是一次普通的插入排序:

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

至此,數(shù)組已經(jīng)完全有序了。

通過上面的例子不難看出,希爾排序就是對(duì)插入排序的簡(jiǎn)單優(yōu)化,引入了預(yù)排序的概念。

當(dāng)gap>1時(shí),進(jìn)行的是預(yù)排序(也就是對(duì)每一組進(jìn)行插入排序);

當(dāng)gap=1時(shí),進(jìn)行對(duì)整個(gè)數(shù)組的插入排序。


7.希爾排序的實(shí)現(xiàn)

下面使用C語言實(shí)現(xiàn)的希爾排序:

void ShellSort(int* a, int n)
{
	int gap = n;             //間隔
	while (gap > 1)
	{
		gap = gap / 3 + 1;   //+1是為了使gap最后等于1
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}

代碼相較于插入排序并沒有改變多少,在插入排序的基礎(chǔ)上多了一層循環(huán)用來控制gap。

此處可以看出,預(yù)排序并不是固定的3次或者4次。而是取決于數(shù)組元素個(gè)數(shù),這么做一是為了方便控制gap,二是預(yù)排序越多次,對(duì)整體排序而言更有利,所以我們不用吝嗇預(yù)排序,并不是預(yù)排序越多,花費(fèi)的步數(shù)就越多,時(shí)間復(fù)雜度就越高。

gap = gap / 3 + 1; 

除了這樣控制gap外,還有一種常用的方法:

gap = gap / 2; 

但是根據(jù)有人實(shí)驗(yàn)得出,第一種方式比第二種方式快一點(diǎn)點(diǎn),但是差距很細(xì)微,所以兩者皆可。


8.希爾排序的效率

希爾排序的時(shí)間復(fù)雜度并不好算,因?yàn)槊看稳ap的值都不同,而且gap取不同值的情況下,每次預(yù)排序所面臨的數(shù)據(jù)也不同。希爾排序的時(shí)間復(fù)雜度計(jì)算需要運(yùn)用到數(shù)學(xué)知識(shí),而且目前為止我們也沒有得到嚴(yán)格的標(biāo)準(zhǔn)答案。有人在大量實(shí)驗(yàn)的基礎(chǔ)上得出希爾排序的時(shí)間復(fù)雜度接近O(N^1.3)。

《數(shù)據(jù)結(jié)構(gòu)(C語言版)》--- 嚴(yán)蔚敏

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

?《數(shù)據(jù)結(jié)構(gòu)-用面相對(duì)象方法與C++描述》--- 殷人昆

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

因?yàn)槲覀兊膅ap取值的方式是按照Knuth的方式取的,所以以我們這種方式實(shí)現(xiàn)的希爾排序時(shí)間復(fù)雜度暫定為O(N^1.25)。

目前僅僅靠時(shí)間復(fù)雜度的對(duì)比,我們也許感受不到什么叫做質(zhì)的飛躍,那我們就通過一組數(shù)據(jù)來對(duì)比一下二者的差距。

這是一個(gè)測(cè)試排序算法所用時(shí)間的函數(shù):

void TestOP()
{
	srand(time(0));
	const int N = 1000000;
	int* a1 = (int*)malloc(sizeof(int) * N);
	int* a2 = (int*)malloc(sizeof(int) * N);
	int* a3 = (int*)malloc(sizeof(int) * N);
	int* a4 = (int*)malloc(sizeof(int) * N);
	int* a5 = (int*)malloc(sizeof(int) * N);
	int* a6 = (int*)malloc(sizeof(int) * N);
	int* a7 = (int*)malloc(sizeof(int) * N);

	int j = 0;
	for (int i = 0; i < N; ++i)
	{
		a1[i] = rand();
		a2[i] = a1[i];
		a3[i] = a1[i];
		a4[i] = a1[i];
		a5[i] = a1[i];
		a6[i] = a1[i];
		a7[i] = a1[i];
	}
	printf("%d\n", j);

	int begin1 = clock();
	InsertSort(a1, N);
	int end1 = clock();

	int begin2 = clock();
	ShellSort(a2, N);
	int end2 = clock();

	int begin3 = clock();
	//SelectSort(a3, N);
	int end3 = clock();

	int begin4 = clock();
	//HeapSort(a4, N);
	int end4 = clock();

	int begin7 = clock();
	//BubbleSort(a7, N);
	int end7 = clock();

	int begin5 = clock();
	//QuickSort(a5, 0, N - 1);
	int end5 = clock();

	int begin6 = clock();
	//MergeSort(a6, N);
	int end6 = clock();

	printf("InsertSort:%d\n", end1 - begin1);
	printf("ShellSort:%d\n", end2 - begin2);
	printf("SelectSort:%d\n", end3 - begin3);
	printf("HeapSort:%d\n", end4 - begin4);
	printf("BubbleSort:%d\n", end7 - begin7);

	printf("QuickSort:%d\n", end5 - begin5);
	printf("MergeSort:%d\n", end6 - begin6);

	free(a1);
	free(a2);
	free(a3);
	free(a4);
	free(a5);
	free(a6);
}

我們以排序1百萬個(gè)元素為例,得到以下結(jié)果:

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言

?很顯然兩種排序算法已經(jīng)不在一個(gè)數(shù)量級(jí)了。


9.總結(jié)

懂得區(qū)分最好、平均、最壞情況,是為當(dāng)前場(chǎng)景選擇最優(yōu)算法以及給現(xiàn)有算法調(diào)優(yōu)以適應(yīng)環(huán)境變化的關(guān)鍵。記住,雖然為最壞情況做好準(zhǔn)備十分重要,但大部分時(shí)間我們面對(duì)的是平均情況。

『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序,排序算法(C語言版),新星計(jì)劃免費(fèi)學(xué)習(xí)專欄·數(shù)據(jù)結(jié)構(gòu)與算法,算法,排序算法,數(shù)據(jù)結(jié)構(gòu),c語言文章來源地址http://www.zghlxwxcb.cn/news/detail-612930.html

到了這里,關(guān)于『初階數(shù)據(jù)結(jié)構(gòu) ? C語言』⑥ - 插入排序&希爾排序的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)__<八大排序> __插入排序 |希爾排序 |選擇排序 |堆排序 |快速排序 |歸并排序(C語言實(shí)現(xiàn))

    數(shù)據(jù)結(jié)構(gòu)__<八大排序> __插入排序 |希爾排序 |選擇排序 |堆排序 |快速排序 |歸并排序(C語言實(shí)現(xiàn))

    目錄 插入排序? 希爾排序 選擇排序 堆排序 冒泡排序 快速排序 hoare法 挖坑法 前后指針法 快排特性總結(jié) 三數(shù)取中優(yōu)化 小區(qū)間優(yōu)化 快排非遞歸 歸并排序 歸并排序非遞歸 計(jì)數(shù)排序 總結(jié) OJ測(cè)試 1、元素集合越接近有序,直接插入排序算法的時(shí)間效率越高 2、時(shí)間復(fù)雜度:O(N^2

    2023年04月09日
    瀏覽(100)
  • 【數(shù)據(jù)結(jié)構(gòu)】排序之插入排序(直接插入排序||希爾排序)

    【數(shù)據(jù)結(jié)構(gòu)】排序之插入排序(直接插入排序||希爾排序)

    在生活中處處可見排序,當(dāng)我們打開京東或者其它購物平臺(tái)時(shí),搜索物品,它會(huì)有一定的排序。 這次就來分享的博客與排序有關(guān)。 正文開始。 排序 :所謂排序,就是使一串記錄,按照其中的某個(gè)或某些的大小,遞增或遞減的排列起來的操作。 穩(wěn)定性 :假定在待排序

    2024年01月16日
    瀏覽(26)
  • 數(shù)據(jù)結(jié)構(gòu)——插入排序與希爾排序

    數(shù)據(jù)結(jié)構(gòu)——插入排序與希爾排序

    ??個(gè)人主頁:_麥麥_ ??今日名言:喜你成疾,藥石無醫(yī)?!睹倒迮c鹿》 ? ? ? ? 在本篇文章,我們將為小伙伴們進(jìn)行排序概念的基本講解并具體講解其中的兩種基礎(chǔ)排序: 插入排序和希爾排序 ,希望小伙伴們能夠從中有所收獲!??! 1.1排序的概念 排序 :所謂排序,

    2023年04月09日
    瀏覽(24)
  • 【數(shù)據(jù)結(jié)構(gòu)】排序(1) ——插入排序 & 希爾排序

    【數(shù)據(jù)結(jié)構(gòu)】排序(1) ——插入排序 & 希爾排序

    ? ? ? ? ? ? ? ? ? ? ? ? ? 目錄 一. 直接插入排序 ?基本思想 ?代碼實(shí)現(xiàn) ?時(shí)間和空間復(fù)雜度 ?穩(wěn)定性 二. 希爾排序 ?基本思想 ?代碼實(shí)現(xiàn)?? ? ?時(shí)間和空間復(fù)雜度 ?穩(wěn)定性 ? ? ? ? ? ? 把待排序的記錄按其關(guān)鍵碼值的大小依次插入到一個(gè)已經(jīng)排好序的有序序列中,直到

    2024年02月07日
    瀏覽(25)
  • 數(shù)據(jù)結(jié)構(gòu)與算法:插入排序&希爾排序

    數(shù)據(jù)結(jié)構(gòu)與算法:插入排序&希爾排序

    假設(shè)現(xiàn)在你有一個(gè)有序的數(shù)組,你要把一個(gè)數(shù)據(jù)插入到數(shù)組中,保證插入后依然有序,要怎么做? 對(duì)于人來說,這個(gè)問題就像是在整理撲克牌,瞄一眼就知道應(yīng)該插入什么位置。但是對(duì)于程序來說,就需要一一對(duì)比,直到找到一個(gè)位置 左邊比它大,右邊比它小 ,就算找到了

    2024年01月17日
    瀏覽(38)
  • 【數(shù)據(jù)結(jié)構(gòu)】直接插入排序 & 希爾排序(一)

    【數(shù)據(jù)結(jié)構(gòu)】直接插入排序 & 希爾排序(一)

    目錄 一,排序的概念 二,直接插入排序 1,基本思想 2,基本思路 3,思路實(shí)現(xiàn) 三,希爾排序 1,希爾排序的特性總結(jié): 2,思路實(shí)現(xiàn): 排序 :所謂排序,就是使一串記錄,按照其中的某個(gè)或某些的大小,遞增或遞減的排列起來的操作; 穩(wěn)定性 :假定在待排序的記錄

    2024年02月08日
    瀏覽(31)
  • 【數(shù)據(jù)結(jié)構(gòu)】排序:插入排序與希爾排序詳解

    【數(shù)據(jù)結(jié)構(gòu)】排序:插入排序與希爾排序詳解

    本章開始就要分享一些常用的排序方法,我們的日常生活中很多地方都要使用排序,比如電商平臺(tái)可以按照你的需求進(jìn)行排序,或者是你想了解大學(xué)的綜合排名時(shí) ? ?我們之前也學(xué)到過一些簡(jiǎn)單的排序比如冒泡排序,雖然他在時(shí)間復(fù)雜度上可以說是依托答辯,但是作為排序算

    2024年02月13日
    瀏覽(17)
  • 【數(shù)據(jù)結(jié)構(gòu)與算法】:插入排序與希爾排序

    【數(shù)據(jù)結(jié)構(gòu)與算法】:插入排序與希爾排序

    ?? 個(gè)人主頁 : Quitecoder ?? 專欄 : 數(shù)據(jù)結(jié)構(gòu)與算法 歡迎大家來到初階數(shù)據(jù)結(jié)構(gòu)的最后一小節(jié):排序 排序是一種將一組對(duì)象按照某種特定順序重新排列的過程。在計(jì)算機(jī)科學(xué)中,排序是數(shù)據(jù)處理中非?;厩抑匾牟僮?,它可以幫助人們更有效地理解和分析數(shù)據(jù)。排序的順序

    2024年03月18日
    瀏覽(29)
  • 【數(shù)據(jù)結(jié)構(gòu)與算法】插入排序和希爾排序

    【數(shù)據(jù)結(jié)構(gòu)與算法】插入排序和希爾排序

    ? 目錄 一.插入排序? InsertSort 基本思想 動(dòng)圖演示 ?特性總結(jié) 二.希爾排序? ShellSort 基本思想 圖例 特性總結(jié) 基本思想 把待排序的記錄按其關(guān)鍵碼值的大小逐個(gè)插入到一個(gè)已經(jīng)排好序的有序序列中,直到所有的記錄插入完為止,得到一個(gè)新的有序序列 。 當(dāng)插入第i(i=1)個(gè)元素

    2023年04月18日
    瀏覽(24)
  • 【數(shù)據(jù)結(jié)構(gòu)】常見排序算法——常見排序介紹、插入排序、直接插入排序、希爾排序

    【數(shù)據(jù)結(jié)構(gòu)】常見排序算法——常見排序介紹、插入排序、直接插入排序、希爾排序

    ??在計(jì)算機(jī)科學(xué)中,排序是將一組數(shù)據(jù)按照指定的順序排列的過程。排序算法由于執(zhí)行效率的不同可以分為多種不同的算法。 ??通常情況下,排序算法可以分為兩類,即 內(nèi)部排序和外部排序 。內(nèi)部排序是指數(shù)據(jù)全部加載到內(nèi)存中進(jìn)行排序,適用于數(shù)據(jù)量較小的情況,而

    2024年02月08日
    瀏覽(34)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包