当前位置: 首页 > news >正文

排序算法-----快速排序(非递归实现)

目录

前言

快速排序

 基本思路

 非递归代码实现

算法分析

空间复杂度

时间复杂度

稳定性


前言

        很久没跟新数据结构与算法这一栏了,因为数据结构与算法基本上都发布完了,哈哈,那今天我就把前面排序算法那一块的快速排序完善一下,前面只发布了快速排序递归算法,那这一次就去用非递归来去实现。(递归算法:排序算法-----快速排序(递归)_快排递归_Gretel Tade的博客-CSDN博客)

快速排序

 快速排序(Quicksort),计算机科学词汇,适用领域Pascal,C++等语言,是对冒泡排序算法的一种改进。

        快速排序采用的是分治思想,即在一个无序的序列中选取一个任意的基准元素pivot,利用pivot将待排序的序列分成两部分,前面部分元素均小于或等于基准元素,后面部分均大于或等于基准元素,然后采用递归的方法分别对前后两部分重复上述操作,直到将无序序列排列成有序序列。

 基本思路

现在给定一个数组初始 [25,24,6,65,11,43,22,51] ,然后进行快速排序

 第一步,先选取一个参考数字temp,一般选取第一个即temp=25,然后标记最左边和最右边数字的位置分别为i, j

 25        24        6        64        11        43        22        51

  i                                                                                 j

temp

 第二步,先去向左移动j 的位置,当j指向的数字小于temp时候,就停止移动,然后开始向右移动i 

当i 移动到比temp要大的数字时,停止移动,此时将i 和 j 指向的数字进行交换,如下所示:

 25        24        6        64        11        43        22        51

temp                             i                                   j

交换后:

 25        24        6        22        11        43        65       51

temp                             i                                   j

 第三步,此时,开始接着移动 j,当j 移动到比temp要小的数字的时候,停止移动, 如下所示:

 25        24        6        22        11        43        65       51

temp                             i           j

 然后开始移动i ,当i 移动到与j 相遇的位置时,i停止移动(如果i 移动到比temp要大的数字的时候就执行上面的第二步,i与j 进行数字交换)

 25        24        6        22        11        43        65       51

temp                                        i,j

第四步,此时,i与j指向的数字与temp指向的数字进行数字交换

 11        24        6        22        25        43        65       51

temp                                        i,j

这时候我们会发现,此时i和j指向的数字的位置,左边的都比这个数字要小,右边的都比这个数字要大,于是我们就可以去进入到递归,分别对左边和右边的数字进行以上步骤的递归,最后两边的数字都会被排好序。

动态图

 非递归代码实现

#include<stdio.h>
#include<stdlib.h>
//每一趟排序
int sort(int* arr, int left, int right) {int i = left;int j = right;int temp = arr[left];while (i != j) {while (temp <= arr[j] && i < j)//j左移j--;while (temp >= arr[i] && i < j)//i向右移i++;if (i < j) {//i与j都停止移动的时候,交换数字int t = arr[i];arr[i] = arr[j];arr[j] = t;}}//此时i与j相遇,进行数字交换arr[left] = arr[i];arr[i] = temp;return i;//返回这个交汇点
}void quick_sort(int* arr, int left, int right) {int* stack = (int*)malloc(sizeof(int) * right);//创建一个数组栈for (int i = 0; i < right; i++)stack[i] = -1;//初始化为-1int count = 0;//当前栈数据的个数if (left < right) {//入栈stack[count++] = left;stack[count++] = right;}while (count) {//当栈为非空的时候//出栈操作int r_pop = stack[count-1];int l_pop = stack[count-2];stack[count - 1] = stack[count - 2] = -1;//出栈后,清空已出栈数据,设置为-1count -= 2;int i = sort(arr, l_pop, r_pop);//如果这个交汇点前面数据的下标比当前最左边的数据下标要大的话,就入栈if (l_pop < i - 1) {stack[count++] = l_pop;stack[count++] = i - 1;}//如果这个交汇点后面一个数据的下标比当前最右边数据的下标要小的话,入栈if (r_pop > i + 1) {stack[count++] = i + 1;stack[count++] = r_pop;}}//释放空间free(stack);stack = NULL;
}int main() {int array[8] = { 25,24,6,65,11,43,22,51 };printf("排序前:");for (int i = 0; i < sizeof(array) / sizeof(int); i++) {printf("%d ", array[i]);}printf("\n排序后:");quick_sort(array, 0, sizeof(array) / sizeof(int) - 1);for (int i = 0; i < sizeof(array) / sizeof(int); i++) {printf("%d ", array[i]);}
}

运行结果:

算法分析

空间复杂度

快速排序算法没有涉及到空间的开辟,使用的空间是原数组空间,空间复杂度为O(1)

时间复杂度

快速排序之所以比较快,是因为与冒泡排序相比,每次的交换时跳跃式的,每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样整体交换次数和比较次数就少很多, 故排序速度就提高了许多,当然如果是最坏的情况下时间复杂度还是为O(n^2),其平均的时间复杂度为 O(nlog2​n)

稳定性

 俗话说得好:有得必有失。快速排序虽然排序速度快了很多,但是其缺牺牲了稳定性,当出现相同大小元素的时候,相同大小元素的相对位置会发生改变,每次递归都会发生变化,这就导致了快速排序的稳定性不好,这是因为快速排序改变了交换的规则,使用跳跃式交换,没有进行数字大小的一一比较,故快速排序是不稳定的,所以选择排序算法的时候要慎重选择,充分考虑到稳定性

以上就是本期的全部内容了,喜欢的话给个赞吧!

分享一张壁纸: 

相关文章:

  • 安卓开发之HTTP API服务接口设计(基于okhttp3请求)
  • uni-app小程序 swiper 分页器样式修改
  • cocos2dx ​​Animate3D(二)
  • 《微信小程序开发从入门到实战》学习二十五
  • Qt/QML编程学习之心得:一个Qt工程的学习笔记(九)
  • 2023-11-22 LeetCode每日一题(网格中的最小路径代价)
  • C#语言高阶开发
  • 药品一致性评价工作开展流程(常见问题40个)
  • 【自动驾驶】一些业内自动驾驶专业术语释义
  • C++编程——输入
  • JVM 之 class文件详解
  • 2023.11.24 海豚调度,postgres库使用
  • 智慧城市内涝积水监测仪功能,提升城市预防功能
  • 初识Linux(1),看了这篇文章,妈妈再也不用担心我Linux找不到门了。
  • 2个视频怎么做一个二维码?二维码展示多内容的方法
  • 《深入 React 技术栈》
  • CentOS 7 修改主机名
  • CSS 专业技巧
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • JavaScript创建对象的四种方式
  • php的插入排序,通过双层for循环
  • TypeScript实现数据结构(一)栈,队列,链表
  • vue.js框架原理浅析
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • vue学习系列(二)vue-cli
  • webpack+react项目初体验——记录我的webpack环境配置
  • 多线程事务回滚
  • 规范化安全开发 KOA 手脚架
  • 技术发展面试
  • 将回调地狱按在地上摩擦的Promise
  • 排序算法学习笔记
  • 判断客户端类型,Android,iOS,PC
  • 前端之Sass/Scss实战笔记
  • kubernetes资源对象--ingress
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • ​iOS安全加固方法及实现
  • (5)STL算法之复制
  • (ZT)一个美国文科博士的YardLife
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (回溯) LeetCode 131. 分割回文串
  • (九)信息融合方式简介
  • (三)SvelteKit教程:layout 文件
  • (四) Graphivz 颜色选择
  • (一)WLAN定义和基本架构转
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • .chm格式文件如何阅读
  • .h头文件 .lib动态链接库文件 .dll 动态链接库
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .Net 基于IIS部署blazor webassembly或WebApi
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .NET开源纪元:穿越封闭的迷雾,拥抱开放的星辰