12-C語言排序算法-指趣學(xué)院

計數(shù)排序(Counting Sort)

  • 計數(shù)排序是一個非基于比較的排序算法特咆,該算法于1954年由 Harold H. Seward 提出妒牙。它的優(yōu)勢在于在對一定范圍內(nèi)的整數(shù)排序時贵扰,快于任何比較排序算法。
  • 排序思路:
    • 1.找出待排序數(shù)組最大值
    • 2.定義一個索引最大值為待排序數(shù)組最大值的數(shù)組
    • 3.遍歷待排序數(shù)組, 將待排序數(shù)組遍歷到的值作新數(shù)組索引
    • 4.在新數(shù)組對應(yīng)索引存儲值原有基礎(chǔ)上+1


  • 簡單代碼實(shí)現(xiàn):
int main()
{
    // 待排序數(shù)組
    int nums[5] = {3, 1, 2, 0, 3};
    // 用于排序數(shù)組
    int newNums[4] = {0};
    // 計算待排序數(shù)組長度
    int len = sizeof(nums) / sizeof(nums[0]);
    // 遍歷待排序數(shù)組
    for(int i = 0; i < len; i++){
        // 取出待排序數(shù)組當(dāng)前值
        int index = nums[i];
        // 將待排序數(shù)組當(dāng)前值作為排序數(shù)組索引
        // 將用于排序數(shù)組對應(yīng)索引原有值+1
        newNums[index] = newNums[index] +1;
    }
    
    // 計算待排序數(shù)組長度
    int len2 = sizeof(newNums) / sizeof(newNums[0]);
    // 輸出排序數(shù)組索引, 就是排序之后結(jié)果
    for(int i = 0; i < len2; i++){
        for(int j = 0; j < newNums[i]; j++){
            printf("%i\n", i);
        }
    }
    /*
    // 計算待排序數(shù)組長度
    int len2 = sizeof(newNums) / sizeof(newNums[0]);
    // 還原排序結(jié)果到待排序數(shù)組
    for(int i = 0; i < len2; i++){
        int index = 0;
        for(int i = 0; i < len; i++){
            for(int j = 0; j < newNums[i]; j++){
                nums[index++] = i;
            }
        }
    }
    */
    return 0;
}

選擇排序

  • 選擇排序(Selection sort)是一種簡單直觀的排序算法浇雹。它的工作原理如下稿蹲。首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續(xù)尋找最小元素,然后放到排序序列末尾。以此類推,直到所有元素均排序完畢皂冰。


  • 排序思路:

    • 假設(shè)按照升序排序
    • 1.用第0個元素和后面所有元素依次比較
    • 2.判斷第0個元素是否大于當(dāng)前被比較元素, 一旦小于就交換位置
    • 3.第0個元素和后續(xù)所有元素比較完成后, 第0個元素就是最小值
    • 4.排除第0個元素, 用第1個元素重復(fù)1~3操作, 比較完成后第1個元素就是倒數(shù)第二小的值
    • 以此類推, 直到當(dāng)前元素沒有可比較的元素, 排序完成
  • 代碼實(shí)現(xiàn):


// 選擇排序
void selectSort(int numbers[], int length) {
    
    // 外循環(huán)為什么要-1?
    // 最后一位不用比較, 也沒有下一位和它比較, 否則會出現(xiàn)錯誤訪問
    for (int i = 0; i < length; i++) {
        for (int j = i; j < length - 1; j++) {
            // 1.用當(dāng)前元素和后續(xù)所有元素比較
            if (numbers[i] < numbers[j + 1]) {
                //  2.一旦發(fā)現(xiàn)小于就交換位置
                swapEle(numbers, i, j + 1);
            }
        }
    }
}
// 交換兩個元素的值, i/j需要交換的索引
void swapEle(int array[], int i, int j) {
    int temp = array[i];
    array[i] = array[j];
    array[j] = temp;
}

冒泡排序

  • 冒泡排序(Bubble Sort)是一種簡單的排序算法店展。它重復(fù) 地走訪過要排序的數(shù)列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數(shù)列的工作是重復(fù)地進(jìn)行直到?jīng)]有再需要交換,也就是說該數(shù)列已經(jīng)排序完成秃流。這個算法的名字由來是因?yàn)樵叫〉脑貢?jīng)由交換慢慢“浮”到數(shù)列的頂端赂蕴。


  • 排序思路:
    • 假設(shè)按照升序排序
    • 1.從第0個元素開始, 每次都用相鄰兩個元素進(jìn)行比較
    • 2.一旦發(fā)現(xiàn)后面一個元素小于前面一個元素就交換位置
    • 3.經(jīng)過一輪比較之后最后一個元素就是最大值
    • 4.排除最后一個元素, 以此類推, 每次比較完成之后最大值都會出現(xiàn)再被比較所有元素的最后
    • 直到當(dāng)前元素沒有可比較的元素, 排序完成
  • 代碼實(shí)現(xiàn):
// 冒泡排序
void bubbleSort(int numbers[], int length) {
    for (int i = 0; i < length; i++) {
        // -1防止`角標(biāo)越界`: 訪問到了不屬于自己的索引
        for (int j = 0; j < length - i - 1; j++) {
           //  1.用當(dāng)前元素和相鄰元素比較
            if (numbers[j] < numbers[j + 1]) {
                //  2.一旦發(fā)現(xiàn)小于就交換位置
                swapEle(numbers, j, j + 1);
            }
        }
    }
}
// 交換兩個元素的值, i/j需要交換的索引
void swapEle(int array[], int i, int j) {
    int temp = array[i];
    array[i] = array[j];
    array[j] = temp;
}

插入排序

  • 插入排序(Insertion-Sort)的算法描述是一種簡單直觀的排序算法。它的工作原理是通過構(gòu)建有序序列剔应,對于未排序數(shù)據(jù)睡腿,在已排序序列中從后向前掃描,找到相應(yīng)位置并插入峻贮。


  • 排序思路:
    • 假設(shè)按照升序排序
    • 1.從索引為1的元素開始向前比較, 一旦前面一個元素大于自己就讓前面的元素先后移動
    • 2.直到?jīng)]有可比較元素或者前面的元素小于自己的時候, 就將自己插入到當(dāng)前空出來的位置
  • 代碼實(shí)現(xiàn):
int main()
{
    // 待排序數(shù)組
    int nums[5] = {3, 1, 2, 0, 3};
    // 0.計算待排序數(shù)組長度
    int len = sizeof(nums) / sizeof(nums[0]);

    //  1.從第一個元素開始依次取出所有用于比較元素
    for (int i = 1; i < len; i++)
    {
        // 2.取出用于比較元素
        int temp = nums[i];
        int j = i;
        while(j > 0){
            // 3.判斷元素是否小于前一個元素
            if(temp < nums[j - 1]){
                // 4.讓前一個元素向后移動一位
                nums[j] = nums[j - 1];
            }else{
                break;
            }
            j--;
        }
        // 5.將元素插入到空出來的位置
        nums[j] = temp;
    }
}
int main()
{
    // 待排序數(shù)組
    int nums[5] = {3, 1, 2, 0, 3};
    // 0.計算待排序數(shù)組長度
    int len = sizeof(nums) / sizeof(nums[0]);

    //  1.從第一個元素開始依次取出所有用于比較元素
    for (int i = 1; i < len; i++)
    {
        // 2.遍歷取出前面元素進(jìn)行比較
        for(int j = i; j > 0; j--)
        {
            // 3.如果前面一個元素大于當(dāng)前元素,就交換位置
            if(nums[j-1] > nums[j]){
                int temp = nums[j];
                nums[j] = nums[j - 1];
                nums[j - 1] = temp;
            }else{
                break;
            }
        }
    }
}

希爾排序

  • 1959年Shell發(fā)明席怪,第一個突破O(n2)的排序算法,是簡單插入排序的改進(jìn)版纤控。它與插入排序的不同之處在于挂捻,它會優(yōu)先比較距離較遠(yuǎn)的元素。希爾排序又叫縮小增量排序船万。


  • 排序思路:
    • 1.希爾排序可以理解為插入排序的升級版, 先將待排序數(shù)組按照指定步長劃分為幾個小數(shù)組
    • 2.利用插入排序?qū)π?shù)組進(jìn)行排序, 然后將幾個排序的小數(shù)組重新合并為原始數(shù)組
    • 3.重復(fù)上述操作, 直到步長為1時,再利用插入排序排序即可
  • 代碼實(shí)現(xiàn):
int main()
{
    // 待排序數(shù)組
    int nums[5] = {3, 1, 2, 0, 3};
    // 0.計算待排序數(shù)組長度
    int len = sizeof(nums) / sizeof(nums[0]);

// 2.計算步長
    int gap = len / 2;
    do{
        //  1.從第一個元素開始依次取出所有用于比較元素
        for (int i = gap; i < len; i++)
        {
            // 2.遍歷取出前面元素進(jìn)行比較
            int j = i;
            while((j - gap) >= 0)
            {
                printf("%i > %i\n", nums[j - gap], nums[j]);
                // 3.如果前面一個元素大于當(dāng)前元素,就交換位置
                if(nums[j - gap] > nums[j]){
                    int temp = nums[j];
                    nums[j] = nums[j - gap];
                    nums[j - gap] = temp;
                }else{
                    break;
                }
                j--;
            }
        }
        // 每個小數(shù)組排序完成, 重新計算步長
        gap = gap / 2;
    }while(gap >= 1);
}

江哥提示:
對于初學(xué)者而言, 排序算法一次不易于學(xué)習(xí)太多, 咋們先來5個玩一玩, 后續(xù)繼續(xù)講解其它5個


折半查找

  • 基本思路
  • 在有序表中,取中間元素作為比較對象,若給定值與中間元素的要查找的數(shù)相等,則查找成功;若給定值小于中間元素的要查找的數(shù),則在中間元素的左半?yún)^(qū)繼續(xù)查找;
  • 若給定值大于中間元素的要查找的數(shù),則在中間元素的右半?yún)^(qū)繼續(xù)查找刻撒。不斷重復(fù)上述查找過 程,直到查找成功,或所查找的區(qū)域無數(shù)據(jù)元素,查找失敗

  • 實(shí)現(xiàn)步驟

  • 在有序表中,取中間元素作為比較對象,若給定值與中間元素的要查找的數(shù)相等,則查找成功;

  • 若給定值小于中間元素的要查找的數(shù),則在中間元素的左半?yún)^(qū)繼續(xù)查找;

  • 若給定值大于中間元素的要查找的數(shù),則在中間元素的右半?yún)^(qū)繼續(xù)查找。

  • 不斷重復(fù)上述查找過 程,直到查找成功,或所查找的區(qū)域無數(shù)據(jù)元素,查找失敗耿导。


  • 代碼實(shí)現(xiàn)

int findKey(int values[], int length, int key) {
    // 定義一個變量記錄最小索引
    int min = 0;
    // 定義一個變量記錄最大索引
    int max = length - 1;
    // 定義一個變量記錄中間索引
    int mid = (min + max) * 0.5;
    
    while (min <= max) {
        // 如果mid對應(yīng)的值 大于 key, 那么max要變小
        if (values[mid] > key) {
            max = mid - 1;
            // 如果mid對應(yīng)的值 小于 key, 那么min要變
        }else if (values[mid] < key) {
            min = mid + 1;
        }else {
            return mid;
        }
        // 修改完min/max之后, 重新計算mid的值
        mid = (min + max) * 0.5;
    }
    return -1;
}

進(jìn)制轉(zhuǎn)換(查表法)

  • 實(shí)現(xiàn)思路:
    • 將二進(jìn)制声怔、八進(jìn)制、十進(jìn)制舱呻、十六進(jìn)制所有可能的字符都存入數(shù)組
    • 利用按位與運(yùn)算符和右移依次取出當(dāng)前進(jìn)制對應(yīng)位置的值
    • 利用取出的值到數(shù)組中查詢當(dāng)前位輸出的結(jié)果
    • 將查詢的結(jié)果存入一個新的數(shù)組, 當(dāng)所有位都查詢存儲完畢, 新數(shù)組中的值就是對應(yīng)進(jìn)制的值
  • 代碼實(shí)現(xiàn)
#include <stdio.h>
void toBinary(int num)
{
    total(num, 1, 1);
}
void toOct(int num)
{
    total(num, 7, 3);
}
void toHex(int num)
{
    total(num, 15, 4);
}

void total(int num , int base, int offset)
{
    //    1.定義表用于查詢結(jié)果
    char cs[] = {
        '0', '1', '2', '3', '4', '5',
        '6', '7', '8', '9', 'a', 'b',
        'c', 'd', 'e', 'f'
    };
    //    2.定義保存結(jié)果的數(shù)組
    char rs[32];
    //    計算最大的角標(biāo)位置
    int length = sizeof(rs)/sizeof(char);
    int pos = length;//8

    while (num != 0) {
        int index = num & base;
        rs[--pos] = cs[index];
        num = num >> offset;
    }

    for (int i = pos; i < length; i++) {
        printf("%c", rs[i]);
    }
    printf("\n");
}
int main()
{
    toBinary(9);
    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末醋火,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子箱吕,更是在濱河造成了極大的恐慌芥驳,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茬高,死亡現(xiàn)場離奇詭異兆旬,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)怎栽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門丽猬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宿饱,“玉大人,你說我怎么就攤上這事宝鼓⌒炭茫” “怎么了巴刻?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵愚铡,是天一觀的道長。 經(jīng)常有香客問我胡陪,道長沥寥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任柠座,我火速辦了婚禮邑雅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘妈经。我一直安慰自己淮野,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布吹泡。 她就那樣靜靜地躺著骤星,像睡著了一般。 火紅的嫁衣襯著肌膚如雪爆哑。 梳的紋絲不亂的頭發(fā)上洞难,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機(jī)與錄音揭朝,去河邊找鬼队贱。 笑死,一個胖子當(dāng)著我的面吹牛潭袱,可吹牛的內(nèi)容都是我干的柱嫌。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼屯换,長吁一口氣:“原來是場噩夢啊……” “哼编丘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起趟径,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤瘪吏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蜗巧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掌眠,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年幕屹,在試婚紗的時候發(fā)現(xiàn)自己被綠了蓝丙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片级遭。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖渺尘,靈堂內(nèi)的尸體忽然破棺而出挫鸽,到底是詐尸還是另有隱情,我是刑警寧澤鸥跟,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布丢郊,位于F島的核電站,受9級特大地震影響医咨,放射性物質(zhì)發(fā)生泄漏枫匾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一拟淮、第九天 我趴在偏房一處隱蔽的房頂上張望干茉。 院中可真熱鬧,春花似錦很泊、人聲如沸角虫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽戳鹅。三九已至,卻和暖如春争涌,著一層夾襖步出監(jiān)牢的瞬間粉楚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工亮垫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留模软,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓饮潦,卻偏偏與公主長得像燃异,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子继蜡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

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

  • 原文地址:http://theory.stanford.edu/~amitp/GameProgramming/ 1...
    達(dá)微閱讀 19,395評論 0 28
  • 一些概念 數(shù)據(jù)結(jié)構(gòu)就是研究數(shù)據(jù)的邏輯結(jié)構(gòu)和物理結(jié)構(gòu)以及它們之間相互關(guān)系回俐,并對這種結(jié)構(gòu)定義相應(yīng)的運(yùn)算,而且確保經(jīng)過這...
    Winterfell_Z閱讀 5,654評論 0 13
  • 當(dāng)冰雪消融春回大地,當(dāng)春風(fēng)拂面百花待放碘举,每個人的心里也都涌起了新一輪的沖動和期望忘瓦。 新的一年,要有新的氣象引颈,有新的...
    鑫雨親子講師閱讀 540評論 0 2
  • 今年的九月份耕皮,我迎來了我的大學(xué)生活境蜕! 可當(dāng)我來到了學(xué)校之后,我才發(fā)現(xiàn)跟我想象中的大學(xué)完全不一樣凌停,不論是環(huán)境粱年,學(xué)習(xí),...
    小佳大家閱讀 268評論 2 1
  • 場景: 科大訊飛近日在北京召開翻譯戰(zhàn)略及新品發(fā)布會,會上發(fā)布訊飛翻譯機(jī)二代產(chǎn)品舟舒,并定義A.I.翻譯的四大標(biāo)準(zhǔn):聽得...
    小草出閱讀 186評論 0 0