【数据结构】交换排序

插入排序链接。
这篇文章讲解交换排序的两种排序:冒泡排序快速排序

目录

  • 冒泡排序:
    • 完整代码:
  • 快速排序:
    • 单趟排序:
      • hoare:
      • 挖坑:
      • 前后指针:
    • 完整代码(3种方式):

冒泡排序:

冒泡排序简单不实用,被誉为数据结构的“HelloWord”

思想:相邻元素两两比较,根据升序或者降序每趟选出一个最值放在数组尾部
在这里插入图片描述

我们实现冒泡排序时,先进行一趟冒泡排序,这样容易控制整个程序

注意n为数组元素个数

for (int j = 0; j < n - 1; j++)
为什么j<n-1而不是j<n,因为我们会访问a[j+1],故最大的J为n-2
{if (a[j] > a[j + 1]){Swap(&a[j], &a[j + 1]);}
}

在进行完一趟后,就可以嵌套一个for循环,因为一趟可以确定一个元素位置,故for (int i = 0; i < n; i++)
最后我们想,当确定一个元素的位置后,下一次就可以不用管他,故内层for循环再for (int j = 0; j < n - i - 1; j++)

完整代码:

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

快速排序:

先来数一下快排的整体思想(升序):

先选出一个关键值,进行一次单趟排序,
这趟排序是怎样的排序呢?
只要确保关键值左边的比关键值小,右边的比关键值大就算一趟排序

单趟排序完成后,我们可以利用遍历二叉树的思想
在这里插入图片描述
最终完成排序,也就是快排

单趟排序:

既然主要部分是单趟排序,那么就有多种单趟排序的办法,这里我们只说最常用的三种

hoare:

hoare是快排的发明者,故hoare自己搞了一个单趟排序,
在这里插入图片描述
思想:
选出一个key值(最左边),
right先走,当 right 找到比 key 小的时候或遇到 left 时停止,
left再走,当 left 找到比 key 大的时候或遇到 right 时停止,
当没有相遇时,他们交换值,
相遇后,将key的值与left(或right,因为相遇时left == right)交换

此时完成单趟排序。

int PartSort1(int* a, int begin, int end)
{int left = begin;int right = end;int keyi = left;while (left < right){while (left < right && a[right] >= a[keyi]){right--;}while (left < right && a[left] <= a[keyi]){left++;}//相遇前,left与right的值交换Swap(&a[left], &a[right]);}//相遇后Swap(&a[keyi], &a[right]);keyi = left;//为什么return呢,马上会讲解return keyi;
}

挖坑:

挖坑法的思想整体与hoare一致,不过有点差异。
在这里插入图片描述
思想:

将最左边作为关键值,同时作为坑的下标,
同理,right先走,遇到比关键值小的或相遇时停下,将right此时的值给坑,right变成新的坑
left再走,遇到比关键值大的或相遇时停下,将left此时的值给坑,left变成新的坑
当相遇时,将key值给坑

这就是一趟排序

//挖坑
int PartSort2(int* a, int begin, int end)
{int left = begin;int right = end;int key = a[left];int holei = left;while (left < right){// 右边找小,填到左边的坑while (left < right && a[right] >= key){right--;}a[holei] = a[right];holei = right;// 左边找大,填到右边的坑while (left < right && a[left] <= key){left++;}a[holei] = a[left];holei = left;}a[holei] = key;return holei;
}

前后指针:

前后指针的方法与前两者的思想不同。
在这里插入图片描述


分解成一步一步,看到最后发现prev与cur之间的就是比key大的,
最后将prev与key的值交换,完成单趟排序
在这里插入图片描述


这是我们最提倡的一种,根本思想就是:

cur的值大于key时,cur++;
当cur的值小于key时,prev++,将prev与cur的值交换,cur++

int PartSort3(int* a, int begin, int end)
{int prev = begin;int cur = begin + 1;int keyi = begin;while (cur <= end){if (a[cur] < a[keyi]){prev++;Swap(&a[prev], &a[cur]);}cur++;}Swap(&a[prev], &a[keyi]);return prev;
}

这里解释一下为什么会返回一个key的下标,因为我们是单趟排序,有多种方案
用下图代码实现快排更为方便

void QuickSort(int* a, int begin, int end)
{if (begin >= end){return;}int keyi = PartSort3(a, begin, end);//begin keyi endQuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);
}

完整代码(3种方式):

#include "Sort.h"
#include "stack.h"void Swap(int* e1, int* e2)
{int tmp = *e1;*e1 = *e2;*e2 = tmp;
}
//hoare
int PartSort1(int* a, int begin, int end)
{int left = begin;int right = end;int mid = (left + right) / 2;int midi = getmid(a, mid, left, right);Swap(&a[left], &a[midi]);int keyi = left;while (left < right){while (left < right && a[right] >= a[keyi]){right--;}while (left < right && a[left] <= a[keyi]){left++;}Swap(&a[left], &a[right]);}Swap(&a[keyi], &a[right]);keyi = left;return keyi;
}//挖坑
int PartSort2(int* a, int begin, int end)
{int left = begin;int right = end;int mid = (begin - end) / 2;int midi = getmid(a, mid, left, right);Swap(&a[midi], &a[left]);int key = a[left];int holei = left;while (left < right){while (left < right && a[right] >= key){right--;}a[holei] = a[right];holei = right;while (left < right && a[left] <= key){left++;}a[holei] = a[left];holei = left;}a[holei] = key;return holei;
}//前后指针
int PartSort3(int* a, int begin, int end)
{int prev = begin;int cur = begin + 1;int keyi = begin;while (cur <= end){if (a[cur] < a[keyi]){prev++;Swap(&a[prev], &a[cur]);}cur++;}Swap(&a[prev], &a[keyi]);return prev;
}void QuickSort(int* a, int begin, int end)
{if (begin >= end){return;}int keyi = PartSort3(a, begin, end);//begin keyi endQuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);
}

欢迎讨论哦

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

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

相关文章

3 - AOP

1. 快速入门 1.1 基本说明 AOP(aspect oriented programming) &#xff0c;面向切面编程 切面类中声明通知方法&#xff1a; 前置通知&#xff1a;Before返回通知&#xff1a;AfterReturning异常通知&#xff1a;AfterThrowing后置通知&#xff1a;After环绕通知&#xff1…

2、Redis持久化、主从与哨兵:构建强大而稳定的数据生态

Redis作为一款高性能的内存数据库&#xff0c;其在持久化、主从复制和哨兵系统方面的支持使其在大规模应用和高可用性场景中脱颖而出。本文将深入探讨Redis的持久化机制、主从复制以及哨兵系统&#xff0c;为构建强大而稳定的数据生态揭示关键技术。 持久化&#xff1a;数据的…

二进制与十六进制,二进制与八进制之间的相互转换技巧

目录 1.二进制转换为八进制 2.八进制转换为二进制 3.二进制转换为十六进制 4.十六进制转换为二进制 1.二进制转换为八进制 转换为8进制 第一步&#xff1a;以小数点为分界线&#xff0c;整数部分自右向左&#xff0c;小数部分自左向右每3位取成1位&#xff1a; 整数部分…

【python入门】day28:记录用户登录日志

演示 代码 #-*- coding:utf-8 -*- print(记录用户登录日志----------------------------) import time def show_info():print(输入提示数字,执行相应操作:0退出,1查看登录日志) def write_logininfo(username):#----------记录日志with open(log.txt,a,encodingutf-8)as file…

如何高效阅读Linux的man page

有时候需要在man page中查某个命令的用法&#xff0c;我们一般会使用man command的方式来查询&#xff0c;例如man vmstat.但是对于一些bash内置的命令&#xff0c;如alias,如果使用man alias会打开General Commands Manual ,如下图 可以看到&#xff0c;内置命令很多&#xff…

COBOL语言 :一种主要专注于解决业务问题的编程语言

译文&#xff1a; 什么是COBOL? COBOL是一种主要专注于解决业务问题的编程语言。COBOL的完整形式是面向业务的通用语言。它主要用于公司和政府的商业、金融和行政系统。这种语言也被用来解决许多数据处理问题。 它是由CODASYL(数据系统语言会议)开发的。它被用作大型机中的一…

基于 InternLM 和 LangChain 搭建你的知识库

如何打造垂域大模型是一个重要落地方向。 如何打造个人专属的大模型应用也是重要的问题。 RAG 外挂一个知识库 优势&#xff1a;成本低&#xff0c;实时更新 劣势&#xff1a;能力受基座模型影响大&#xff0c;RAG每次需要将检索文档和问题提交给大模型&#xff0c;极大占用上下…

工程项目管理系统源码与Spring Cloud:实现高效系统管理与二次开发

随着企业规模的不断扩大和业务的快速发展&#xff0c;传统的工程项目管理方式已经无法满足现代企业的需求。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性&#xff0c;企业需要借助先进的数字化技术进行转型。本文将介绍一款采用Spring CloudSpring BootMybat…

C++力扣题目701--二叉搜索树中的插入操作

给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 注意&#xff0c;可能存在多种有效的插入方式&a…

苏州倍丰智能新型雾化粉末技术量产成功!金属3D打印全产业链更进一步

苏州倍丰智能深耕金属3D打印技术领域&#xff0c;以金属3D打印全产业链为目标&#xff0c;围绕金属3D打印设备&#xff0c;涵盖包括金属粉末前后处理设备、金属粉末原材料制备、先进工艺研发等多个领域&#xff0c;完成了一整条自上而下的金属3D打印全产业链。 近日&#xff0c…

大数据Doris(五十四):SQL函数之日期函数(二)

文章目录 SQL函数之日期函数(二) 一、DAYOFMONTH(DATETIME date) 二、dayofweek(DATETIME date)

HarmonyOS 通过 animateTo讲解尺寸动画效果

上文 HarmonyOS讲解并演示 animateTo 动画效果 我们已经做出了基本的动画效果 也对 animateTo 的使用比较熟悉了 第一个参数是 配置动画参数的json 第二个参数 则是改变我们元素属性值的事件 但属性值 远远不止位置属性 本文 我们来说 通过尺寸变化 完成动画效果 如果你有看过…

代码随想录算法训练营第4天 | 24. 两两交换链表中的节点 , 19.删除链表的倒数第N个节点 , 面试题 02.07. 链表相交 , 142.环形链表II

链表知识基础 文章链接&#xff1a;https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html# 24. 两两交换链表中的节点 题目链接&#xff1a;https://leetcode.cn/problems/swap-nodes-in-pairs/ 使用虚拟头结点&#xff0c;这样会方便很…

Centos7编译Python3.11源码并安装完成的详细教程

Python3.11的Linux源码&#xff1a; Index of /ftp/python/https://www.python.org/ftp/python/由于Centos7里自带的openssl是1.0版本的&#xff0c;而Centos Stream8和9用的是openssl-1.1.1版本的。 注意&#xff1a;openssl必须是openssl-1.1.1版本的&#xff0c;虽然最高版…

QT的事件机制

QT的事件机制 文章目录 QT的事件机制 1、QT的事件机制。2、QT事件的整体流程。1、事件处理函数。1、鼠标按下与鼠标释放事件。2、事件的接收与忽略(accept()和ignore()函数&#xff09;。 2.事件的分发enevt()1、事件分发的dome。2、enevt事件的缺点。 3、事件的过滤器。 3、总…

通过本质看现象:关于Integer受内部初始化赋值范围限制而出现的有趣现象

文/朱季谦 这是我很多年前的第一篇技术博客&#xff0c;当时作为一名技术小菜鸟&#xff0c;总体而言显得很拙见&#xff0c;但也算是成长路上的一个小脚印&#xff0c;希望能在以后的日子里&#xff0c;可以对JAVA技术有一个更加深入的思考与认识。 前几天我在逛论坛的时候&a…

SSM基础入门

SSM Mybatis、Spring和SpringMVC这三个框架整合在一起完成业务功能开发 文章目录 SSM5.1 流程5.2 详细步骤5.2.1 基本配置5.2.2 功能模块开发5.2.3 测试5.2.3.1 单元测试5.2.3.2 PostMan测试 5.3 统一结果封装5.3.1 概念5.3.2 实现 5.4 统一异常处理5.4.1 异常处理器的使用5.4…

Linux Centos7静默安装(非图形安装)Oracle RAC 11gR2(Oracle RAC 11.2.0.4)

Oracle RAC (全称Oracle Real Application Clusters &#xff09;静默安装&#xff08;非图形安装&#xff09;教程。 由于这篇文章花费了我太多时间&#xff0c;设置了仅粉丝可见&#xff0c;见谅。 环境说明&#xff1a; 虚拟机软件&#xff1a;VMware Workstation 16 Pro…

Git与VScode联合使用详解

目录 Git与VScode联合使用 方式一 1. 用vscode打开文件夹&#xff0c;如图点击初始化仓库&#xff0c;把此仓库初始为git仓库。 2. 提交文件到本地仓库 3. vscode与github账号绑定 4. 在github中建立远程仓库 5. 本地仓库与远程仓库绑定 方式二 1. 在github上建立远程仓…

VSCode添加Python解释器并安装Python库

目录 一、安装VSCode 二、安装Python解释器 1、安装包链接 2、安装过程 3、测试 4、安装flake8和yapf两个包 &#xff08;1&#xff09;安装flake8包 &#xff08;2&#xff09;安装yapf包 三、VSCode中选择python解释器 一、安装VSCode VSCode安装教程&#xff08;默…