排序算法——交换排序(快排*)和归并排序

2023-11-11

上篇文章介绍了插入排序和选择排序,详见https://mp.csdn.net/postedit/97524495

3交换排序

     所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记

录向序列的尾部移动,键值较小的记录向序列的前部移动。交换排序分为冒泡排序和快速排序。

3.1冒泡排序

3.1.1基本方法

①比较相邻的元素。如果第一个比第二个大,就交换他们两个。 

②对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。 

③针对所有的元素重复以上的步骤,除了最后一个。 

④持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 

3.1.2图解算法

3.1.3算法实现

void BubbleSort(int* array, int size)
{
	int flag = 1;
	for (int i = 0; i < size&&flag==1; i++)
	{
		int flag = 0;
		for (int j = 1; j < size - i; j++)
		{
			if (array[j - 1] > array[j])
			{
				flag = 1;
				Swap(&array[j - 1], &array[j]);//两两比较有逆序就交换 
			}
		}
	}
}

3.1.4特性总结

1. 冒泡排序是一种容易理解的排序

2. 时间复杂度:O(N^2)

3. 空间复杂度:O(1)

4. 稳定性:稳定

3.2快速排序

3.2.1基本思想

      任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准

值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。快排之所以

快,是因为利用了二分的思想。

       快排有三种方法①左右指针法②挖坑法③前后指针法

3.2.2左右指针法

int Partion1(int* array, int left, int right)
{
	assert(array);
	int begin = left;
	int end = right-1;
	int key = array[end];//选基准值为最右元素
	while (begin < end)
	{
		while (begin < end && array[begin] <= key)//前面找大
			begin++;
		while (begin < end && array[end] >= key)//后面找小
			end--;
		if (begin < end)
			Swap(&array[begin], &array[end]);//交换
	}
	Swap(&array[right - 1], &array[begin]);//交换基准值和分界点
	return begin;
}

3.2.3挖坑法

int Partion2(int* array, int left, int right)
{
	assert(array);
	int begin = left;
	int end = right - 1;
	int key = array[end];//选取最右元素为坑
	while (begin < end)
	{
		while (begin < end && array[begin] <= key)//左边找大入坑
			begin++;
		if (begin < end)
			array[end] = array[begin];
		while (begin < end && array[end] >= key)//右边找小入坑
			end--;
		if (begin < end)
			array[begin] = array[end];
	}
	array[begin] = key;
	return begin;
}

3.2.4前后指针法

关于该方法很巧妙,这篇文章有详细的分析:https://blog.csdn.net/Hanani_Jia/article/details/80571665

int Partion3(int* array, int left, int right)
{
	int cur = left;
	int pre = cur-1;
	int end = right - 1;
	int key = array[end];
	while (cur<end)
	{
        //定义两个指针
        //如果前面的array[cur]小于key,prev走一步后交换array[pre]和array[cur],cur走
        //遇到array[cur]大于key时,pre停下来,cur继续走
        //当array[cur]等于key时,一趟结束,交换key和array[cur],平分数组,依次递归。

		while (array[cur] > key)
			cur++;
		if (array[cur] <= key)
		{
			pre++;
			Swap(&array[pre], &array[cur]);
			cur++;
		}
	}
	Swap(&array[pre], &array[end]);
	return pre;
}

3.2.5快速排序的优化

①三数取中法 
    当我们每次选取key时,如果key恰好是最大或者最小值,效率会很低,为了避免这种情况,对快排选取key值进行优化。 

    思路:依旧选取最右边的值作为key,但是在选取前,我们把数组中最左边,中间,最右边位置的三个数取出来。找到这三个

数中值排在中间的一个。把该值与最右边位置的值进行交换。此时key的值不可能是最大值或者最小值。 

int GetMidIndex(int* array, int left, int right)
{
	int mid = left + ((right - left)>>1);
	if(array[left] < array[right])
	{
		if(array[mid] < array[left])
			return left;
		else if(array[mid] > array[right])
			return right;
		else
			return mid;
	}
	else
	{
		if(array[mid] > array[left])
			return left;
		else if(array[mid] < array[right])
			return right;
		else
			return mid;
	}
}


②随机值法。 
      num = rand()%N 把num位置的数与最右边的值交换,key依旧去最右边的值。这种方法也可以,但是太随机了,特殊场景

会导致不可控的结果。 

③小区间优化 。

      快排是利用递归栈帧完成的,如果递归深度太深会影响效率。切割区间时,当区间内元素数量比较少时就不用切割区间了,

这时候就直接对这个区间采用直接插入法,可以进一步提高算法效率。 

// [left, right)
void QuickSort(int* array, int left, int right)
{
	if(right - left < 16)
		InsertSort(array+left, right - left);
	else
	{
		int div = Partion2(array, left, right);
		QuickSort(array, left, div);
		QuickSort(array, div+1, right);
	}
}

3.2.6快速排序特性总结

1. 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序

2. 时间复杂度:O(N*logN)

3. 空间复杂度:O(logN)

4. 稳定性:不稳定

4归并排序

4.1归并排序

4.1.1基本思想

       归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,

得到完全有序的序列;即先使每个子序列有 序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

4.1.2图解

4.1.3算法实现

void MergeData(int* array, int left, int mid, int right, int*temp)
{
	int beginL = left, endL = mid;
	int beginR = mid, endR = right;
	int index = left;

	while(beginL < endL && beginR < endR)
	{
		if(array[beginL] <= array[beginR])
			temp[index++] = array[beginL++];
		else
			temp[index++] = array[beginR++];
	}

	while(beginL < endL)
	{
		temp[index++] = array[beginL++];
	}

	while(beginR < endR)
	{
		temp[index++] = array[beginR++];
	}
}

void _MergeSort(int* array, int left, int right, int* temp)
{
	if(right - left > 1)
	{
		int mid = left + ((right - left)>>1);
		_MergeSort(array, left, mid, temp);
		_MergeSort(array, mid, right, temp);
		MergeData(array, left, mid, right, temp);
		memcpy(array+left, temp+left, sizeof(array[0])*(right - left));
	}
}

void MergeSort(int* array, int size)
{
	int* temp = (int*)malloc(size * sizeof(array[0]));//需要开额外空间
	if(NULL == temp)
	{
		assert(0);
		return;
	}

	_MergeSort(array, 0, size, temp);
	free(temp);
}

4.1.4归并排序特性总结

1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。

2. 时间复杂度:O(N*logN)

3. 空间复杂度:O(N)

4. 稳定性:稳定

5排序算法性能比较

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

排序算法——交换排序(快排*)和归并排序 的相关文章

  • 数据结构和算法--树

    数据结构和算法是一种思想 理解了思想就是忘记了代码也能找回原来的记忆 二叉搜索树 二叉树 每个结点只存储一个关键字 等于则命中 小于走左结点 大于走右结点 AVL树 每个节点的左子树和右子树的高度最多差1的二叉搜索树 B B 树 多路搜索树
  • 给定一个二叉树, 找到该树中两个指定节点p和q(数值唯一)的最近公共祖先

    递归思想 判断p和q是否分别根结点的左右两侧 如果在左右两侧那么直接返回根结点即可 不失一般性 假设p和q分别均在根结点的左侧 那么按照分治的思想 此时继续往左子树找即可 问题规模已经缩小 那么依旧还是上面的操作划分 故可以采用递归的思想
  • 【数据结构和算法】超多图解,超详细,堆详解

    作者 Linux猿 简介 CSDN博客专家 华为云享专家 数据结构和算法 C C 面试 刷题 Linux尽管咨询我 关注我 有问题私聊 关注专栏 图解数据结构和算法 优质好文持续更新中 欢迎小伙伴们点赞 收藏 留言 目录 一 什么是堆
  • 图的深度优先搜索(dfs)

    图的遍历 即是对结点的访问 一个图有那么多个结点 如何遍历这些结点 需要特定策略 一般有两种访问策略 1 深度优先遍历 2 广度优先遍历 图的深度优先搜索 Depth First Search 指的是在搜索时 如果遇到一个结点既有子结点 又
  • 数据结构---归并排序

    归并排序 第一步 分组 第二步 归并 归并操作 第一步 第二步 第三步 JAVA实现 总结 第一步 分组 第1层分成2个大组 每组n 2个元素 第2层分成4个小组 每组n 4个元素 第3层分成8个更小的组 每组n 8个元素 一直到每组只有一
  • 第十四届蓝桥杯第三期模拟赛 C/C++ B组 原题与详解

    1 找最小全为字母的16进制数 2 求一个数的26进制并用A Z字母表示 3 日期相等 4 乘积方案数 5 最大连通块 6 求星期几 7 范围覆盖点数 8 清理水草 9 滑行距离 10 序号最小值 1 找最小全为字母的16进制数 请找到一个
  • 数据结构和算法(栈的模拟、前中后缀表达式、表达式求值步骤和思路)

    1 栈的介绍 栈的英文为 stack 栈是一个先入后出 FILO First In Last Out 的有序列表 栈 stack 是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表 允许插入和删除的一端 为变化的一端 称
  • A*寻路算法 lua

    function InitMap self AMap for i 1 10 do self AMap i for j 1 10 do local map map x i map y j map g 999 map h 0 map f 0 m
  • 14-堆排序

    堆 Heap 是一种常见的数据结构 常用于存储数据 其本质上是一棵完全二叉树 下面我们来看看如何用数组实现堆结构及其相关功能 堆的定义 首先来看一下堆的存储结构 堆可以看成是一颗完全二叉树 首先什么是二叉树 借助百度中的解释 二叉树 bin
  • 数据结构和算法(2)-----队列

    一 基本介绍 队列是一个有序列表 可以用数组或链表来实现 遵循先入先出的原则 即先存入队列的数据 要先取出 后存入队列的数据 要后取出 示意图 二 数组模拟队列 思路 队列本身是有序列表 若使用数组的结构来存储队列的数据 则队列数组的声明如
  • 如何实现概率性事件

    游戏中经常会遇到概率性的问题 比如装备升级的成功率 合成宝石的成功率 洗装备时出现随机属性条数的概率等 这些概率性事件具体是怎么实现的呢 在网上看了一些相关的文章 总结一下 首先需要了解两个函数rand 和srand 下面是百科里面的解释
  • 数据结构和算法(查找算法[ 二分、插值 ]、哈希表构成、普通二叉树操作、线索化和遍历[ 前、中、后 ] 序)

    常用查找算法 顺序 线性 查找 二分查找 折半查找 插值查找 顺序查找 按照顺序 遍历数组 比对数字 如果找到 返回下标 由于比较简单 不再介绍 二分查找 二分查找思路分析 需要查找的数组必须是有序的 否则查找没有意义 二分查找代码实现 p
  • 详解八大排序算法-附动图和源码(插入,希尔,选择,堆排序,冒泡,快速,归并,计数)

    目录 一 排序的概念及应用 1 排序的概念 2 排序的应用 3 常用的排序算法 二 排序算法的实现 1 插入排序 1 1直接插入排序 1 2希尔排序 缩小增量排序 2 选择排序 2 1直接选择排序 2 2堆排序 3 比较排序 3 1冒泡排序
  • 数据结构和算法之插入排序

    一 插入排序 插入排序是一种简单直观的排序算法 它的原理是通过构建有序序列 对于未排序数据 在已排序序列中从后向前扫描 找到相应位置并插入 mermaid svg v2YbPqchr8qWCPvn font family trebuchet
  • (十三):图

    1 图的基本介绍 1 1为什么要有图 前面我们学到了线性表和树 线性表局限于直接前驱和一个直接后继结点的关系 树也只能有一个直接前驱也就是父节点 当我们需要多对多关系时候 就需要图 1 2图的举例说明 图是一种数据结构 其中结点可以具有零个
  • 哈希表查找——成功和不成功时的平均查找长度

    哈希表查找 成功和不成功时的平均查找长度 以下求解过程是按照 计算机统考的计算方法 不同的老师 教材在 处理冲突 上可能会有不同的方法 所以最主要的是掌握原理即可 对于考研的朋友最好掌握统考真题的解题方法 题目 例子 2010年全国硕士研究
  • 数据结构和算法(堆排序和哈夫曼树、哈夫曼编码、解码)

    堆排序 一般使用大顶堆升序排列 使用小顶堆降序排列 下图为代码测试的树 数组格式 堆降序代码实现 import java util Arrays public class HeapSort public static void main S
  • 二叉树的先序,中序,后序遍历

    java 二叉树的先序 中序 后序遍历 一 前序遍历 访问顺序 先根节点 再左子树 最后右子树 上图的访问结果为 GDAFEMHZ 1 递归实现 public void preOrderTraverse1 TreeNode root if
  • 数据结构和算法(4):栈与队列

    栈 ADT 及实现 栈 stack 是存放数据对象的一种特殊容器 其中的数据元素按线性的逻辑次序排列 故也可定义首 末元素 尽管栈结构也支持对象的插入和删除操作 但其操作的范围仅限于栈的某一特定端 也就是说 若约定新的元素只能从某一端插入其
  • 深入理解左倾红黑树 | 京东物流技术团队

    平衡二叉搜索树 平衡二叉搜索树 Balanced Binary Search Tree 的每个节点的左右子树高度差不超过 1 它可以在 O logn 时间复杂度内完成插入 查找和删除操作 最早被提出的自平衡二叉搜索树是 AVL 树 AVL

随机推荐

  • python语法--标识符(2)

    1 标识符 1 1定义 标识符即用户编程时自定义的名字 可以用来给变量 常量 函数等命名 以建立起名称与使用之间的关系 1 2命名规则 a 必须为字母数字下划线 且数字不能打头 b 严格区分大小写 c 不能使用关键字 但可以包含关键字 1
  • Tensorflow2.0 GPU版本安装(CUDA10.0 + cuDNN7.5 + Tensorflow2.0 Alpha)

    本人小白一名 总结了一些自己的操作经验 仅供参考 前段时间Tensorflow 2 0 Alpha版本发布 作为刚入门深度学习的小白之前没有学过 Tensorflow1 x 系列 只学过一些keras 也懒得再学习 Tensorflow1
  • SQLserver存储过程加密、解密

    SQLserver存储过程加密 解密 作者 邱名涛 撰写时间 2019 年 6 月 22 日 关键技术 数据库存储过程加密 解密 加密存储过程 判断表是否存在 如果存在就删除 if object id N dbo Test N U is n
  • SMALE 实验室投稿期刊选择

    摘要 本文档仅供 SMALE 实验室同学参考 这里的分区均按中科院标准 分区仅由当前的影响因子确定 而 CCF 分类则说明了长期的声誉 有些期刊是 CCF B 类 但落到三 四区 其实是不合理的 申请自然科学基金之类 小同行主要还是依据 C
  • java 等额本息计算方式

    投资理财 等额本息计算方式 以下按照10000元 以年利率15 5 投资期限为6个月 以等额本息方式偿还来计算 等额本息计算 public class PrincipalAndInterestEquals public static voi
  • echarts 地图类型热力图

    地图主要用于地理区域数据的可视化 配合 visualMap 组件用于展示不同区域的人口分布密度等数据 visualMap 是视觉映射组件 用于进行 视觉编码 也就是将数据映射到视觉元素 视觉通道 echarts 官网案例 https ech
  • Java项目样式规范checkstyle.xml

    具体项的具体说明请参考 https www cnblogs com ziyuyuyu p 9870717 html 梳理此次完整checkstyle xml说明 以备以后再此基础上删减
  • 网页抓取工具

    Teleport Ultra Teleport Ultra所能做的 不仅仅是 离线浏览某个网页 让你离线快速浏览某个网页的内容当然是它的一项重要功能 它可以从Internet的任何地方抓回你想要的任何文件 它可以在你指定的时间自动登录到你指
  • 开源麒麟Linux系统openKylin-1.0 内核是debian 安装openssh-server及配置root远程登陆

    原因 服务器安装完开源麒麟Linux系统openKylin 1 0后 换使用时的键鼠很烦 目标 Debian安装openssh server 原系统安装Xshell 并配置实现root远程登录 记录下并供大家参考 检查 apt search
  • 【传感器课程设计——DHT11温湿度数据上传阿里云】课程设计论文大纲

    1 摘要 摘要可以分为中文和英文两部分 2 概述 2 1 课程设计背景 2 2 国内外研究现状 2 3 报告组织形式 3 系统设计 3 1 设计目标 3 2 设计方案 3 3 设计方案分析 3 4 程序结构 4 硬件设计 4 1 ESP82
  • Authing 入选《2022年度中国高科技高成长企业》榜单

    近日 Authing 入选 2022 年度中国高科技高成长企业系列榜单 云原生高成长企业榜 该榜单由 第一新声 联合 天眼查 发起的 数字中国 系列之 2022 年度中国高科技高成长企业系列榜单发布 该榜单旨在发现和挖掘被资本市场关注 同时
  • 同方服务器系统安装,同方云服务器安装使用手册

    同方云服务器安装使用手册 内容精选 换一换 如果您已经创建了一台Linux云服务器 并根据业务需要进行了自定义配置 如安装软件 部署应用环境等 您可以为更新后的云服务器创建系统盘镜像 使用该镜像创建新的云服务器 会包含您已配置的自定义项 省
  • mysql常见函数使用

    时间操作 时间单位 unit MICROSECOND SECOND MINUTE HOUR DAY WEEK MONTH QUARTER YEAR SECOND MICROSECOND MINUTE MICROSECOND MINUTE S
  • 获得焦点除去class和失去焦点获得class

    html li class top relative tt huge 餐厅员工数 li
  • win7打不开chm

    1 打开chm2 win7提示安全问题3 chm无法显示内容4 关闭chm5 右键点击chm 点击 解除锁定 ok 没有 解除锁定 晕 请往下6 右键点击chm 点击 压缩到 rar 压缩chm7 双击生成的压缩文件 rar8 在rar中双
  • Windows NodeJS 二进制文件安装

    第一步下载node下载 Node js 中文网 本人系统Win10 X64 如图 将下载的zip包解压到你自定义的目录 尽量不要有空格或中文 你懂的 作者选择了d盘下自定义目录D datastorage下 解压后的文件目录如图所示 在此目录
  • 微信小程序中使用websocket

    实现多账号登录踢出效果 效果图 一 创建websocket监听方法 websocket js export const ws connect function id wx connectSocket 创建一个 WebSocket 连接 ur
  • 【探索AI潜能,连结现代通讯】相隔万里,我们与AI一同赏月。

    1 写在前面 近年来 AI得到了迅猛的发展 尤其是大模型的出现受到了广泛的关注和讨论 ChatGPT 文心一言等纷纷登场 可谓是百家争鸣 而AI大模型所延申出的子项目如AI绘画 AI写作等 在各自的领域展示出了惊人的潜力 最圆的月亮在中秋
  • Winform项目之学生成绩管理系统设计与实现(三)

    1 班级管理 private ClassService classService new ClassService public ListClassForm InitializeComponent this dgvListClass Row
  • 排序算法——交换排序(快排*)和归并排序

    上篇文章介绍了插入排序和选择排序 详见https mp csdn net postedit 97524495 3交换排序 所谓交换 就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置 交换排序的特点是 将键值较大的记 录向序