数据结构之庖丁解牛八大排序算法,附动图说明过程(上)

news2024/11/28 14:13:08

目录

一、排序的概念以及应用

二、常见排序算法的实现

1.插入排序

1.1直接插入排序

b.实现直接插入排序

1.2希尔排序(缩小增量排序)

2.选择排序

2.1直接选择排序

2.2堆排序

3.交换排序

3.1冒泡排序


一、排序的概念以及应用

1.排序的概念

        所谓排序,就是使一串记录,按照其中的某个或某个关键字的大小,递增或者递减的排列起来的操作。

        排序的稳定性:假定在待排序的记录序列中,存在多个具有相同关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i] = r[j],且r[i]在r[j]之前,在排序后的序列中,r[i]仍在r[j]之前,则这种排序算法是稳定的,否则称为不稳定的

        内部排序:数据元素全部放在内存中的排序

        外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能再内外存之间移动数据的排序

二、常见排序算法的实现

        常见的排序算法包括:插入排序(直接插入排序,希尔排序),选择排序(选择排序,堆排序),交换排序(冒泡排序,快速排序),归并排序

1.插入排序

插入排序的基本思想是:把待排序的记录按其关键值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。

1.1直接插入排序

        当插入第i(i>=1)个元素时,前面的array[0],array[1],...array[i-1]已经排好顺序,此时用array[i]的排序码与array[i-1],array[i-2],...的排序码进行比较,找到插入位置将array[i]插入,原来位置上的元素顺序后移。 a.先看插入一个数的情况,假设前面序列有序,为 1 3 5 6 如果插入7 则放在最后一个位置,如果插入2,则找到比2小的那个数,放在这个数的后面,如果插入 0,找到1仍旧比0大,则0放在最开始的位置,实现代码如下:

void InsertSort1(int * a,int n)
{
    int end = n-1;
    int tmp ;
    a[end+1] = tmp;
    while(end>=0)
    {
        if(tmp <a[end])
        {
            //往后挪动    
            a[end+1] = a[end];
            --end;
        }
        else
        {
            break;
        }
   }
    a[end+1] = tmp;

b.实现直接插入排序

        假设有一组序列: 9 1 2 5 7 4 8 6 3 5 ,将这个序列按照从小到大的顺序进行排序,思想是:先前两个数进行排序,end的位置在9,tmp为1,tmp<end,a[end]向后挪动,插入这个tmp,第二次,排序 则为1 9 2,end的位置在9,tmp的位置在2,进行排序,插入交换位置,第三次 1 2 9 5 依次类推,直到end的位置到3,5为tmp,遍历完整个序列结束排序。

        上述这个过程end的位置在不断变化,给一个变量,控制end的位置。可以使用for循环,end从0开始,到n-1。实现代码如下

void InsertSort(int * a, int n)
{
    for(int i = 0; i< ; i++)
    {
        int end = i;
        int tmp = a[end+1];
        while(end >= 0)
        {
            if(a[end] > tmp)
            {
                a[end+1] = a[end];
                --end;
            }
           else
            {
                break;
            }
        }
        a[end+1] = tmp;
    }
}

1.2希尔排序(缩小增量排序)

        希尔排序,又称缩小增量排序,希尔排序的基本思想是:先选定一个整数,把待排序文件中的所有分组,所有距离相同的记到同一个分组中,并对每一组内的记录进行排序,然后重复分组和排序的工作,当gap = 1的时候,所有的为有序。

      假设现在有一组数据: 9 8  7 6 5 4 3 2 1 ,先进行分组,gap = 3的为一组 (9,6,3;8,5,2;7,4,1)然后对每一组进行插入排序,end的位置在9,tmp为6,排序完6 9 3 这个时候end不再--,而是end-gap,实现这一步骤的代码如下:

int gap = 3;
int end;
int tmp = a[end+gap];
while(end >= 0)
{
    if(tmp<a[end])
    {
        a[end+gap] = a[end];
        end -= gap;
    }
    else
    {
        break;
    }
 }
  
a[end+gap] = tmp;

        上述过程只实现了一步的预排序和插入,想要对一组进行排序,end的位置需要变化,每次变化是有规律的,第一次end 在起始位置,第二次end在下标为3的位置,第三次end在下标为6的位置,一共有9个数,第一次变量i= 0,第三次i = n-gap,每次i++gap次,实现代码如下:

int gap = 3;
for(int i = 0;i<n-gap;i+=gap)
{
    int end = i;
    int tmp = a[end+gap];
    while(end>=0)
    {
        if(tmp>a[end])
        {
            a[end+gap] = a[end];
            end-=gap;
        }
        else
        {
            break;
        }
        
    }
    a[end+gap] = tmp;
}

上述过程实现了对一组数据进行排序,如果想要对所有组进行排序,需要对i进行改变,进而改变end的位置,由上述分组可以看出,gap为3的时候,分为了3组,i的起始位置分别为9 8 7,所以使用一个变量j,来控制i的变化,i= 0时,排序第一组,i=1的时候,排序第二组,i=3的时候排序第3组;实现代码如下:

int gap = 3;
for(int j = 0;j<gap;++j)
{
    for(int i = j; i<n-gap;i+=gap)
    {
        int end = i;
        int tmp = a[end+gap];
        while(end>=0)
        {
            if(tmp<a[end])
            {
                a[end+gap] = a[end];
                end -=gap;
            }
            else
            {
            break;
            }
         }
        a[end+gap] = tmp;
    }
}

//如果不想一组一组排,gap并排可以修改上述条件
for(int i = 0;i<n-gap;++i)

        排序的时候gap越大,大的数可以更快到后面,小的可以更快到前面,表面这个时候序列越不接近有序,gao越小,数据跳动越慢,越接近有序

        实际上的gap值是变化的,实现代码如下:

void ShellSort(int * a,int n)
{
    //gap>1 预排序
    // gap ==1 直接插入排序
    int gap = n;
    while(gap > 1)
    {
        gap = gap / 3 +1  //这里是为了保证最后一个数可以实现直接插入排序
        for(int i = 0; i<n-gap; ++i)
        {
            int end = i;
            int tmp = a[end+gap];
            while(end >= 0)
            {
                if(tmp <a[end])
                {
                    a[end+gap] = a[end];
                    end -= gap;
                }
                else
                {
                    break;
                }
        }

            a[end+gap] = tmp;
        }
}

2.选择排序

        基本思想:每次从待排序的数据元素中选出最小(或者最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完

2.1直接选择排序

        在元素集合array[i]--array[n-1]中选择关键最大(小)的数据元素,如果它不是这组元素中的第一个(最后一个)元素,则将它与这组元素中的最后一个(第一个)进行交换,在剩余的array[i]--array[n-2]集合,重复上述步骤,直到集合剩余1个元素

        在这里改进一下直接选择排序,每次找到最大的和最小的,分别放在前面和后面。注意这里,如果maxi和begin指向了同一块,需要进行特殊处理,实现代码如下:

实现代码如下:

void SelectSort(int * a, int n)
{

    int begin = 0 , end = n-1;
    while(begin < end)
    {
        int mini = begin, maxi = begin;
        for(int i = begin +1; i<=end ; ++i)
        {
            if(a[i] <a[mini])
            {
                mini = i;
            }
        
            if(a[i] > a[maxi])
            {
                maxi = i;
            }
        
        }
        
        Swap(&a[begin],&a[mini]);
        //这里为了防止maxi和begin指向同一块位置
        if(maxi == begin)
        {
            maxi = mini;
        }
        Swap(&a[end],&a[maxi])
        ++begin;
    }
}

2.2堆排序

        思想:如果要排序一个升序,建立一个小堆,先将堆顶元素和最后一个元素交换,然后向下调整。如果要排序一个降序,建立一个大堆,将堆顶元素和最后一个元素交换,然后向下调整。

void AdjustDown(int * a, int n,int root)
{
    int parent = root;
    int child = 2*parent +1;
    
    while(child < n)
    {
        if(child+1 <n && a[child+1] >a[child])
        {
            ++child;
        }

        //小的向下调整 建立大堆
    
        if(a[parent] <a[child])
        {
            Swap(&a[parent],&a[child]);
            parent = child;
            child = 2*parent +1;
        }
       
        else
        {
            break;
        }
        


}
//要排一个升序,升序建立一个大堆 
//这里形参是一个数组,从数组开始要对一个数进行排序,先找最后一个非叶子节点建立大堆,堆顶是最大的数
//然后找到最后一个数,此时大堆的最后一个数是较小的数,放在堆顶,再去调整为大堆,此时第二大的数就在堆顶
void HeapSort(int * a, int n)
{
    //从倒数第一个非叶子节点开始建立大堆
    for(int i = n-1-1/2; i>=0;i--)
    {
        AdjustDown(a,n,i);
    }

    int end = n-1;
    while(end >0)
    {
        Swap(&a[0],&a[end]);  //将堆顶元素和最后一个元素交换
        AdjustDown(a,end,0);  //然后将堆顶元素向下调整
        end--;
    }
}

}

3.交换排序

        交换排序的基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换之两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动

3.1冒泡排序

        冒泡排序的思想就是:a[i]和a[i+1]进行比较,大的往后挪动,一直重复这个过程,这是单趟的冒泡排序,多趟就是控制i的变化,每次冒泡都会把这轮中最大的数放在最后面,可以使用一个变量j,i第一次到最后一个值,第二次到倒数第二个,...i的变化就是0--n-j;j++。实现代码如下:

void BubbleSort(int * a, int n)
{
    for(int j = 0; j<n;j++)
    {
        for(int i = 0; i<n-j;i++)
        {
            if(a[i] >a[i+1])
            {
                Swap(&a[i],&a[i+1]);
            }
        }
    }
}

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

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

相关文章

Mysql数据库--修改root密码的几种方法(忘记密码知道密码)

Mysql数据库--修改root密码的几种方法&#xff08;忘记密码&知道密码&#xff09; &#x1f53b;一、知道密码情况--修改root密码⛳ 1.1 方式1&#xff1a;alter 命令修改⛳ 1.2 方式2&#xff1a;set password命令修改 &#x1f53b;二、忘记密码情况-修改root密码⛳ 2.1 …

华为OD机试真题 Java 实现【找车位】【2023 B卷 100分】,附详细解题思路

一、题目描述 停车场有一横排车位&#xff0c;0代表没有停车&#xff0c;1代表有车。至少停了一辆车在车位上&#xff0c;也至少有一个空位没有停车。 为了防剐蹭&#xff0c;需为停车人找到一个车位&#xff0c;使得距停车人的车最近的车辆的距离是最大的&#xff0c;返回此…

打造高质量视频,创造视觉奇观!Camtasia 2023为你升级!

嘿&#xff0c;伙计&#xff01; 在这个全新版本中&#xff0c;我们迎来了焕然一新的动画控制和更简化的特效制作流程&#xff0c;让创作变得更高效。 不仅如此&#xff0c;全新的背景去除和动画光标功能也让视频拥有全新的视觉体验。让我们先谈谈光标&#xff0c;这个细节或…

计算机视觉:风格迁移

风格迁移 本节将介绍如何使用卷积神经网络&#xff0c;自动将一个图像中的风格应用在另一图像之上&#xff0c;即风格迁移&#xff08;style transfer&#xff09; (Gatys et al., 2016)。 这里我们需要两张输入图像&#xff1a;一张是内容图像&#xff0c;另一张是风格图像。…

Mac使用DBeaver连接达梦数据库

Mac使用DBeaver连接达梦数据库 下载达梦驱动包 达梦数据库 在下载页面随便选择一个系统并下载下来。 下载下来的是zip的压缩包解压出来就是一个ISO文件&#xff0c;然后我们打开ISO文件进入目录&#xff1a;/dameng/source/drivers/jdbc 进入目录后找到这几个驱动包&#x…

Vue 2和Vue 3路由Router创建的区别简记(在main.js文件中引入的区别和router的js文件中创建语法的区别)

Vue 2和Vue 3路由Router创建的区别即Router3.0和Router4.0的创建区别简记 1、版本的搭配&#xff1a; Vue 2到Vue 3的改版升级&#xff0c;同样的带来Vue Router的升级。创建Vue项目之后&#xff0c;我们可以在package.json文件中看到&#xff0c;Vue 2创建的项目往往是与Vue…

C++ | 拷贝文件

C拷贝文件 文章目录 C拷贝文件ANSI-C-WAYPOSIX-WAY (K&R use this in "The C programming language", more low-level)KISS-C-Streambuffer-WAYCOPY-ALGORITHM-C-WAYOWN-BUFFER-C-WAYLINUX-WAY理智的方式C 17Reference欢迎关注公众号【三戒纪元】 列举了几种拷贝…

nestjs超详细从零到零点五详细入门项目搭建过程

nestjs超详细从零到零点五详细入门项目搭建过程 项目完整地址github&#xff0c;修复了一些swagger文档接口&#xff0c;传参显示问题 从零到有搭建一个完整的后台管理系统项目 涉及到的知识 controller控制器provider提供者module模块middleware中间件filter过滤器pipe管道…

简明Python教程

前言&#xff1a;学习《简明 Python 教程》Swaroop, C. H. 著 沈洁元 译 www.byteofpython.info 摘录&#xff0c;方便以后使用查阅。 基础概念 常量 Python中有4种类型的数——整数、长整数、浮点数和复数。 2是一个整数的例子。长整数不过是大一些的整数。3.23和52.3E-4是…

高标准农田信息化管理平台概要设计

1、综合信息一张图系统 通过一张图的形式&#xff0c;可视化直观展示地区土地分布、耕地质量、高标准农田建设情况、灌溉情况、设备分布情况及环境监测数据。农业管理者可在一张图上查看农田相关信息&#xff0c;及时了解农田情况&#xff0c;为农田管理者的精准管理和科学决策…

Axure教程—拖拽获取(中继器+动态面板 )

本文将教大家如何用AXURE中的中继器和动态面板制作拖拽获取效果 一、效果介绍 如图&#xff1a; 预览地址&#xff1a;https://68e5b3.axshare.com 下载地址&#xff1a;https://download.csdn.net/download/weixin_43516258/87874085?spm1001.2014.3001.5503 二、功能介绍 …

OpenMMLab-AI实战营第二期——2-2.基于RTMPose的耳朵穴位关键点检测(Colab+MMPose)

文章目录 1. Colab和Google云端硬盘1.1 建立项目文件和jupyter文件1.2 Colab运行时选择1.3 关联Colab中的文件和Google云端硬盘的文件 2. Colab和MMPose2.1 环境配置2.2 配置文件修改 3. Colab相关知识 视频链接&#xff1a;B站-RTMPose关键点检测-安装MMDetection和MMPose 1.…

一篇文章搞定Java中常用集合的排序方法

目录 Array 数组 List 列表 Collections.sort() 简单类型 复杂对象 类 使用Lambda表达式 Stream API Map 键值对 对 Map 的 Key 进行排序 对 Map 的 Value 进行排序 最近在做算法题的时候&#xff0c;发现排序在大部分题中都不可或缺&#xff0c;今天心血来潮&am…

Vue配置proxy代理,但接口报错2007 bad domain

1、排查proxy代理配置是否有误 排查 proxyTable 对象中配置的 target 是否正确。若正确&#xff0c;那可能就是请求头的问题。 无特殊配置的情况下&#xff0c;请求头是这样子的&#xff1a; Host 和 Referer 是本地地址&#xff0c;如果后端增加 CSRF 防御机制&#xff0c;…

【JDBC:连接MySQL数据库】出现SQL注入的解决办法、什么时候需要使用SQL注入、事务的使用、悲观锁乐观锁

JDBC JDBC是什么&#xff1f; Java Database Connectivity&#xff08;java语言连接数据库&#xff09; java.sql.*;&#xff08;这个包下有很多接口&#xff09; JDBC的本质是什么&#xff1f; JDBC的本质是SUN公司制定的一套接口&#xff08;interface&#xff09; 接口都有…

【C语言】数据以及位运算

位和位运算 C语言中数据的表示方法各种数据类型可表示的数值范围位和CHAR_BITsizeof运算符整型的内部表示无符号整数的内部表示有符号整数的内部表示 位运算位运算符位与运算位或运算位异或运算位取反运算位左移运算符位右移运算符逻辑位移与算术位移 C语言中数据的表示方法 各…

HCIA-RS实验-路由配置-OSPF 单区域配置

OSPF&#xff08;Open Shortest Path First&#xff09;是一种基于链路状态的路由协议&#xff0c;常用于大型企业网络中。在一个单区域的OSPF网络中&#xff0c;所有的路由器都属于同一个区域&#xff0c;这种配置方式相对简单直观。本文将介绍OSPF单区域的配置方法。 这篇文章…

Vultr 简介和域名购买

1. 网络地址 Vultr: https://my.vultr.com/ Namecheap: Namecheap.com • Login 2. Vultr 简介&#xff1a; Vultr是一家知名的云计算服务提供商&#xff0c;成立于2014年&#xff0c;总部位于美国新泽西州。Vultr提供高性能的云服务器、存储、网络和应用服务&#xff0c;以…

如何把低像素图片转成高清,分享四个方法给大家!

当图片的像素较低时&#xff0c;通常会导致图片模糊不清。然而&#xff0c;我们可以采取一些方法来将低像素图片转变为高清。下面我将介绍几种简单易用的方法&#xff0c;帮助您快速提高照片的分辨率&#xff0c;还原照片的清晰度&#xff01; 方法一&#xff1a;记灵在线工具…

【attention|Tensorformer】从attention走向Transformer

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 概括 说明&#xff1a; 后续增补 1. 正文 1.0 通俗理解 人类视觉的注意力&#xff0c;简单说就第一眼会注意在一幅图像的重要位置上。 而在程序中&am…