【C语言】深入解析插入排序

news/2024/8/30 20:40:18 标签: c语言, 排序算法, 算法

文章目录

        • 什么是插入排序?
        • 插入排序的基本实现
        • 代码解释
        • 插入排序的优化
        • 插入排序的性能分析
        • 插入排序的实际应用
        • 结论

在这里插入图片描述

在C语言编程中,插入排序是一种简单且高效的算法>排序算法,尤其在处理小型数据集时表现出色。插入排序通过构建有序序列,对于未排序的数据,在已排序序列中从后向前扫描,找到相应位置并插入。本文将详细介绍插入算法>排序算法,包括其定义、实现、优化方法和性能分析,帮助读者深入理解这一经典算法

什么是插入排序?

插入排序(Insertion Sort)是一种基于比较的算法>排序算法。它的基本思想是将元素逐个插入到已排序的部分中,使整个序列保持有序。插入排序在处理小数据集或几乎已经有序的数据集时,效率较高。

插入排序的基本实现

以下是插入排序的基本实现代码:

#include <stdio.h>

// 插入排序函数
void insertionSort(int arr[], int n) {
    int i, key, j;
    for (i = 1; i < n; i++) {
        key = arr[i];
        j = i - 1;

        // 将arr[i]插入到已排序部分
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j = j - 1;
        }
        arr[j + 1] = key;
    }
}

// 打印数组函数
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++)
        printf("%d ", arr[i]);
    printf("\n");
}

// 主函数
int main() {
    int arr[] = {12, 11, 13, 5, 6};
    int n = sizeof(arr) / sizeof(arr[0]);

    printf("未排序的数组: \n");
    printArray(arr, n);

    insertionSort(arr, n);
    printf("排序后的数组: \n");
    printArray(arr, n);

    return 0;
}
代码解释
  1. 插入排序函数insertionSort

    • 使用两个嵌套的循环遍历数组。
    • 外层循环从数组的第二个元素开始,将当前元素作为key
    • 内层循环从已排序部分的末尾开始,将key插入到已排序部分的正确位置。
  2. 打印数组函数printArray

    • 遍历数组并打印每个元素,便于查看排序结果。
  3. 主函数main

    • 初始化一个整数数组并计算其大小。
    • 调用insertionSort函数对数组进行排序。
    • 打印排序前后的数组。
插入排序的优化

虽然插入排序在处理小型数据集时表现良好,但可以通过一些优化方法进一步提高其性能:

  1. 减少交换操作

    • 在内层循环中,使用赋值操作代替交换操作可以减少不必要的开销。

    优化代码示例:

    void insertionSort(int arr[], int n) {
        int i, key, j;
        for (i = 1; i < n; i++) {
            key = arr[i];
            j = i - 1;
    
            // 使用赋值操作代替交换操作
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j = j - 1;
            }
            arr[j + 1] = key;
        }
    }
    
  2. 二分查找优化

    • 在内层循环中使用二分查找来找到插入位置,从而减少比较次数。

    优化代码示例:

    int binarySearch(int arr[], int item, int low, int high) {
        if (high <= low)
            return (item > arr[low]) ? (low + 1) : low;
    
        int mid = (low + high) / 2;
    
        if (item == arr[mid])
            return mid + 1;
    
        if (item > arr[mid])
            return binarySearch(arr, item, mid + 1, high);
        return binarySearch(arr, item, low, mid - 1);
    }
    
    void insertionSort(int arr[], int n) {
        int i, key, j, loc;
        for (i = 1; i < n; i++) {
            key = arr[i];
            j = i - 1;
    
            // 使用二分查找找到插入位置
            loc = binarySearch(arr, key, 0, j);
    
            // 移动元素以腾出插入位置
            while (j >= loc) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[loc] = key;
        }
    }
    
插入排序的性能分析

插入排序的时间复杂度在最坏情况下为 O ( n 2 ) O(n^2) O(n2),这是因为每次插入都需要比较和移动多个元素。然而,在最好情况下(当数组已经有序时),时间复杂度为 O ( n ) O(n) O(n)。因此,插入排序在处理几乎有序的数据时效率较高。

插入排序的空间复杂度为 O ( 1 ) O(1) O(1),因为它只需要常数级别的额外空间来存储临时变量。插入排序是一个稳定的算法>排序算法,因为相同元素的相对位置不会改变。

插入排序的实际应用

插入排序由于其简单性和高效性,在以下几种情况下非常有用:

  1. 小型数据集

    • 在处理小型数据集时,插入排序的性能足够,而且实现简单。
  2. 几乎有序的数据

    • 插入排序在处理几乎有序的数据时效率非常高,因为它可以利用数据的已有序性。
  3. 在线算法

    • 插入排序可以用于在线算法(即数据逐步到达时进行排序),因为它每次只处理一个新的元素。
结论

插入排序是C语言中一种简单且高效的算法>排序算法,其实现简单且易于理解。通过一些优化方法,可以进一步提高插入排序的性能。在学习和使用插入排序时,了解其优缺点以及适用场景,能够帮助我们更好地选择和使用算法>排序算法。希望本文能帮助读者深入理解插入排序,并在实际编程中灵活应用。


http://www.niftyadmin.cn/n/5561036.html

相关文章

postgresql删除用户

背景 **角色与用户**&#xff1a;在 PostgreSQL 中&#xff0c;用户和组的概念是通过“角色”来统一实现的。角色可以有登录权限&#xff08;在这种情况下&#xff0c;它们通常被称为“用户”&#xff09;&#xff0c;也可以没有&#xff08;在这种情况下&#xff0c;它们通常用…

HTML2048小游戏

源代码在效果图后面 效果图 源代码 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>2048 Game&l…

STM32使用CubeMX创建HAL库工程文件

文章目录 1. STM32CubeMX 2. 界面介绍 3. 使用教程 新建工程 选择芯片界面 ​编辑 配置页面 引脚配置页面 引脚配置界面的颜色指示 配置RCC时钟参数 配置SYS参数 配置时钟树 Project Manager项目管理配置 生成工程文件 KEIL代码编写 1. STM32CubeMX STM32CubeM…

【JavaScript 算法】树的遍历:前序、中序与后序

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、前序遍历&#xff08;Preorder Traversal&#xff09;前序遍历的步骤前序遍历的JavaScript实现 二、中序遍历&#xff08;Inorder Traversal&#xff09;中序遍历的步骤中序遍历的JavaScript实现 三、后序遍历&#xff…

【时时三省】单元测试 简介

目录 1,单元测试简介 2,单元测试的目的 3,单元测试检查范围 4,单元测试用例设计方法 5,单元测试判断通过标准 6,测试范围 7,测试频率 8,输出成果 经验建议: 山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 1,单元测试简介 单元测试在以V模型…

时间轮算法理解、Kafka实现

概述 TimingWheel&#xff0c;时间轮&#xff0c;简单理解就是一种用来存储若干个定时任务的环状队列&#xff08;或数组&#xff09;&#xff0c;工作原理和钟表的表盘类似。 关于环形队列&#xff0c;请参考环形队列。 时间轮由两个部分组成&#xff0c;一个环状数组&…

电脑系统重装数据被格式化,那些文件还有办法恢复吗?

在日常使用电脑的过程中&#xff0c;系统重装或格式化操作是常见的维护手段&#xff0c;尤其是在遇到系统崩溃、病毒感染或需要升级系统时。然而&#xff0c;这一操作往往伴随着数据丢失的风险&#xff0c;尤其是当C盘&#xff08;系统盘&#xff09;和D盘&#xff08;或其他数…

Linux C++ realpath函数crash的解决方法

现象 调用realpath函数进程崩溃&#xff0c;可使用如下代码复现&#xff1a; //test.cpp #include "stdio.h" #include "stdlib.h" #include <limits.h>int main() {char *pnew char[300];realpath("1.txt",p);printf("%s\n",…