数据结构:算法篇:快速排序;直接插入排序

news2024/12/24 20:36:25

目录

快速排序

直接插入排序

改良版冒泡排序


快速排序

理解:

①从待排序元素中选定一个基准元素;

②以基准元素将数据分为两部分:(可以将:大于基准元素放左,小于基准元素放右)

③对左半部分(从左端到基准数据)进行①②操作;直到数据有序

    即将左端到基准数据作为范围,传入;这个范围又会产生新的范围:左端到基准数据2;

    ……

    直到数据有序

④对左半部分(从基准数据到右端)进行①②操作;

【粗劣分析:便于理解】

右半部分:

【深层分析:便于代码】

遍历直倒有序:

数据有序后返回上一层

代码思路

/*

思路:

选定一个基准(默认左端):   用变量temp记录基准值;

loop:

此时左端所在下标low代表的值可以被覆盖(值已经被复制了)

从右端向左端的方向,开始与temp比较,直到遇到比temp小的数,(否则就high--左移),将这个小于temp的数(下标可假定为high')放到左边,左边下标low所在的数据上

此时右端所在下标high代表的值可以被覆盖(值已经复制到下标low代表的值内了)

从左端向左端的方向,开始与temp比较,直到遇到比temp大的数,(否则就low++后移),将这个大于temp的数(下标可假定为low')放到右边,左边下标high所在的数据上

此时左端low'下标的数据可以被覆盖,回到loop;

循环结束条件:low'后移high'前移 直到相遇,说明以基准值temp将这批数据分成两份完毕。

注意:此时大小两份虽然分类完成,但是 作为基准值的数据 还未找到位置;【基准值应该放在下标为low的位置】

看下面图理解

注意,此时应low==high并且理应必须low==high,

注意,此时下标所在位置的数据应该被覆盖,

故基准值应该放在下标为low的位置(或者下标为high,反正两值相等)

*********************************************************

《基准值临界情形图》

基准值5

x x x x 6 3 x x x

        l h     此时基准值正在与l所代表元素比较l向右移中(说明h位置是无用数据)

x x x x 6 6 x x x

        l h     l数据复制给h,轮到下标h向左移动

x x x x 6 6 x x x

        ↑       两下标重合相等,此时应该放入基准值temp(h现在是无用数据)(low左边比基准值小,high右边比基准值大)

基准值7

x x x x 6 5 x x

        l h     此时基准值正在与l所代表元素比较h向左移动中(说明l位置是无用数据)

x x x x 5 5 x x

        l h     h数据复制给l,轮到下标l向左移动(h现在是无用数据)

x x x x 5 5 x x

          ↑     两下标重合相等,此时应该放入基准值temp(h现在是无用数据)(low左边比基准值小,high右边比基准值大)

*********************************************************

*/

全部代码:

#include <stdio.h>

//显示函数
void showData(int buf[],int len)
{
    //显示
    for(int i=0;i<len;i++)
        printf("%d ",buf[i]);
    printf("\n");
}

//快速排序函数

/*************************************************************************
函数功能:   对传入的数据进行一次快速排序(分成大于基准值和小于基准值的两部分);
输入参数:   待排序的数组,需要排序的下标范围(左端下标、右端下标);
返回值:    基准所在的下标
*************************************************************************/
/*
思路:
选定一个基准(默认左端):   用变量temp记录基准值;

loop:
此时左端所在下标low代表的值可以被覆盖(值已经被复制了)
从右端向左端的方向,开始与temp比较,直到遇到比temp小的数,(否则就high--左移),将这个小于temp的数(下标可假定为high')放到左边,左边下标low所在的数据上

此时右端所在下标high代表的值可以被覆盖(值已经复制到下标low代表的值内了)
从左端向左端的方向,开始与temp比较,直到遇到比temp大的数,(否则就low++后移),将这个大于temp的数(下标可假定为low')放到右边,左边下标high所在的数据上

此时左端low'下标的数据可以被覆盖,回到loop;

循环结束条件:low'后移high'前移 直到相遇,说明以基准值temp将这批数据分成两份完毕。

注意:此时大小两份虽然分类完成,但是 作为基准值的数据 还未找到位置;【基准值应该放在下标为low的位置】

看下面图理解
注意,此时应low==high并且理应必须low==high,
注意,此时下标所在位置的数据应该被覆盖,
故基准值应该放在下标为low的位置(或者下标为high,反正两值相等)
*********************************************************
《基准值临界情形图》
基准值5
x x x x 6 3 x x x
        l h     此时基准值正在与l所代表元素比较l向右移中(说明h位置是无用数据)
x x x x 6 6 x x x
        l h     l数据复制给h,轮到下标h向左移动
x x x x 6 6 x x x
        ↑       两下标重合相等,此时应该放入基准值temp(h现在是无用数据)(low左边比基准值小,high右边比基准值大)
基准值7
x x x x 6 5 x x 
        l h     此时基准值正在与l所代表元素比较h向左移动中(说明l位置是无用数据)
x x x x 5 5 x x
        l h     h数据复制给l,轮到下标l向左移动(h现在是无用数据)
x x x x 5 5 x x
          ↑     两下标重合相等,此时应该放入基准值temp(h现在是无用数据)(low左边比基准值小,high右边比基准值大)
*********************************************************
*/

int part(int arr[],int low,int high)
{
    //检查输入范围是否合法
    if(low>high)
    {
        return -1;
    }
    //选定一个基准值(以左端作为基准值)
    int temp=arr[low];//注意:下标low所在数据被temp保存

    //结束循环的条件
    while(low<high)
    {
        //比较右端,比基准大的仍然放在右边,不用管,继续向前判断下一个:故high--;
        while(temp<arr[high]&&low<high)
        {
            high--;//下标向前移动,判断下一个
        }
        //条件不满足时出循环,将这个小数据放到左边,下标为low的地方(low数据已经被保存)
        arr[low]=arr[high];

        //开始比较左端:比基准小得仍然放左边,继续向后判断下一个
        while(temp>arr[low]&&low<high)
        {
            low++;
        }
        //条件不满足,跳出循环,将这个小数据放到左边
        arr[high]=arr[low];//此时high所在数据,之前已经被放到循环前的low里了

        /*
        注意:这里内层循环增设了条件为low<high,
        图形解释:   见最下方《基准值临界情形图》PRO
        文字解释:
            当low与high相差为1时,假定low与low将值给high,开始判断high,
            此时high的值必定会满足,所以high会左移
            high移动到low的位置,仍然会满足值的条件条件
            high继续移动到low的左边,此时high值不满足条件;出循环并且交换数据;回到大循环,判断low<high
        */
    }
    //运行到此,说明low==high;
    arr[high]=temp;
    return high;//基准所在下标low或者high都可以
}

void quick_sort(int arr[],int low,int high)
{
    if(low>=high)
    {
        return;
    }
    int mid=part(arr,low,high);
    quick_sort(arr,low,mid-1);
    quick_sort(arr,mid+1,high);
}

int main()
{
    int arr[]={82,15,49,85,28,43,39,17,47,48};
    int len=sizeof(arr)/sizeof(arr[0]);
    printf("len=%d\n",len);
    //快速排序
    quick_sort(arr,0,9);
    //数据显示
    showData(arr,len);
}

/*
*********************************************************
《基准值临界情形图》PRO     临界情形分析
基准值5
x x x x 6 3 x x x
        l h     此时基准值正在与l所代表元素比较l向右移中(说明h位置是无用数据)
x x x x 6 6 x x x
        l h     l数据复制给h,轮到下标h向左移动
x x x x 6 6 x x x
        ↑       两下标重合相等,此时应该放入基准值temp(h现在是无用数据)
x x x x 6 6 x x x
      h l       内层循环不加low<high;则h会一直移动!直到小于基准值,才回到外层循环判断low<high
基准值7
x x x x 6 5 x x 
        l h     此时基准值正在与l所代表元素比较h向左移动中(说明l位置是无用数据)
x x x x 5 5 x x
        l h     h数据复制给l,轮到下标l向左移动(h现在是无用数据)
x x x x 5 5 x x
          ↑     两下标重合相等,此时应该放入基准值temp(h现在是无用数据)
x x x x 5 5 x x
          h l   内层循环不加low<high;则l会一直移动!直到大于基准值,才回到外层循环判断low<high
*********************************************************
*/

直接插入排序

//直接插入排序
void insert_sort(int arr[],int len)
{
    for(int i=1;i<len;i++)//
    {
        int temp=arr[i];//选定第i个,进行插入
        int j;
        for(j=i-1;j>=0&&arr[j]>temp;j--)//将在"我"之前的数据,依次向后搬运,直到遇到第一个比自己小的元素
        {
            arr[j+1]=arr[j];
        }
        arr[j+1]=temp;//插入位置!注意执行了"j--"才出的循环
    }
}

改良版冒泡排序

//改良版冒泡排序
void bubble_sort(int buf[],int len)
{
    int temp;
    int flag=1;
    for(int i=0;i<len&&flag;i++)//轮数
    {
        flag=0;//使用标志位前,标志位初始值
        for(int j=0;j<len-1-i;j++)//每轮比较次数
        {
            if(buf[j]>buf[j+1])
            {
                flag=1;//发生交换,标志位置1
                temp=buf[j+1];
                buf[j+1]=buf[j];
                buf[j]=temp;
            }
        }
        //一轮下来没有发生交换,排序已完成,跳出循环
    }
}

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

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

相关文章

运维工程师面试系统监控与优化自动化与脚本云计算的理解虚拟化技术的优点和缺点

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把…

如何打造用户友好的维护页面:6个创意提升WordPress网站体验

在网站运营中&#xff0c;无论是个人博主还是大型企业网站的管理员&#xff0c;难免会遇到需要维护的情况。无论是服务器迁移、插件更新&#xff0c;还是突发的技术故障&#xff0c;都可能导致网站短暂无法访问。这时&#xff0c;设计维护页面能很好的缓解用户的不满&#xff0…

postman读取文件执行

要从文件获取的变量 text 在pre-request 中写从文件获取数据的脚本。脚本实现了&#xff0c;设置了text默认值&#xff0c;从文件读取text列&#xff0c;将text存入环境变量 //获取text参数 var text "济南天气"; if(data.text){ text data.text } pm.environment.…

37. Three.js案例-绘制部分球体

37. Three.js案例-绘制部分球体 实现效果 知识点 WebGLRenderer WebGLRenderer 是Three.js中的一个渲染器类&#xff0c;用于将3D场景渲染到网页上。 构造器 WebGLRenderer( parameters : Object ) 参数类型描述parametersObject渲染器的配置参数&#xff0c;可选。 常用…

【Rust自学】4.4. 引用与借用

4.4.0 写在正文之前 这一节的内容其实就相当于C的智能指针移动语义在编译器层面做了一些约束。Rust中引用的写法通过编译器的约束写成了C中最理想、最规范的指针写法。所以学过C的人对这一章肯定会非常熟悉。 喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文…

电脑使用CDR时弹出错误“计算机丢失mfc140u.dll”是什么原因?“计算机丢失mfc140u.dll”要怎么解决?

电脑使用CDR时弹出“计算机丢失mfc140u.dll”错误&#xff1a;原因与解决方案 在日常电脑使用中&#xff0c;我们时常会遇到各种系统报错和文件丢失问题。特别是当我们使用某些特定软件&#xff0c;如CorelDRAW&#xff08;简称CDR&#xff09;时&#xff0c;可能会遇到“计算…

C# 基本信息介绍

总目录 前言 对 C# 做一个基本信息介绍&#xff0c;让我们对 C# 有个基本的认识。 在进行本文的阅读之前&#xff0c;可以瞧瞧 编程基础知识简述 简单的入个门儿。 一、C# 1. C# 概述 C#是由微软公司发布的一种由C和C衍生出来的面向对象的编程语言。 2. C# 详细介绍 C#&am…

『Linux学习笔记』FRPC 详细介绍及配置解析!

『Linux学习笔记』FRPC 详细介绍及配置解析&#xff01; 文章目录 一. FRPC 详细介绍及配置解析FRPC 的主要功能FRPC 配置文件解析全局配置代理配置第一个代理服务第二个代理服务 配置文件整体工作流程常见配置项说明FRPC 的使用步骤注意事项结论 二. 参考文献 一. FRPC 详细介…

WPS工具栏灰色怎么办

WPS离线不登录&#xff0c;开启工具栏等相关功能 当你在使用WPS的过程中&#xff0c;若因网络问题或其他特殊原因&#xff0c;导致无法登录使用WPS时&#xff0c;可根据以下步骤开启离线兼容模式&#xff0c;开启此模式后&#xff0c;可在未登录的状态下&#xff0c;激活并使用…

【微信小程序】2|轮播图 | 我的咖啡店-综合实训

轮播图 引言 在微信小程序中&#xff0c;轮播图是一种常见的用户界面元素&#xff0c;用于展示广告、产品图片等。本文将通过“我的咖啡店”小程序的轮播图实现&#xff0c;详细介绍如何在微信小程序中创建和管理轮播图。 轮播图数据准备 首先&#xff0c;在home.js文件中&a…

JavaEE进阶--mybatis使用测试日志参数传递浏览器访问

文章目录 1.项目创建2.mybatis的使用2.1创建初始页面2.2补充yml文件2.3navicate表2.4用户类的编写2.5查询接口2.6运行测试 3.细节说明3.1java开发规范3.2关于包3.3持久层代码 4.测试文件4.1如何生成4.2生成位置4.3补充方法 5.配置mybatis日志6.参数传递6.1单个参数6.2多个参数 …

IDEA用jformdesigner插件做管理系统MVC架构

在 IntelliJ IDEA 中结合 JFormDesigner 插件&#xff0c;通过 Swing 框架实现一个管理系统的 MVC 架构是一种经典的开发方式。以下是具体的步骤和实现思路&#xff0c;包含从项目创建到 MVC 架构的核心代码实现。 1. 项目结构设计 为了清晰的 MVC 分层架构&#xff0c;建议按…

学习Cookie 提升

目录 Cookie 的覆盖​​​​​​​ Cookie下的path 特点 设置Cookie 路径 实例 Cookie的最大存活时间 设置Cookie 存活时间 实例 Cookie 和session的区别 和联系 Cookie 的覆盖 当 key相同 和只要path的上级目录的路径相同&#xff0c;就可以被替换掉 value 值 如下图…

021、深入解析前端请求拦截器

目录 深入解析前端请求拦截器&#xff1a; 1. 引言 2. 核心实现与基础概念 2.1 基础拦截器实现 2.2 响应拦截器配置 3. 实际应用场景 3.1 完整的用户认证系统 3.2 文件上传系统 3.3 API请求缓存系统 3.4 请求重试机制 3.5 国际化处理 4. 性能优化实践 4.1 请求合并…

4、mysql高阶语句

mysql高阶语句是对复杂的条件进行查询的操作。 排序—order by 加了desc表示由大到小 1、查询name和score&#xff0c;地址都是云南西路的按id进行由小到大排序 2、查询name和score&#xff0c;先按hobbid进行排序&#xff0c;再把结果按id进行排序 第一段字段必须要有相同的…

叉车作业如何确认安全距离——UWB测距防撞系统的应用

叉车在工业环境中运行&#xff0c;常常需要在狭窄的空间内完成货物的搬运和堆垛&#xff0c;这对操作员的技术水平和安全意识提出了极高的要求。传统的叉车作业依赖操作员的经验和视觉判断来确认安全距离&#xff0c;然而这种方式往往存在误差&#xff0c;特别是在视线受阻或光…

LLaVA 多模态大模型:两阶段训练,实现视觉与语言模态的高效融合

LLaVA 多模态大模型&#xff1a;两阶段训练&#xff0c;实现视觉与语言模态的高效融合 论文大纲理解确认目标分析过程实现步骤效果展示金手指 结构分析1. 层级结构分析叠加形态&#xff08;从基础到高级&#xff09;构成形态&#xff08;部分到整体&#xff09;分化形态&#x…

PostgreSQL 的历史

title: PostgreSQL 的历史 date: 2024/12/23 updated: 2024/12/23 author: cmdragon excerpt: PostgreSQL 是一款功能强大且广泛使用的开源关系型数据库管理系统。其历史可以追溯到1986年,当时由加州大学伯克利分校的一个研究团队开发。文章将深入探讨 PostgreSQL 的起源、…

台球助教平台系统开发APP和小程序信息收藏功能需求解析(第十二章)

以下是开发台球助教系统客户端&#xff08;APP&#xff0c;小程序&#xff0c;H5&#xff09;几端的信息收藏功能的详细需求和功能说明&#xff0c;内容比较详细&#xff0c;可以说是一个教科书式的详细说明了&#xff0c;这套需求说明不仅仅用在我们的台球助教系统程序上&…

SRE 与 DevOps记录

flashcat https://flashcat.cloud