插入排序算法之希爾排序+直接插入排序
希爾排序
在介紹希爾排序之前,先了解一下直接插入排序
一、直接插入排序
1. 單趟排序
x插入一個(gè)有序區(qū)間

這里end是指向數(shù)組最后一個(gè)元素

2. 直接插入排序
根據(jù)上面的單趟排序啟發(fā)
end是數(shù)組的最后一個(gè)元素,end之后的元素都是待排序

一個(gè)關(guān)鍵的判斷點(diǎn),end和x比較大小
這里end < x
還需要再做改善

可以發(fā)現(xiàn)有兩個(gè)循環(huán),一個(gè)循環(huán)時(shí)end倒著遍歷完之后,使得最開(kāi)始的end結(jié)束的數(shù)組加入x后是一個(gè)有序數(shù)組,最后再返回這個(gè)新數(shù)組的最后一個(gè)元素所在位置
注意公共部分
end--; x = a[end + 1];
外面是一個(gè)for循環(huán),從第二個(gè)到最后一個(gè)元素
for(i = 0; i < n - 1; i++)
{
}
代碼:
//插入排序
void InsetSort(int* a, int n)
{
int end = 0;
int i = 0;
for (i = 0; i < n - 1; i++)
{
end = i;
int x = a[end + 1];
while (end >= 0)
{
if (a[end] > x)
{
a[end + 1] = a[end];
a[end] = x;
}
else
{
break;
}
end--;
}
}
}
時(shí)間復(fù)雜度O(N2)
測(cè)試:
int main()
{
int a[4] = { 2, 6, 5, 3 };
InsetSort(a, 4);
//ShellSort(a, 4);
int i = 0;
for (i = 0; i < 4; i++)
{
printf("%d ", a[i]);
}
printf("\n");
return 0;
}

二、希爾排序
希爾排序法又稱縮小增量法
希爾排序法的基本思想是:先選定一個(gè)整數(shù),把待排序文件中所有記錄分成
gap個(gè)組,所有距離為的記錄分在同一組內(nèi),并對(duì)每一組內(nèi)的記錄進(jìn)行排序。然后,重復(fù)上述分組和排序的工作。當(dāng)?shù)竭_(dá)gap=1時(shí),所有記錄在統(tǒng)一組內(nèi)排好序。
希爾排序是根據(jù)直接插入排序的基礎(chǔ)上,先進(jìn)行分組排序

以3個(gè)為一組進(jìn)行排序

時(shí)間復(fù)雜度:
每次排可以看作長(zhǎng)度為gap的數(shù)組直接插入排序
一共有gap組,當(dāng)然并不是每組都是gap/n個(gè)元素,但當(dāng)數(shù)據(jù)相當(dāng)多的時(shí)候我們看作每個(gè)數(shù)組都有gap/n個(gè)元素
所以是 (1+2……+n/gap)gap
如果gap = 1,則時(shí)間復(fù)雜度是O(n2),相當(dāng)于直接插入排序
//希爾排序
void ShellSort(int* a, int n)
{
int end = 0;
int i = 0;
int j = 0;
int gap = 6;
//預(yù)排序
for (j = 0; j < gap; j++)
{
//最后一個(gè)數(shù)一定是1
gap = gap / 2;
for (i = 0; i < n - gap; i++)
{
end = i;
//這里其實(shí)就是直接插入排序,而數(shù)組的每個(gè)元素間隔是gap
int x = a[end + gap];
while (end >= 0)
{
if (a[end] > x)
{
a[end + gap] = a[end];
a[end] = x;
}
else
{
break;
}
end -= gap;
}
}
}
}
測(cè)試用例還是上面直接插入排序的例子
結(jié)果還是成功的

三、測(cè)試希爾排序和直接插入排序性能
//性能測(cè)試
void TestOP()
{
srand(time(0));
//以1000個(gè)數(shù)字為例
const int N = 10000;
int* a1 = (int*)malloc(sizeof(int) * N);
int* a2 = (int*)malloc(sizeof(int) * N);
for (int i = 0; i < N; ++i)
{
a1[i] = rand();
a2[i] = a1[i];
}
//這里clock是運(yùn)行到這里的時(shí)間
int begin1 = clock();
InsertSort(a1, N);
int end1 = clock();
int begin2 = clock();
ShellSort(a2, N);
int end2 = clock();
//end-begin為排序所用時(shí)間
printf("%d\n%d\n", end1 - begin1, end2 - begin2);
}

可以看出希爾排序比直接排序快得多,但希爾排序因?yàn)間ap可以改變,目前沒(méi)有一個(gè)統(tǒng)一的時(shí)間復(fù)雜度,先按照時(shí)間復(fù)雜度為O(n1.3)來(lái)吧
到此這篇關(guān)于插入排序算法之希爾排序+直接插入排序的文章就介紹到這了,更多相關(guān)插入排序算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)leetcode(3.最長(zhǎng)無(wú)重復(fù)字符的子串)
這篇文章主要介紹了C++實(shí)現(xiàn)leetcode(3.最長(zhǎng)無(wú)重復(fù)字符的子串),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C++獲取本機(jī)登陸過(guò)的QQ號(hào)碼示例程序
這篇文章主要介紹了使用C++獲取本機(jī)登陸過(guò)的QQ號(hào)碼列表的程序示例,大家可以參考使用2013-11-11
C語(yǔ)言實(shí)現(xiàn)返回字符串函數(shù)的四種方法
在C語(yǔ)言中實(shí)現(xiàn)函數(shù)返回字符串,首先要確定函數(shù)返回的字符串地址的來(lái)源,一般分為四種方式,下面這篇文章就給大家通過(guò)示例代碼詳細(xì)介紹這幾種方法,有需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。2016-12-12
C語(yǔ)言實(shí)現(xiàn)堆排序的簡(jiǎn)單實(shí)例
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)堆排序的簡(jiǎn)單實(shí)例,講述了堆排序的原理,需要的朋友可以參考下2014-07-07
標(biāo)準(zhǔn)C++類string的Copy-On-Write技術(shù)
這里,我想從C++類或是設(shè)計(jì)模式的角度為各位揭開(kāi)Copy-On-Write技術(shù)在string中實(shí)現(xiàn)的面紗,以供各位在用C++進(jìn)行類庫(kù)設(shè)計(jì)時(shí)做一點(diǎn)參考2013-11-11
C語(yǔ)言中strcpy和strcat的使用和模擬實(shí)現(xiàn)
strcpy()?函數(shù)是?C語(yǔ)言中一個(gè)非常重要的字符串處理函數(shù),其功能是將一個(gè)字符串復(fù)制到另一個(gè)字符串中,strcat函數(shù)可以將一個(gè)字符串拼接到另一個(gè)字符串的末尾,本文給大家介紹了C語(yǔ)言中strcpy和strcat的使用和模擬實(shí)現(xiàn),需要的朋友可以參考下2024-03-03
在while中使用cin>>a?為條件及注意事項(xiàng)說(shuō)明
這篇文章主要介紹了在while中使用cin>>a?為條件及注意事項(xiàng)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07

