【数据结构】插入排序:直接插入排序、折半插入排序、希尔排序的学习知识总结

news2024/12/28 19:40:17

目录

1、排序的基本概念

2、直接插入排序

2.1 算法思想 

2.2 代码实现 

3、折半插入排序

3.1 算法思想

3.2 代码实现 

4、希尔排序

4.1 算法思想

4..2 代码实现 


1、排序的基本概念

排序是将一组数据按照预定的顺序排列的过程,排序的基本概念包括以下内容:

  1. 关键字:排序时按照哪个字段进行排序,该字段称为关键字。

  2. 排序规则:排序时按照升序或降序的方式排列。升序表示从小到大排列,降序表示从大到小排列。

  3. 稳定性:排序算法如果经过排序后,具有相同关键字的元素,排序前后的相对顺序是否保持不变。如果保持不变,该排序算法就是稳定的。

  4. 时间复杂度:排序算法进行排序所需要的时间复杂度。

  5. 空间复杂度:排序算法进行排序所需要的额外空间复杂度,即算法需要占用的额外内存大小。

2、直接插入排序

2.1 算法思想 

        直接插入排序算法的思想是将待排序的元素插入到已经排好序的元素序列中,从而得到一个新的、更大的有序序列。

        具体来说,算法从第二个元素开始遍历待排序序列,将当前元素插入到已经排好的元素序列中的正确位置上,使得插入后仍然保持有序。因为初始时已经有一个元素的有序序列,所以排序过程中每次插入的元素都将比已经排好序的元素序列中的元素小,因此不会影响已经排好序的元素序列的有序性。当遍历完整个序列,待排序序列就被完全插入到已经排好序的元素序列中,排序完成。

        直接插入排序的时间复杂度为O(n^2),空间复杂度为O(1)。虽然时间复杂度较高,但是对于小规模数据的排序效率较高,并且具有稳定性。

2.2 代码实现 

以下是C语言编写的直接插入排序并计数比较次数的程序:

#include <stdio.h>
#define MAXSIZE 100

void InsertionSort(int A[], int n, int *cnt) {
    int i, j, temp;
    for(i = 1; i < n; i++) {
        temp = A[i];
        for(j = i - 1; j >= 0; j--) {
            (*cnt)++;
            if(A[j] > temp)
                A[j + 1] = A[j];
            else
                break;
        }
        A[j + 1] = temp;
    }
}

int main() {
    int A[MAXSIZE];
    int n, cnt = 0;
    printf("请输入待排序数列元素个数(不超过%d):", MAXSIZE);
    scanf("%d", &n);
    printf("请输入待排序数列:");
    for(int i = 0; i < n; i++)
        scanf("%d", &A[i]);
    InsertionSort(A, n, &cnt);
    printf("排序后结果:");
    for(int i = 0; i < n; i++)
        printf("%d ", A[i]);
    printf("\n比较次数:%d\n", cnt);
    return 0;
}

        程序中的 InsertionSort 函数实现了直接插入排序,并使用指针形参 cnt 对比较次数进行计数。主函数中首先输入待排序数列元素个数和数列元素,然后调用 InsertionSort 函数进行排序,并输出排序后的结果和比较次数。

下面是C语言在链式存储结构上设计直接插入排序算法的示例代码:

typedef struct Node {
    int data;
    struct Node *next;
}Node;

void insertSort(Node **head) {
    if (*head == NULL || (*head)->next == NULL) {
        return;
    }
    Node *p = (*head)->next;
    (*head)->next = NULL; // 设置新的有序链表头节点
    while (p != NULL) {
        Node *q = p->next;
        Node *prev = NULL;
        Node *cur = *head;
        while (cur != NULL && cur->data < p->data) {
            prev = cur;
            cur = cur->next;
        }
        if (prev == NULL) { // 插入到头节点之前
            p->next = *head;
            *head = p;
        } else { // 插入到prev和cur之间
            prev->next = p;
            p->next = cur;
        }
        p = q;
    }
}

        此代码首先对链表的头节点进行判断,若链表为空或只有一个节点则不需要排序。然后指针p指向头节点的后继节点,将头节点的后继节点设为空,新的有序链表头节点为原链表的头节点。接下来,对p的每个节点进行插入排序操作,找到p应该插入的位置并插入。最后返回排好序的链表头节点。

3、折半插入排序

3.1 算法思想

        折半插入排序算法是插入排序算法的一种变种。它的基本思想是将待排序的序列分成两部分,前半部分为已排序好的部分,后半部分为未排序的部分。排序过程中,每次从未排序的部分中选出一个元素,通过折半查找的方式,找到它应该插入到已排序的部分中的哪个位置,然后再将的元素插入到已排序的部分中。

具体实现步骤如下:

1. 将待排序序列的第一个元素作为已排序的部分,剩下的元素作为未排序的部分。

2. 从未排序的部分中选出一个元素,通过二分查找找到它应该插入到已排序的部分中的位置。

3. 将该元素插入到已排序的部分中,同时将已排序的部分的长度增加1,未排序的部分的长度减少1。

4. 重复步骤2和步骤3,直到未排序的部分为空。

        折半插入排序算法相比于普通的插入排序算法,虽然查找的时间复杂度由O(n)降低为O(log n),但是这并不影响算法的总体时间复杂度,依然是O(n^2)。不过,在某些特定的场景下,折半插入排序算法的效率可能会比普通的插入排序算法更高。

3.2 代码实现 

        折半插入排序是插入排序的一种优化算法,它利用二分查找的思想来确定插入位置,从而减少比较和移动的次数,提高排序效率。

下面是C语言实现折半插入排序的示例代码:

void binary_insertion_sort(int arr[], int len) {
    int i, j, left, right, mid, tmp;
    for (i = 1; i < len; i++) {
        tmp = arr[i];
        left = 0;
        right = i - 1;
        // 找到插入位置
        while (left <= right) {
            mid = (left + right) / 2;
            if (tmp < arr[mid]) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        // 移动元素
        for (j = i - 1; j >= left; j--) {
            arr[j + 1] = arr[j];
        }
        // 插入元素
        arr[left] = tmp;
    }
}

        该算法的时间复杂度为O(nlogn),空间复杂度为O(1)。

4、希尔排序

4.1 算法思想

        希尔排序算法是插入排序的一种改进算法,也称为缩小增量排序。希尔排序的基本思想是将待排序序列分割成若干个子序列,对每个子序列进行插入排序,然后不断减小步长,直到步长为1,完成排序。

        具体实现时,先确定一个增量,在每个增量下将序列分成若干个小组,对每个小组进行插入排序。然后逐渐减小增量,重复上述操作,直到增量减小为1,再进行一次插入排序。不同的增量序列会影响希尔排序的效率,一般采用Hibbard增量序列或Sedgewick增量序列来提高排序效率。

        希尔排序算法时间复杂度为O(nlogn)到O(n^2)之间,取决于增量序列的选择。在一般情况下,希尔排序具有较好的排序效率和稳定性,特别适用于数据量较大、无序性较强的序列。

4..2 代码实现 

下面是C语言实现希尔排序的代码:

void shell_sort(int arr[], int len)
{
    int gap, i, j, temp;
    for (gap = len / 2; gap > 0; gap /= 2) {  // gap为步长,每次减半直到为1
        for (i = gap; i < len; i++) {
            temp = arr[i];
            for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
                arr[j + gap] = arr[j];  // 向后移动gap位
            }
            arr[j + gap] = temp;  // 插入到正确位置
        }
    }
}

        该代码首先将整个待排序序列分成若干个子序列,按照步长进行插入排序。然后逐渐缩小步长,直至为1,最后进行一次普通的插入排序,完成整个排序过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1044151.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自学WEB后端01-安装Express+Node.js框架完成Hello World!

一、前言&#xff0c;网站开发扫盲知识 1.网站搭建开发包括什么&#xff1f; 前端 前端开发主要涉及用户界面&#xff08;UI&#xff09;和用户体验&#xff08;UX&#xff09;&#xff0c;负责实现网站的外观和交互逻辑。前端开发使用HTML、CSS和JavaScript等技术来构建网页…

数据结构--快速排序

文章目录 快速排序的概念Hoare版本挖坑法前后指针法快速排序的优化三数取中法小区间用插入排序 非递归的快速排序 快速排序的概念 快速排序是通过二叉树的思想&#xff0c;先设定一个值&#xff0c;通过比较&#xff0c;比它大的放在它的右边&#xff0c;比它小的放在它的左边…

Python中的数据常见问题

数据可视化在Python中是一个非常重要的主题&#xff0c;它可以帮助我们更好地理解和分析数据。无论是探索数据的特征&#xff0c;还是向其他人展示数据的结果&#xff0c;数据可视化都起到了关键作用。然而&#xff0c;在进行数据可视化时可能会遇到一些常见问题。本文将为您分…

基于微信小程序的同城家政服务预约系统(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

DC电源模块关于宽电压输入和输出的范围

BOSHIDA DC电源模块关于宽电压输入和输出的范围 DC电源模块是一种电子设备&#xff0c;能够将输入的直流电源转换成所需的输出电源&#xff0c;用于供电各种电子设备。其中&#xff0c;关于宽电压输入和输出的范围&#xff0c;是DC电源模块常见的设计要求之一。本文将详细介绍…

嵌入式Linux应用开发-基础知识及GCC 编译器的使用

嵌入式Linux应用开发-基础知识及GCC 编译器的使用 第一章 HelloWorld 背后没那么简单1.1 交叉编译 hello.c1.2 请回答这几个问题1.3 演示 (...) 第二章 GCC 编译器的使用2.1 配套视频内容大纲2.1.1 GCC 编译过程(精简版)2.1.2 常用编译选项2.1.3 怎么编译多个文件2.1.4 制作、使…

深度学习:模型训练过程中Trying to backward through the graph a second time解决方案

1 问题描述 在训练lstm网络过程中出现如下错误&#xff1a; Traceback (most recent call last):File "D:\code\lstm_emotion_analyse\text_analyse.py", line 82, in <module>loss.backward()File "C:\Users\lishu\anaconda3\envs\pt2\lib\site-packag…

【Unity】LODGroup 计算公式

Unity 在配置 LodGroup 时&#xff0c;其分级切换的计算方法是按照物体在相机视野中占据的比例计算的。在运行时&#xff0c;如果相机视野范围&#xff08;Field of View&#xff09;没有改变&#xff0c;那么这个值可以直接换算成物体距离相机的距离。这里就讨论下如何计算得到…

ubuntu下用pycharm专业版连接AI服务器及其docker环境

一&#xff1a;用pycharm专业版连接AI服务器 1、首先在自己电脑上新建一个文件夹&#xff0c;后续用于映射服务器上自己所要用的项目文件 2、用pycharm专业版打开该文件夹&#xff0c;作为一个项目打开 3、然后在工具->部署->配置 4、配置中形式如下&#xff1a; 点击左…

Chatbot UI集成LocalAI实现自托管的ChatGPT

本文比惯例提前了一天发&#xff0c;因为明天一早&#xff0c;老苏就踏上回乡的路了&#xff0c;三年没回老家&#xff0c;这次专门请了 2 天的假 难得回家&#xff0c;打算多陪陪家人&#xff0c;和多年不见的朋友聚聚&#xff0c;当然如果有网络条件&#xff0c;还是会正常发…

英语单词记忆学习打卡系统 微信小程序

本单词记忆系统使用了计算机语言Java和存放数据的仓库MySQL&#xff0c;采用了微信小程序模式来实现。本系统使用了框架SSM和Uni-weixin实现了单词记忆系统应有的功能&#xff0c;系统主要角色包括管理员和用户。 关键词&#xff1a;Java&#xff1b;MySQL&#xff1b;SSM  在…

Unity实现设计模式——命令模式

Unity实现设计模式——命令模式 推荐一个Unity学习设计模式很好的GitHub地址&#xff1a;https://github.com/QianMo/Unity-Design-Pattern 有非常多的Star 一、介绍 命令模式使得请求的发送者与请求的执行者之间消除耦合&#xff0c;让对象之间的调用关系更加灵活。在命令模…

聊聊零拷贝技术原理和应用

文章目录 0. 引言1. 什么是零拷贝技术 1. 零拷贝技术在不同领域的应用2.传统拷贝技术的缺点3. 零拷贝技术的原理与实现1. sendfile系统调用2. 内核缓冲区与用户缓冲区3. DMA&#xff08;Direct Memory Access&#xff09;技术4. 文件描述符传递与共享5. Direct I/O&#xff08;…

Apache shiro RegExPatternMatcher 权限绕过漏洞 (CVE-2022-32532)

漏洞描述 2022年6月29日&#xff0c;Apache 官方披露 Apache Shiro &#xff08;CVE-2022-32532&#xff09;权限绕过漏洞。 当Apache Shiro中使用RegexRequestMatcher进行权限配置&#xff0c;且正则表达式中携带"."时&#xff0c;未经授权的远程攻击者可通过构造恶…

基于Springboot实现毕业生信息招聘平台管理系统演示【项目源码+论文说明】分享

基于Springboot实现毕业生信息招聘平台管理系统演示 摘要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 毕业生信息招聘平台&#xff0c;主要的模块包括查看管理员&#xff1b;首页、个人中心、企…

Nginx 可视化管理工具与 cpolar 配置:实现远程访问本地服务的优化

文章目录 前言1. docker 一键安装2. 本地访问3. Linux 安装cpolar4. 配置公网访问地址5. 公网远程访问6. 固定公网地址 前言 Nginx Proxy Manager 是一个开源的反向代理工具&#xff0c;不需要了解太多 Nginx 或 Letsencrypt 的相关知识&#xff0c;即可快速将你的服务暴露到外…

服务断路器_服务雪崩解决方案之服务降级

什么是服务降级 两种场景: 当下游的服务因为某种原因响应过慢&#xff0c;下游服务主动停掉一些不太重要的业务&#xff0c;释放出服务器资源&#xff0c;增加响应速度&#xff01;当下游的服务因为某种原因不可用&#xff0c;上游主动调用本地的一些降级逻辑&#xff0c;避免…

SPA移动端解决方案参考

企业在实现SAP移动化时遇到的一些挑战&#xff0c;如果我们利用自己开发团队来进行应用程序的开发&#xff0c;可能会陷入规划&#xff0c;开发&#xff0c;调试&#xff0c;测试的循环中&#xff0c;最后仍一无所获。那如果企业寻找第三方咨询公司进行开发的话&#xff0c;又担…

【高阶数据结构】哈希的应用 {位图;std::bitset;位图的应用;布隆过滤器;布隆过滤器的应用}

一、位图 1.1 位图概念 面试题 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中。【腾讯】 遍历查找&#xff1a;内存中无法存放40亿个整数&#xff08;约占内存15-16G&#xff09;&#xff1b;时间复杂…