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