排序八卦炉之冒泡、快排【完整版】

文章目录

  • 1.冒泡排序
    • 1.1代码实现
    • 1.2复杂度
  • 2.快速排序
    • 2.1人物及思想介绍【源于百度】
    • 2.2hoare【霍尔】版本
      • 1.初识代码
      • 2.代码分析
      • 3.思其因果
    • 2.3挖坑版本
      • 1.初始代码
      • 2.代码分析
      • 3.思想比较
    • 2.4指针版本
      • 1.初识代码
      • 2.代码分析
      • 3.问题探讨
    • 2.5集体优化
    • 2.6极致优化
    • 2.7非递归版本
      • 1.初识代码
      • 2.代码分析
    • 2.8相关博客及完整代码

在这里插入图片描述

1.冒泡排序

在这里插入图片描述

1.1代码实现

//插入排序  O(N)~O(N^2)
//冒泡排序  O(N)~O(N^2)
//当数据有序 二者均为O(N)
//当数据接近有序或局部有序 插排更优
void BubbleSort(int* a, int n)
{assert(a);int flag = 1;for (int i = 0; flag && i < n - 1; ++i){flag = 0;for (int j = 0; j < n - 1 - i; ++j){if (a[j] > a[j + 1]){Swap(&a[j - 1], &a[j]);flag = 1;}}}
}

1.2复杂度

  1. 最坏:
    比较n-1轮
    每一轮比较次数:n n-1 n-2 n-3 … 1 ≈ N^2
  2. 最优:
    比较n-1轮
    数据有序–每一轮只判断不比较 – N

2.快速排序

2.1人物及思想介绍【源于百度】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.2hoare【霍尔】版本

1.初识代码

//霍尔版本
int PartSort1(int* a, int begin, int end)
{int left = begin, right = end, x = left;while (left < right){//右找小while (left < right && a[right] >= a[x])--right;//左找大while (left < right && a[left] <= a[x])++left;Swap(&a[left], &a[right]);}Swap(&a[x], &a[left]);x = left;return x;
}
void QuickSort(int* a, int begin, int end)    
{//begin:左区间左边界下标 //end  :右区间右边界下标//begin==end:数据量=1 无需排序 直接返回//begin>end :无效区间 无需排序 直接返回if (begin >= end)return;int x = PartSort1(a, begin, end);// [begin, x - 1] x [x + 1, end]QuickSort(a, begin, x - 1);QuickSort(a, x+1, end);
}

2.代码分析

在这里插入图片描述

3.思其因果

Q:为什么a[x]【作为基准值key】置于左侧 – 右边先移动?
A:目的是为了保证相遇位置的值<=key 从而把key与相遇值交换 不打乱“左放小,右放大”的思想
在这里插入图片描述

2.3挖坑版本

1.初始代码

//挖坑版本
int PartSort2(int* a, int begin, int end)
{int x = begin, key = a[begin];while (begin < end){while (begin < end && a[end] >= key)--end;a[x] = a[end];x = end;while (begin < end && a[begin] <= key)++begin;a[x] = a[begin];x = begin;}a[x] = key;return x;
}
void QuickSort(int* a, int begin, int end)    
{//begin:左区间左边界下标 //end  :右区间右边界下标//begin==end:数据量=1 无需排序 直接返回//begin>end :无效区间 无需排序 直接返回if (begin >= end)return;int x = PartSort1(a, begin, end);// [begin, x - 1] x [x + 1, end]QuickSort(a, begin, x - 1);QuickSort(a, x+1, end);
}

2.代码分析

在这里插入图片描述

3.思想比较

霍尔版本:右找小 左找打 大小交换 依次递归
挖坑版本:记录key值 x位–置空 右找小入坑 坑位更新 左找大入坑 坑位更新 依次递归

在这里插入图片描述

2.4指针版本

1.初识代码

int PartSort3(int* a, int begin, int end)
{   //prv:previous  cp:current pointerint prv = begin, cp = begin + 1, x = begin;while (cp <= end){if (a[cp] < a[x] && ++prv != cp)Swap(&a[prv], &a[cp]);++cp;}Swap(&a[prv], &a[x]);x = prv;return x;
}
void QuickSort(int* a, int begin, int end)    
{//begin:左区间左边界下标 //end  :右区间右边界下标//begin==end:数据量=1 无需排序 直接返回//begin>end :无效区间 无需排序 直接返回if (begin >= end)return;int x = PartSort3(a, begin, end);// [begin, x - 1] x [x + 1, end]QuickSort(a, begin, x - 1);QuickSort(a, x+1, end);
}

2.代码分析

在这里插入图片描述

3.问题探讨

在这里插入图片描述

2.5集体优化

//快速排序   O(N * logN)
//对任意区间三值取中位数
int GetMid_X(int* a, int begin, int end)
{int mid = (begin + end) / 2;if (a[begin] < a[mid]){if (a[mid] < a[end])return mid;else if (a[begin] < a[end])return end;elsereturn begin;}else //a[begin] >= a[mid]{if (a[mid] > a[end])return mid;else if (a[begin] < a[end])return begin;elsereturn end;}
}
//霍尔版本
int PartSort1(int* a, int begin, int end)
{int left = begin, right = end, x = left;//确定更合适的keyint mid_x = GetMid_X(a, begin, end);Swap(&a[x], &a[mid_x]);while (left < right){//右找小while (left < right && a[right] >= a[x])--right;//左找大while (left < right && a[left] <= a[x])++left;Swap(&a[left], &a[right]);}Swap(&a[x], &a[left]);x = left;return x;
}
//挖坑版本
int PartSort2(int* a, int begin, int end)
{int x = begin;//确定更合适的keyint mid_x = GetMid_X(a, begin, end);Swap(&a[x], &a[mid_x]); int key = a[x];while (begin < end){while (begin < end && a[end] >= key)--end;a[x] = a[end];x = end;while (begin < end && a[begin] <= key)++begin;a[x] = a[begin];x = begin;}a[x] = key;return x;
}  
//指针版本
int PartSort3(int* a, int begin, int end)
{   //prv:previous  cp:current pointerint prv = begin, cp = begin + 1, x = begin;//确定更合适的keyint mid_x = GetMid_X(a, begin, end);Swap(&a[x], &a[mid_x]);while (cp <= end){if (a[cp] < a[x] && ++prv != cp)Swap(&a[prv], &a[cp]);++cp;}Swap(&a[prv], &a[x]);x = prv;return x;
}
void QuickSort(int* a, int begin, int end)    
{//begin:左区间左边界下标 //end  :右区间右边界下标//begin==end:数据量=1 无需排序 直接返回//begin>end :无效区间 无需排序 直接返回if (begin >= end)return;int x = PartSort2(a, begin, end);// [begin, x - 1] x [x + 1, end]QuickSort(a, begin, x - 1);QuickSort(a, x+1, end);
}

2.6极致优化

在这里插入图片描述

在这里插入图片描述

2.7非递归版本

递归版本存在的问题:若递归层次太深 导致栈溢出问题
递归改非递归的方法:

  1. 直接改循环 – 斐波那契数列、归并排序等
  2. 数据结构的栈(Stack)模拟递归【Stack的空间是从堆申请的 堆内存比栈内存大】

1.初识代码

int PartSort3(int* a, int begin, int end)
{   //prv:previous  cp:current pointerint prv = begin, cp = begin + 1, x = begin;//确定更合适的keyint mid_x = GetMid_X(a, begin, end);Swap(&a[x], &a[mid_x]);while (cp <= end){if (a[cp] < a[x] && ++prv != cp)Swap(&a[prv], &a[cp]);++cp;}Swap(&a[prv], &a[x]);x = prv;return x;
}
void QuickSort_NonRecursion(int* a, int begin, int end)
{ST st;StackInit(&st);StackPush(&st, begin);StackPush(&st, end);while (!StackEmpty(&st)){int right = StackTop(&st);StackPop(&st);int left = StackTop(&st);StackPop(&st);int x = PartSort3(a, left, right);if (x + 1 < right){StackPush(&st, x + 1);StackPush(&st, right);}// [left, x-1] x [x+1, right]if (left < x - 1){StackPush(&st, left);StackPush(&st, x - 1);}}StackDestroy(&st);
}

2.代码分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.8相关博客及完整代码

点击 [qsort与bubble之间不为人知的关系](htt p://t.csdn.cn/filuW) 查看博主之前关于分析这两个排序的博客。

//快速排序   O(N * logN)
int count = 0;  //测试递归次数
//对任意区间三值取中位数
int GetMid_X(int* a, int begin, int end)
{int mid = (begin + end) / 2;if (a[begin] < a[mid]){if (a[mid] < a[end])return mid;else if (a[begin] < a[end])return end;elsereturn begin;}else //a[begin] >= a[mid]{if (a[mid] > a[end])return mid;else if (a[begin] < a[end])return begin;elsereturn end;}
}
//霍尔版本
int PartSort1(int* a, int begin, int end)
{int left = begin, right = end, x = left;//确定更合适的keyint mid_x = GetMid_X(a, begin, end);Swap(&a[x], &a[mid_x]);while (left < right){//右找小while (left < right && a[right] >= a[x])--right;//左找大while (left < right && a[left] <= a[x])++left;Swap(&a[left], &a[right]);}Swap(&a[x], &a[left]);x = left;return x;
}
//挖坑版本
int PartSort2(int* a, int begin, int end)
{int x = begin;//确定更合适的keyint mid_x = GetMid_X(a, begin, end);Swap(&a[x], &a[mid_x]); int key = a[x];while (begin < end){while (begin < end && a[end] >= key)--end;a[x] = a[end];x = end;while (begin < end && a[begin] <= key)++begin;a[x] = a[begin];x = begin;}a[x] = key;return x;
}  
//指针版本
int PartSort3(int* a, int begin, int end)
{   //prv:previous  cp:current pointerint prv = begin, cp = begin + 1, x = begin;//确定更合适的keyint mid_x = GetMid_X(a, begin, end);Swap(&a[x], &a[mid_x]);while (cp <= end){if (a[cp] < a[x] && ++prv != cp)Swap(&a[prv], &a[cp]);++cp;}Swap(&a[prv], &a[x]);x = prv;return x;
}void QuickSort(int* a, int begin, int end)
{count++;//begin:左区间左边界下标 //end  :右区间右边界下标//begin==end:数据量=1 无需排序 直接返回//begin>end :无效区间 无需排序 直接返回if (begin >= end)return;int x = PartSort3(a, begin, end);// [begin, x - 1] x [x + 1, end]QuickSort(a, begin, x - 1);QuickSort(a, x+1, end);
}/*
void QuickSort(int* a, int begin, int end)
{count++;if (begin >= end)return;if (end - begin > 10){int x = PartSort3(a, begin, end);// [begin, x-1] x [x+1, end]QuickSort(a, begin, x - 1);QuickSort(a, x + 1, end);}else InsertSort(a + begin, end - begin + 1);
}
*/
//非递归版本
void QuickSort_NonRecursion(int* a, int begin, int end)
{ST st;StackInit(&st);StackPush(&st, begin);StackPush(&st, end);while (!StackEmpty(&st)){int end = StackTop(&st);StackPop(&st);int begin = StackTop(&st);StackPop(&st);int x = PartSort3(a, begin, end);if (x + 1 < end){StackPush(&st, x + 1);StackPush(&st, end);}// [begin, x-1] x [x+1, end]if (begin < x - 1){StackPush(&st, begin);StackPush(&st, x - 1);}}StackDestroy(&st);
}

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

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

相关文章

sql语句字符函数,数学函数

一、trim&#xff08;&#xff09;去掉前后单元格 SELECT LENGTH(TRIM( 张三 )) AS 姓名 trim&#xff08;aa from bb) 除掉bb中前后包含的aa&#xff0c;中间的保留 SELECT TRIM(班 FROM class) AS 姓名 FROM user_test 二、lpad&#xff08;&#xff09;用指定字符做左…

【css】css实现一个简单的按钮

四种链接状态分别是&#xff1a; a:link - 正常的&#xff0c;未访问的链接a:visited - 用户访问过的链接a:hover - 用户将鼠标悬停在链接上时a:active - 链接被点击时 <style> a:link, a:visited {//未访问、访问过background-color: #07c160;//设置背景颜色color: wh…

Day10-NodeJS和NPM配置

Day10-NodeJS和NPM 一 Nodejs 1 简介 Nodejs学习中文网:https://www.nodeapp.cn/synopsis.html Nodejs的官网:https://nodejs.org/ 概念:Nodejs是JavaScript的服务端运行环境.Nodejs不是框架,也不是编程语言,就是一个运行环境. Nodejs是基于chrome V8引擎开发的一套js代码…

Toyota Programming Contest 2023#4(AtCoder Beginner Contest 311)D题题解

文章目录 [Grid Ice Floor](https://atcoder.jp/contests/abc311/tasks/abc311_d)问题建模问题分析1.分析移动时前后两个点之间的联系2.方法1通过BFS将所有按照给定运动方式可以到达的点都标记代码 3.方法2采用DFS来标记路径上的点的运动状态代码 Grid Ice Floor 问题建模 给定…

测试岗?从功能测试进阶自动化测试开发,测试之路不迷茫...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 测试新人在想什么…

IO进程线程day7(2023.8.4)

一、Xmind整理&#xff1a; 二、课上练习&#xff1a; 练习1&#xff1a;创建两个线程&#xff1a;其中一个线程拷贝前半部分&#xff0c;另一个线程拷贝后半部分。 只允许开一份资源&#xff0c;且用互斥锁方式实现。 提示&#xff1a;找临界区--->找临界资源。 #includ…

swagger相关问题

swagger相关问题 swagger版本为&#xff1a; <dependency><groupId>com.github.xiaoymin</groupId><artifactId>swagger-bootstrap-ui</artifactId><version>1.9.6</version> </dependency> <dependency><groupId&…

网络安全设备-等保一体机

本文为作者学习文章&#xff0c;按作者习惯写成&#xff0c;如有错误或需要追加内容请留言&#xff08;不喜勿喷&#xff09; 本文为追加文章&#xff0c;后期慢慢追加 等保一体机的功能 等保一体机产品主要依赖于其丰富的安全网元&#xff08;安全网元包括&#xff1a;防火…

sentinel组件

目录 定义 4.加SentinelResource,blockHander是超过阈值之后执行的函数 5.设置阈值 6.springboot集成sentinel 定义 1.sentinel知道当前流量大小&#xff0c;在浏览器和后端之间加sentinel控制流量&#xff0c;避免大批量的瞬时请求都达到服务上&#xff0c;将服务压垮 2.…

汉字姓名转拼音

import osimport pandas as pdfrom xpinyin import Pinyindownpath/Users/Kangyongqing/Downloads/ file1教师姓名转拼音.xlsxdtpd.read_excel(downpathfile1) print(dt.info()) dt[pinyin]dt[教师姓名].apply(lambda x:Pinyin().get_pinyin(x).split(-)[0].capitalize() .join…

linux的搭建以及网关配置

Linux 目前国内 Linux 更多的是应用于服务器上,而桌面操作系统更多使用的是 Windows 安装linux虚拟机 网址 VMware下载网址 点击Workstation 16 Pro for Windows下载 安装CentOS centO下载网址 依次点击 7.6.1810/ isos/ x86_64/ CentOS-7-x86_64-DVD-1810.…

Vue3 watch监听器

概览&#xff1a;watch监听器的定义以及使用场景。在vue3中的监听器的使用方式&#xff0c;watch的三个参数&#xff0c;以及进一步了解第一个参数可以是一个属性&#xff0c;也可以是一个数组的形式包含多个属性。 watch在vue3和vue2中的使用&#xff1a; vue3中&#xff1a…

uniapp-疫情应急管理系统学生端

1 疫情资讯展示 <template><view class"container"><uni-section title"自定义卡片内容" type"line"><uni-card title"基础卡片" class"card-box" v-for"(item,index) in epidemicNewsList"…

【MySQL】DQL语句

8&#xff0c;DQL 下面是黑马程序员展示试题库数据的页面 页面上展示的数据肯定是在数据库中的试题库表中进行存储&#xff0c;而我们需要将数据库中的数据查询出来并展示在页面给用户看。上图中的是最基本的查询效果&#xff0c;那么数据库其实是很多的&#xff0c;不可能在将…

Codeforces Round 881 (Div. 3)F1题解

文章目录 [Omsk Metro (simple version)](https://codeforces.com/contest/1843/problem/F1)问题分析1.分析如何知道根节点到某个结点的区间内是否存在一个子段和为k2.方法1使用树形DP来动态维护每个节点到根节点的最大子段和和最小子段和代码 Omsk Metro (simple version) 问题…

STM32使用HAL库中外设初始化MSP回调机制及中断回调机制详解

STM32使用HAL库之Msp回调函数 1.问题提出 在STM32的HAL库使用中&#xff0c;会发现库函数大都被设计成了一对&#xff1a; HAL_PPP/PPPP_Init HAL_PPP/PPPP_MspInit 而且HAL_PPP/PPPP_MspInit函数的defination前面还会有__weak关键字 上面的PPP/PPPP代表常见外设的名称为…

【css】使用float实现水平导航栏

该实例使用float 浮动实现元素浮动在水平方向&#xff0c;从而实现水平导航栏效果。 overflow: hidden&#xff1a;当不给父级元素设置高度的时候&#xff0c;其内部元素浮动后会导致下面的元素顶上去&#xff0c;这是因为子元素浮动后&#xff0c;子元素脱离标准流&#xff0…

组合总和——力扣39

文章目录 题目描述回溯 题目描述 回溯 class Solution { public:vector<vector<int>> res;vector<int> seq; void dfs(vector<int>& nums, int pos, int target){if(target0){res.emplace_back(seq);return;}if(posnums.size()){return;}//直接跳过…

uniapp 使用iconfont

问题描述&#xff1a;在开发过程中会遇到使用自定义icon的情况&#xff0c;在uniapp项目中使用iconfont步骤如下。 问题解决 步骤一&#xff1a; 打开iconfont网址------我的项目-----下载至本地 下载成功的文件内容&#xff1a; 步骤二&#xff1a; 以管理员身份运行终端&am…

Linux的基本指令(2)

指令1&#xff1a;man 作用&#xff1a;可以查询linux指令语法内容。 格式&#xff1a; man 指令 安装man指令&#xff1a; yum install -y man-pages 例如&#xff1a; 查询 指令 ls 的语法内容。 man ls 查询 fork 指令的语法内容。 man fork 在man中存在9个手册&…