C語言學習周總結003(選擇排序、冒泡排序、二分查找)


1.選擇排序

選擇排序法(Selection Sort) 是對數組進行排序常用的一種簡單直觀的方法。
該方法通過多次循環,每次從待排序的元素中選出最小(或最大)的一個元素,存放在數組的起始位置,然后再從剩余的未排序元素中尋找到最小(大)元素,然后放到已排序的序列的末尾。從而實現將一個數組內的所有元素按大小升序或降序排序

如圖所示:

 

 

 

話不多說,先上例題:

假設有一組待排序的數組a
該數組包含這些元素:2, 45, 6, 12, 87, 34, 103, 53, 25
現對其使用選擇排序法進行升序排序

 

 

 代碼分析:

首先定義數組以及數組長度變量len
通過for循環
讓循環控制變量i從數組的最后一項(len-1)開始
使用自定義的max函數返回數組a從0到第i項中最大值的下標。
得到最大值下標后,把該最大值放到此時數組的末尾,也就是第len-1項
下一次循環,i變成len-2,再得到從0到第i項中最大值的下標,再次將其放到第i項,也就是數組的倒數第二項。
依次循環下去,直到i等於1,循環結束
排序完成,最后遍歷輸出。

代碼:

#include <stdio.h>

int max(int a[], int n);

int main()
{
    int a[] = { 2, 45, 6, 12, 87, 34, 103, 53, 25 };
    int len = sizeof(a) / sizeof(int);

     // 選擇排序
    for (int i = len - 1; i > 0; i--)
    {
        int maxid = max(a, i + 1);
        int t = a[maxid];
        a[maxid] = a[i];
        a[i] = t;
    }



    // 遍歷輸出
    for (int i = 0; i < len; i++)
        printf("%d ", a[i]);
    printf("\n\n\n");


    return 0;
}

int max(int a[], int n)  // 返回數組a中最大值的下標; n表示該數組的長度
{
    int max = 0;
    for (int i = 0; i < n; i++) {
        if (a[i] > a[max])
            max = i;
    }
    return max;

}

 

運行結果:

程序運行成功。

 

2.冒泡排序

冒泡排序(Bubble Sort)也是對數組進行排序常用的方法,它通過多次循環,每次都從頭到尾比較相鄰兩項的大小並進行位置調換來完成排序,也就是說,它要重復地遍歷整個數組, 直到數組的每個元素都排序完畢。

如圖所示:

 

 

 

 

同樣還是上面的例題:

假設有一組待排序的數組a
該數組包含這些元素:2, 45, 6, 12, 87, 34, 103, 53, 25
現對其使用冒泡排序進行升序排序

代碼分析:

先定義數組和數組的長度變量len,數組長度可以通過 (整個數組所占字節大小)/(單個元素所占字節大小) 來得到;

接着進入排序,使用兩層嵌套循環,第一層的控制變量i表示遍歷數組的次數,完成整個冒泡排序過程需要[數組長度-1]次,所以我們讓它從1開始直至len-1;

第二層的控制變量 j 表示遍歷到數組的第幾個元素,j 從0開始直至len-2,比如當 j = 0時,比較第0項和第1項的大小,若后一項小於前一項,則交換它們的位置;

上述嵌套循環完成后,數組也就完成了排序。

代碼:

#include <stdio.h>


int main()
{
    int a[] = { 2, 45, 6, 12, 87, 34, 103, 53, 25 };
    int len = sizeof(a) / sizeof(int);


    // 冒泡排序
    for (int i = 1; i < len; i++) {
        for (int j = 0; j < len-1; j++) {
            if (a[j + 1] < a[j]) {
                int t = a[j + 1];
                a[j + 1] = a[j];
                a[j] = t;
            }
        }
    }


    // 遍歷輸出
    for (int i = 0; i < len; i++)
        printf("%d ", a[i]);
    printf("\n\n\n");


    return 0;
}

 

運行結果與選擇排序法相同。

 

3.二分查找

問題引入:

現有上述按升序排序完的數組: 2, 6, 12, 25, 34, 45, 53, 87, 103;

要求定義一個函數,該函數可以返回某個指定整數(假設為34)在該數組中的下標。

代碼分析:

定義三個記號left(左)、mid(中)、right(右),初始位置左記號在數組第0項,右記號在最后一項;

使用while循環,每次循環比較中記號所表示項與指定整數的大小關系,以判斷是否進一步縮小范圍或返回結果;

若范圍縮小到左記號跑到右記號的右邊還沒找到指定整數,則結束循環,返回-1.

 代碼:

int search(int a[], int n, int x)  // 傳入參數:待查找數組a,數組長度n,查找指定整數x
{
    int index = -1;  // 返回值初始化為-1,若未找到指定整數則返回-1


    // 二分查找法
    int left, right, mid;  // 定義左中右三個下標記號
    left = 0;    // 左記號初始位置為第0項
    right = n - 1;    // 右記號初始位置為最后一項
    while (left < right) {         // 當左記號不在右記號的左邊時,查找過程結束,未找到指定整數,結束循環
        mid = (left + right) / 2;
        if (a[mid] == x) {    // 找到指定整數,將該下標傳遞給返回值index,並結束循環
            index = mid;
            break;
        }
        else if (a[mid] < x) {    // 若中記號所表示的項 小於 指定整數,則表明此時數組左半部分的所有項均小於指定整數
            left = mid + 1;    // 這時將左記號移至此時中記號的右一位,也就是將查找范圍縮小到此時數組的右半部分
        }
        else {    // 反之則移動右記號,將范圍縮小到左半部分
            right = mid - 1;
        }
    }

    return index;
}

運行結果:

在主函數中成功正確輸出指定整數下標:4

總結:

二分查找法相較於一般的遍歷查找法 循環次數更少,程序運行效率更高,不過待查找的數組一定得是有序的數組才可使用該方法。



END:)

注:1 2算法示意動圖引用自菜鳥教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM