C語(yǔ)言深入探究直接插入排序與希爾排序使用案例講解
一.直接插入排序
1.1直接插入排序引入
排序是我們生活中經(jīng)常會(huì)面對(duì)的問(wèn)題,以打撲克牌為例,你摸的手牌肯定是雜亂的,你一定會(huì)將小牌移動(dòng)到大牌的左面,大牌移動(dòng)到小牌的右面,這樣順序就算理好了。這里我們的理牌方法就是直接插入排序。
1.2直接插入排序的核心思想與算法分析
核心思想: 就是將一個(gè)記錄插入到已經(jīng)排好序的有序表中,從而得到一個(gè)新的記錄數(shù)增1的有序表。
算法分析:
- 從序列第一個(gè)元素開(kāi)始,該元素可以認(rèn)為已經(jīng)被排序
- 取出下一個(gè)元素,設(shè)為待插入元素,在已經(jīng)排序的元素序列中從后向前掃描,如果該元素(已排序)大于待插入元素,將該元素移到下一位置。
- 重復(fù)步驟2,直到找到已排序的元素小于或者等于待排序元素的位置,插入元素。
- 重復(fù)2,3步驟,完成排序。
1.3實(shí)例說(shuō)明
以12,2,9,8,18,7這幾個(gè)數(shù)字為例,排序過(guò)程:
- 這里三角形表示要插入的值
- 橫線表示已經(jīng)排好序的數(shù)字
- j是趟數(shù),是這一趟開(kāi)始的時(shí)候已排序隊(duì)列的最后一個(gè)值的下標(biāo)。
1.4直接插入排序代碼實(shí)現(xiàn)
代碼如下:
void InsertSort(int* arr, int len) { //assert arr!=NULL for (int i = 1; i < len; i++)//一共跑了多少趟 //01234 12345 { int tmp = arr[i];//待插入的值 //j 指向 這一趟開(kāi)始的時(shí)候的已排序好的隊(duì)列中最后一個(gè)值的下標(biāo) int j; for (j = i - 1; j >= 0; j--)//這里控制待插入的值和 已排序隊(duì)列的挨著比較(從右向左比較) { if (arr[j] <= tmp) { break;//這時(shí)應(yīng)該停下來(lái) } else { arr[j + 1] = arr[j]; } } arr[j + 1] = tmp; } }
1.5直接插入排序性能分析
時(shí)間復(fù)雜度:
(1)順序排序時(shí),只需比較(n-1)次,插入排序時(shí)間復(fù)雜度為O(n);
(2)逆序排序時(shí),需比較n(n-1)/2次,插入排序時(shí)間復(fù)雜度為O(n^2);
(3)當(dāng)原始序列雜亂無(wú)序時(shí),平均時(shí)間復(fù)雜度為O(n^2)。
空間復(fù)雜度:
插入排序過(guò)程中,需要一個(gè)臨時(shí)變量temp存儲(chǔ)待排序元素,因此空間復(fù)雜度為O(1)。
算法穩(wěn)定性:
插入排序是一種穩(wěn)定的排序算法。
二.希爾排序
2.1希爾排序引入
希爾排序其實(shí)就是對(duì)直接插入排序的優(yōu)化,在第一部分我們說(shuō)過(guò)==(1)直接插入排序數(shù)據(jù)越有序,插入的效率就越高;(2)記錄數(shù)比較少時(shí),直接插入的優(yōu)勢(shì)也很明顯。==希爾排序就是根據(jù)這兩個(gè)特點(diǎn)進(jìn)行的優(yōu)化。
2.2希爾排序的核心思想與算法分析
核心思想: 通過(guò)一個(gè)不斷縮小的增量序列,對(duì)無(wú)序序列反復(fù)的進(jìn)行拆分并且對(duì)拆分后的序列使用插入排序的。
算法分析:
- 先將整個(gè)待排元素序列分割成若干個(gè)子序列(由相隔某個(gè)“增量”的元素組成的);
- 分別進(jìn)行直接插入排序,然后依次縮減增量再進(jìn)行排序;
- 待整個(gè)序列中的元素基本有序(增量足夠小)時(shí),再對(duì)全體元素進(jìn)行一次直接插入排序;
- 完成排序。
2.3實(shí)例說(shuō)明
以12,2,9,8,5,88,99,10,7,17,77,66,89,10,21為例,排序過(guò)程如下:
- 這里相同顏色的線相同的分組
- 每次增量取上一次的一半(向下取整)
- 注意:最后一個(gè)增量值必須等于1才可以
2.4希爾排序代碼實(shí)現(xiàn)
代碼如下:
void Shell(int arr[], int len, int gap)//一趟希爾排序 { for (int i = gap; i < len; i++)//i++ 不是i=i+gap; { int tmp = arr[i];//待插入的值 //j 指向 這一趟開(kāi)始的時(shí)候的已排序好的隊(duì)列中最后一個(gè)值的下標(biāo) int j; for (j = i - gap; j >= 0; j = j - gap)//這里控制待插入的值和 已排序隊(duì)列的挨著比較(從右向左比較) { if (arr[j] <= tmp) { break;//這時(shí)應(yīng)該停下來(lái) } else { arr[j + gap] = arr[j]; } } arr[j + gap] = tmp; } } void ShellSort(int arr[], int len) { int gap[] = { 5, 3, 1 };// int gap_len = sizeof(gap) / sizeof(gap[0]); for (int i = 0; i < gap_len; i++) { Shell(arr, len, gap[i]); } }
2.5希爾排序性能分析
時(shí)間復(fù)雜度:
希爾排序的時(shí)間復(fù)雜度依賴于增量序列的函數(shù),當(dāng)n在某個(gè)特定的范圍后最優(yōu)的情況下,希爾排序的時(shí)間復(fù)雜度為O(n ^ 1.3),在最差的情況下,希爾排序的時(shí)間復(fù)雜度為:O(n ^ 2)。
空間復(fù)雜度:
希爾排序的空間復(fù)雜度:O(1)。
算法穩(wěn)定性:
希爾排序并不是一種穩(wěn)定的排序算法。
到此這篇關(guān)于C語(yǔ)言深入探究直接插入排序與希爾排序使用案例講解的文章就介紹到這了,更多相關(guān)C語(yǔ)言排序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言用循環(huán)單鏈表實(shí)現(xiàn)約瑟夫環(huán)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言用循環(huán)單鏈表實(shí)現(xiàn)約瑟夫環(huán),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10結(jié)合C++11新特性來(lái)學(xué)習(xí)C++中l(wèi)ambda表達(dá)式的用法
這篇文章主要介紹了C++中l(wèi)ambda表達(dá)式的用法,lambda表達(dá)式的引入可謂是C++11中的一大亮點(diǎn),同時(shí)文中也涉及到了C++14標(biāo)準(zhǔn)中關(guān)于lambda的一些內(nèi)容,需要的朋友可以參考下2016-01-01C++找出字符串中出現(xiàn)最多的字符和次數(shù),時(shí)間復(fù)雜度小于O(n^2)
今天小編就為大家分享一篇關(guān)于C++找出字符串中出現(xiàn)最多的字符和次數(shù),時(shí)間復(fù)雜度小于O(n^2),小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12C++回調(diào)函數(shù)實(shí)現(xiàn)計(jì)算器和qsort
這篇文章主要介紹了C++回調(diào)函數(shù)實(shí)現(xiàn)計(jì)算器和qsort,回調(diào)函數(shù)就是一個(gè)通過(guò)函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用來(lái)調(diào)用其所指向的函數(shù)時(shí),我們就說(shuō)這是回調(diào)函數(shù)2022-08-08C++返回值是類名和返回值是引用的區(qū)別及說(shuō)明
這篇文章主要介紹了C++返回值是類名和返回值是引用的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11