20201022-成信大-C语言程序设计-补充内容-三种常见排序算法,顺序和折半搜索的比较

知识点导读

  • 冒泡排序
  • 插入排序
  • 选择排序
  • 顺序搜索
  • 折半搜索

具体示例

#include <stdio.h>

#define N 10
/* 
    打印数组
 */
void printArr(int *arr, int n)
{
    
    
    int i;
    for (i = 0; i < n; i++)
    {
    
    
        printf("%d ", arr[i]);
    }
    printf("\n");
}
/* 
    交换实参
 */
void swap(int *a, int *b)
{
    
    
    int tmp;
    tmp = *a;
    *a = *b;
    *b = tmp;
}
/* 
    冒泡排序
        1. 一次把数据给足
        2. 两两比较,相邻交换,直接交换数据
 */
void bubbleSort(int *a, int n)
{
    
    
    int i, j;
    printf("===bubbleSort===\n");
    printArr(a, n);
    printf("---------------------\n");
    for (i = 0; i < n - 1; i++) // 前n-1个冒泡,最后一个自动归位
    {
    
    
        for (j = 0; j < n - 1 - i; j++) // 一轮一个归位,最后一个不用再归位
        {
    
    
            if (a[j] > a[j + 1]) // 相邻比较,两两交换
            {
    
    
                swap(&a[j], &a[j + 1]);
            }
        }
        printArr(a, N);
    }
}
/* 
    插入排序,左边有序,右边待入序
        1. 象摸牌,一张一张地,摸一张,插到适当的位置,手里的牌总是有序的
        2. 在输入过程中就可以完成插入时有序
        3. 比较序列,从后往前比【升序时】
        4. 比较,让位,再入位
 */
void insertSort(int *arr, int n)
{
    
    
    int i, j;
    int tmp;
    printf("===insertSort===\n");
    printArr(arr, n);
    printf("---------------------\n");
    for (i = 1; i < n; i++) // 首个即为左数列,自动有序,即a[0]已经有序
    {
    
    
        j = i;                            // 从第a[1]个开始,逐个检查并插入到相应位置【末位或是中简某位置】
        tmp = arr[j];                     // 因为可能腾位置,先记录之
        while (j > 0 && tmp < arr[j - 1]) // 找位置,找的过程中,可能需要移动腾位置
        {
    
    
            arr[j] = arr[j - 1]; // 逐个后移【右移】
            j--;                 // 记位置
        }
        arr[j] = tmp; // 插入到相应的位置上
        printArr(arr, N);
    }
}
/* 
    选择排序
        1. 先选择,再入位,与插入相似,但插入是按序选,这里是专门选最大或是最小
        2. 要读入全部数据,才可以做选择
        3. 比较,定位,再交换入位
        4. 象发牌,一把牌拿在手里,然后:直接抽出最大的或是最小的来将牌变得有序,从左到右放置
 */
void selectSort(int *arr, int n)
{
    
    
    int i, j;
    int tmp; // 哨兵数据
    printf("===selectSort===\n");
    printArr(arr, n);
    printf("---------------------\n");
    for (i = 0; i < n; i++) // 首个即为左数列,自动有序,即a[0]已经有序
    {
    
    
        // 打擂法找未排序里的最小的,或是最大的,用哨兵去记它
        tmp = i;
        for (j = i; j < n; j++) // 一个个排坐次,选一个坐一个【梁山好汉坐次表】
        {
    
    
            if (arr[tmp] > arr[j])
            {
    
    
                tmp = j;
            }
        }
        if (tmp != i) // 如果有新擂主产生,则交换
        {
    
    
            swap(&arr[i], &arr[tmp]);
        }
        printArr(arr, N);
    }
}

/* 
    顺序查找
 */
int findDataInArr(int *arr, int n, int key)
{
    
    
    int i;
    int result = 0;
    for (i = 0; i < n; i++)
    {
    
    
        if (key == arr[i])
        {
    
    
            result = 1;
            break;
        }
    }
    return result;
}

/* 
    折半查找,即二分查找
 */
int binarySearch(int a[], int n, int key)
{
    
    
    int low, high; // 首位,尾位
    int mid;       // 折半位
    int count = 0; // 记录和分析次数

    int result = 0; // 查找结果

    low = 0;
    high = n - 1;

    while (low < high) //査找范围不为0时执行循环体语句【即首尾未相遇】
    {
    
    
        count++;                //count记录査找次数
        mid = (low + high) / 2; //求中间位置
        if (key < a[mid])       // key小于中间值时,压缩查找空间
            high = mid - 1;
        else if (key > a[mid]) // key大于中间值时,压缩查找空间
            low = mid + 1;
        else if (key == a[mid]) //当key等于中间值时,证明查找成功
        {
    
    
            // printf("查找成功!\n 查找 %d 次!a[%d]=%d", count, mid, key); //输出査找次数及所査找元素在数组中的位置
            result = 1; // 标记找到了
            break;
        }
    }

    return result;
}

/* 
    测试和演示
 */
int main(int argc, char const *argv[])
{
    
    
    int arrA[N] = {
    
    11, 9, 3, 2, 4, 6, 1, 5, 8, 7};
    int arrB[N] = {
    
    11, 9, 3, 2, 4, 6, 1, 5, 8, 7};
    int arrC[N] = {
    
    11, 9, 3, 2, 4, 6, 1, 5, 8, 7};
    int arrD[N] = {
    
    11, 9, 3, 2, 4, 6, 1, 5, 8, 7};
    int fd = 23;

    bubbleSort(arrA, N);
    insertSort(arrB, N);
    selectSort(arrC, N);

    if (findDataInArr(arrD, 10, fd))
    {
    
    
        printf("find data\n");
    }
    else
    {
    
    
        printf("not find data\n");
    }

    if (binarySearch(arrA, 10, fd))
    {
    
    
        printf("find data\n");
    }
    else
    {
    
    
        printf("not find data\n");
    }

    return 0;
}

知识点摘要

  • 冒泡排序 邻位交换
  • 选择排序 定位交换
  • 插入排序 移位交换
  • 顺序查找 暴力一个个比较即可
  • 折半查找【在排序的基础上进行】一次压缩一半的解空间

冒泡排序,邻位比较再交换

    1. 一次把数据给足
    2. 两两比较,相邻交换,直接交换数据

插入排序,左边有序,右边待入序,移位腾出再入位

    1. 象摸牌,一张一张地,摸一张,插到适当的位置,手里的牌总是有序的
    2. 在输入过程中就可以完成插入时有序
    3. 比较序列,从后往前比【升序时】
    4. 比较,让位,再入位

选择排序,打擂等算法选出再交换

    1. 先选择,再入位,与插入相似,但插入是按序选,这里是专门选最大或是最小
    2. 要读入全部数据,才可以做选择
    3. 比较,定位,再交换入位
    4. 象发牌,一把牌拿在手里,然后:直接抽出最大的或是最小的来将牌变得有序,从左到右放置

顺序查找

    1. 暴力穷举,依次按序逐个比较
    2. 可以从头到尾,找到为止,或找不到为终
    3. 可以重复找多个

折半查找,即二分查找

    1. 前提:数据有序,再每次减半
    2. 跳着找,效率高,速度快,很快出结果:找到了,或没有找到
    3. 一般要求键值唯一

猜你喜欢

转载自blog.csdn.net/matrixbbs/article/details/111208527