七種常見的數(shù)組排序算法整理(C語(yǔ)言版本)

2019 iOS面試題大全---全方面剖析面試
2018 iOS面試題---算法相關(guān)
1、七種常見的數(shù)組排序算法整理(C語(yǔ)言版本)
2组贺、2019 算法面試相關(guān)(leetcode)--數(shù)組和鏈表
3、2019 算法面試相關(guān)(leetcode)--字符串
4祖娘、2019 算法面試相關(guān)(leetcode)--棧和隊(duì)列
5失尖、2019 算法面試相關(guān)(leetcode)--優(yōu)先隊(duì)列
6、2019 算法面試相關(guān)(leetcode)--哈希表
7、2019 算法面試相關(guān)(leetcode)--樹雹仿、二叉樹增热、二叉搜索樹
8、2019 算法面試相關(guān)(leetcode)--遞歸與分治
9胧辽、2019 算法面試相關(guān)(leetcode)--貪心算法
10峻仇、2019 算法面試相關(guān)(leetcode)--動(dòng)態(tài)規(guī)劃(Dynamic Programming)
11、2019 算法面試相關(guān)(leetcode)--動(dòng)態(tài)規(guī)劃之背包問題


~~~C語(yǔ)言版本~~~

  • 冒泡排序
  • 選擇排序
  • 直接插入排序
  • 二分插入排序
  • 希爾排序
  • 快速排序
  • 堆排序
#define EXCHANGE(num1, num2)  { num1 = num1 ^ num2;\
num2 = num1 ^ num2;\
num1 = num1 ^ num2;}

排序算法是否穩(wěn)定:相同元素的相對(duì)在排序前后是否會(huì)發(fā)生改變邑商,如果會(huì)摄咆,就是不穩(wěn)定的,否則就是穩(wěn)定的人断。
一.冒泡排序
冒泡排序原理很容易理解吭从,就是重復(fù)地走訪過要排序的元素列,依次比較兩個(gè)相鄰的元素恶迈,順序不對(duì)就交換涩金,直至沒有相鄰元素需要交換,也就是排序完成暇仲。
這個(gè)算法的名字由來(lái)是因?yàn)樵酱蟮脑貢?huì)經(jīng)由交換慢慢“浮”到數(shù)列的頂端(升序或降序排列)步做,就如同碳酸飲料中二氧化碳的氣泡最終會(huì)上浮到頂端一樣,故名“冒泡排序”奈附。

  • 冒泡排序是一種穩(wěn)定排序算法全度。
  • 時(shí)間復(fù)雜度:最好情況(初始情況就是正序)下是o(n),平均情況是o(n2)
void buddleSort(int num[],int count)
{
    for (int i = 0; i < count - 1; i++) {

        for (int j = 0; j < count - i - 1; j++) {

            if (num[j] > num[j + 1]) EXCHANGE(num[j], num[j + 1])
        }
    }
}

二、選擇排序
選擇排序(Selection sort)是一種簡(jiǎn)單直觀的排序算法斥滤。它的工作原理是每一次從待排序的數(shù)據(jù)元素中選出最薪摇(或最大)的一個(gè)元素,存放在序列的起始位置佑颇,然后顶掉,再?gòu)氖S辔磁判蛟刂欣^續(xù)尋找最小(大)元素漩符,然后放到已排序序列的末尾一喘。以此類推驱还,直到全部待排序的數(shù)據(jù)元素排完嗜暴。
選擇排序的交換操作介于 0 和 (n - 1) 次之間。選擇排序的比較操作為 n (n - 1) / 2 次之間议蟆。選擇排序的賦值操作介于 0 和 3 (n - 1) 次之間闷沥。
比較次數(shù)O(n2),比較次數(shù)與關(guān)鍵字的初始狀態(tài)無(wú)關(guān)咐容,總的比較次數(shù)N=(n-1)+(n-2)+...+1=n*(n-1)/2舆逃。交換次數(shù)O(n),最好情況是,已經(jīng)有序路狮,交換0次虫啥;最壞情況交換n-1次,逆序交換n/2次奄妨。交換次數(shù)比冒泡排序少多了涂籽,由于交換所需CPU時(shí)間比比較所需的CPU時(shí)間多,n值較小時(shí)砸抛,選擇排序比冒泡排序快

  • 選擇排序是不穩(wěn)定的排序方法评雌。
  • 時(shí)間復(fù)雜度:最好和平均情況下都是O(n2)
void selectSort(int num[],int count)
{
    for (int i = 0; i < count; i++) {

        int min = i;

        for (int j = i; j < count; j++) {
            
            if (num[j] < num[min])  min = j;
        }

        if (i != min)   EXCHANGE(num[i], num[min]);//可以看出,最多交換count - 1次
    }
}

三直焙、直接插入排序
插入排序的基本操作就是將一個(gè)數(shù)據(jù)插入到已經(jīng)排好序的有序數(shù)據(jù)中景东,從而得到一個(gè)新的、個(gè)數(shù)加一的有序數(shù)據(jù)奔誓,算法適用于少量數(shù)據(jù)的排序斤吐,
插入排序的基本思想是:每步將一個(gè)待排序的記錄,按其關(guān)鍵碼值的大小插入前面已經(jīng)排序的文件中適當(dāng)位置上厨喂,直到全部插入完為止

  • 直接插入排序是穩(wěn)定的排序算法曲初。
  • 時(shí)間復(fù)雜度:最好情況(初始情況就是正序)下是o(n),平均情況是o(n2)
void insertSort2(int num[],int count)
{
    int i,j;
    
    for (i = 1; i < count; i++) {
        
        if (num[i] < num[i - 1]) {
            
            int temp = num[i];
            
            for (j = i; j > 0; j--) {
                
                if (num[j - 1] > temp) num[j] = num[j - 1];
                
                else break;
            }
            
            num[j] = temp;
        }
    }
}

四、二分插入排序

由于在插入排序過程中杯聚,待插入數(shù)據(jù)左邊的序列總是有序的臼婆,針對(duì)有序序列,就可以用二分法去插入數(shù)據(jù)了幌绍,也就是二分插入排序法颁褂。適用于數(shù)據(jù)量比較大的情況。
二分插入排序的算法思想:
算法的基本過程:
(1)計(jì)算 0 ~ i-1 的中間點(diǎn)傀广,用 i 索引處的元素與中間值進(jìn)行比較颁独,如果 i 索引處的元素大,說明要插入的這個(gè)元素應(yīng)該在中間值和剛加入i索引之間伪冰,反之誓酒,就是在剛開始的位置 到中間值的位置,這樣很簡(jiǎn)單的完成了折半贮聂;
(2)在相應(yīng)的半個(gè)范圍里面找插入的位置時(shí)靠柑,不斷的用(1)步驟縮小范圍,不停的折半吓懈,范圍依次縮小為 1/2 1/4 1/8 .......快速的確定出第 i 個(gè)元素要插在什么地方歼冰;
(3)確定位置之后,將整個(gè)序列后移耻警,并將元素插入到相應(yīng)位置隔嫡。

  • 二分插入排序是穩(wěn)定的排序算法甸怕。
  • 時(shí)間復(fù)雜度:最好情況(剛好插入位置為二分位置)下是O(log?n),平均情況和最壞情況是o(n2)
void insertSortBinary(int num[],int count)
{
    int i,j;
    
    for (i = 1; i < count; i++) {
        
        if (num[i] < num[i - 1]) {
            
            int temp = num[i];
            
            int left = 0,right = i - 1;
            
            while (left <= right) {
                
                int mid = (left + right)/2;
                
                if (num[mid] < temp) left = mid + 1;
                    
                else right = mid - 1;
            }
            //只是比較次數(shù)變少了,交換次數(shù)還是一樣的
            for (j = i; j > left; j--) {
                
                num[j] = num[j - 1];
            }
            
            num[left] = temp;
        }
    }
}

五腮恩、希爾(插入)排序
希爾排序(Shell's Sort)是插入排序的一種又稱“縮小增量排序”(Diminishing Increment Sort)梢杭,是直接插入排序算法的一種更高效的改進(jìn)版本。
希爾排序是把記錄按下標(biāo)的一定增量分組秸滴,對(duì)每組使用直接插入排序算法排序式曲;隨著增量逐漸減少,每組包含的關(guān)鍵詞越來(lái)越多缸榛,當(dāng)增量減至1時(shí)吝羞,整個(gè)文件恰被分成一組,排序完成内颗。

  • 希爾排序是非穩(wěn)定排序算法钧排。
  • 時(shí)間復(fù)雜度:O(n^(1.3—2))
void shellSort(int num[],int count)
{
    int shellNum = 2;
    int gap = round(count/shellNum);

    while (gap > 0) {
        for (int i = gap; i < count; i++) {
            int temp = num[i];
            int j = i;
            while (j >= gap && num[j - gap] > temp) {
                num[j] = num[j - gap];
                j = j - gap;
            }
            num[j] = temp;
        }
        gap = round(gap/shellNum);
    }
}

六、快速排序
快速排序(Quicksort)是對(duì)冒泡排序的一種改進(jìn)均澳。

它的基本思想是:通過一趟排序?qū)⒁判虻臄?shù)據(jù)分割成獨(dú)立的兩部分恨溜,其中一部分的所有數(shù)據(jù)都比另外一部分的所有數(shù)據(jù)都要小,然后再按此方法對(duì)這兩部分?jǐn)?shù)據(jù)分別進(jìn)行快速排序找前,整個(gè)排序過程可以遞歸進(jìn)行糟袁,以此達(dá)到整個(gè)數(shù)據(jù)變成有序序列。

  • 快速排序是非穩(wěn)定的排序算法
  • 時(shí)間復(fù)雜度:最差為O(n^2)躺盛,平均為O(nlogn)项戴,最好為O(nlogn)
void quickSort(int num[],int count,int left,int right)
{
    if (left >= right){
        
        return ;
    }
    int key = num[left];
    int lp = left;           //左指針
    int rp = right;          //右指針
    while (lp < rp) {
        if (num[rp] < key) {
            int temp = num[rp];
            for (int i = rp - 1; i >= lp; i--) {
                num[i + 1] = num[i];
            }
            num[lp] = temp;
            lp ++;
            rp ++;
        }
        rp --;
    }
    quickSort(num,count,left,lp - 1);
    quickSort(num,count,rp + 1,right);
}

七、堆排序
是指利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計(jì)的一種排序算法槽惫。堆是一個(gè)近似完全二叉樹的結(jié)構(gòu)周叮,并同時(shí)滿足堆積的性質(zhì):即子結(jié)點(diǎn)的鍵值或索引總是小于(或者大于)它的父節(jié)點(diǎn)

在堆的數(shù)據(jù)結(jié)構(gòu)中,堆中的最大值總是位于根節(jié)點(diǎn)(在優(yōu)先隊(duì)列中使用堆的話堆中的最小值位于根節(jié)點(diǎn))界斜。堆中定義以下幾種操作:

  • 最大堆調(diào)整(Max Heapify):將堆的末端子節(jié)點(diǎn)作調(diào)整仿耽,使得子節(jié)點(diǎn)永遠(yuǎn)小于父節(jié)點(diǎn)

  • 創(chuàng)建最大堆(Build Max Heap):將堆中的所有數(shù)據(jù)重新排序

  • 堆排序(HeapSort):移除位在第一個(gè)數(shù)據(jù)的根節(jié)點(diǎn),并做最大堆調(diào)整的遞歸運(yùn)算

  • 堆排序是一個(gè)非穩(wěn)定的排序算法各薇。
  • 時(shí)間復(fù)雜度:O(nlogn)
void maxHeapify(int num[], int start, int end) {
    //建立父節(jié)點(diǎn)指標(biāo)和子節(jié)點(diǎn)指標(biāo)
    int dad = start;
    int son = dad * 2 + 1;
    while (son <= end) { //若子節(jié)點(diǎn)指標(biāo)在范圍內(nèi)才做比較
        if (son + 1 <= end && num[son] < num[son + 1]) //先比較兩個(gè)子節(jié)點(diǎn)大小项贺,選擇最大的
            son++;
        if (num[dad] > num[son]) //如果父節(jié)點(diǎn)大於子節(jié)點(diǎn)代表調(diào)整完畢,直接跳出函數(shù)
            return;
        else { //否則交換父子內(nèi)容再繼續(xù)子節(jié)點(diǎn)和孫節(jié)點(diǎn)比較
            EXCHANGE(num[dad], num[son])
            dad = son;
            son = dad * 2 + 1;
        }
    }
}

void heapSort(int num[], int count) {
    int i;
    //初始化峭判,i從最後一個(gè)父節(jié)點(diǎn)開始調(diào)整
    for (i = count / 2 - 1; i >= 0; i--)
        maxHeapify(num, i, count - 1);
    //先將第一個(gè)元素和已排好元素前一位做交換开缎,再重新調(diào)整,直到排序完畢
    for (i = count - 1; i > 0; i--) {
        EXCHANGE(num[0], num[i])
        maxHeapify(num, 0, i - 1);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末朝抖,一起剝皮案震驚了整個(gè)濱河市啥箭,隨后出現(xiàn)的幾起案子谍珊,更是在濱河造成了極大的恐慌治宣,老刑警劉巖急侥,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異侮邀,居然都是意外死亡坏怪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門绊茧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)铝宵,“玉大人,你說我怎么就攤上這事华畏∨羟铮” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵亡笑,是天一觀的道長(zhǎng)侣夷。 經(jīng)常有香客問我,道長(zhǎng)仑乌,這世上最難降的妖魔是什么百拓? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮晰甚,結(jié)果婚禮上衙传,老公的妹妹穿的比我還像新娘。我一直安慰自己厕九,他們只是感情好蓖捶,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著扁远,像睡著了一般腺阳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上穿香,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天亭引,我揣著相機(jī)與錄音,去河邊找鬼皮获。 笑死焙蚓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的洒宝。 我是一名探鬼主播购公,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼雁歌!你這毒婦竟也來(lái)了宏浩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤靠瞎,失蹤者是張志新(化名)和其女友劉穎比庄,沒想到半個(gè)月后求妹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡佳窑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年制恍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片神凑。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡净神,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出溉委,到底是詐尸還是另有隱情鹃唯,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布瓣喊,位于F島的核電站俯渤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏型宝。R本人自食惡果不足惜八匠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望趴酣。 院中可真熱鬧梨树,春花似錦、人聲如沸岖寞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)仗谆。三九已至指巡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間隶垮,已是汗流浹背藻雪。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留狸吞,地道東北人勉耀。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蹋偏,于是被迫代替她去往敵國(guó)和親便斥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 概述 排序有內(nèi)部排序和外部排序威始,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序枢纠,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    蟻前閱讀 5,164評(píng)論 0 52
  • 面試中常用的幾個(gè)基本算法整理記錄(二) 無(wú)意中看到了面試中的 10 大排序算法總結(jié)原文地址記錄一下黎棠,方便查找晋渺。 查...
    190CM閱讀 1,746評(píng)論 1 13
  • 概述 排序有內(nèi)部排序和外部排序镰绎,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大些举,一次不能容納全部...
    閑云清煙閱讀 756評(píng)論 0 6
  • 不動(dòng)聲色的刺人才最傷人跟狱。 我剛才面試被狠狠的刺了一通俭厚。我本來(lái)抱有希望的户魏,結(jié)果面對(duì)的HR不動(dòng)聲色的給了幾刀。如果說之...
    明初的日記本閱讀 231評(píng)論 0 0
  • 名人分別為:亞里士多德挪挤,牧師葛培理叼丑,馬丁路德,愛因斯坦扛门,詩(shī)人毛姆鸠信,加拿大銀行家Acetone, 美國(guó)音樂家Wond...
    舒己懷_Frank閱讀 561評(píng)論 10 21