[数据结构]快速排序
一、问题描述
内部排序是一件具有重大意义的问题,许多项目的实现中都需要用到排序。
我们知道,排序的算法有许多种,每种排序算法的时间复杂度和空间复杂度不尽相同。在解决实际问题时,往往需要根据实际需要选择排序算法。
上次实验已经讨论了希尔排序的实现及其原理,本实验重点介绍另一种排序算法——快速排序。实验中将讨论快速排序的实现及其原理。
二、数据结构——顺序结构
本实验重点在算法实现上,数据结构的思想被弱化了。在排序过程中,由于维护序关系的需要,要有交换的操作,这就破坏了ADT的物理位置的相邻反映逻辑的依次的性质,可以说这里的顺序结构只是一个二次结构。因此,本实验不对此作过多说明。
三、算法的设计和实现
1、算法描述
快速排序是一种基于比较的排序算法,算法是不稳定的。有一种形象的叫法是“挖坑+分治”排序来形容快速排序。以下简要说明其操作。
以不降序排序为例。选择序列中一个元素作为基准元素,本实验中选择的是序列区间的第一个元素。定义两个指针(这里的指针只是一个意指,不一定用c++语言中真正的指针来实现,可以是一个整型数)i和j,初始时分别指向待排序列区间的首、尾。
每一轮排序时,选择第一个元素作为基准元素,相当于在序列区间的第一个位置挖了一个坑,现在要填坑。移动j,直到Elem[j]比基准元素小,将Elem[j]挖出来填到第一个位置,这时坑就是j这个位置了;移动i,知道Elem[i]比基准元素大,将Elem[i]挖出来填到j位置,这时坑就是i这个位置了。重复上述挖坑、填坑的操作,直到i == j,结束循环。此时,将基准元素填入当前的坑里,于是在该基准元素的左侧的元素都比它小,右侧的都比它大。这时就出现了一个自相似的子结构,于是很自然地选择递归,将当前的待排序序列区间以基准元素的位置一分为二,分别重复上述过程。递归的边界是当前区间只有一个元素,平凡有序。
所谓“挖坑”上面已经提到了,所谓“分治”就是指的区间一分为二的递归过程。
2、算法复杂度分析
快速排序的时间主要耗费在划分操作上,设当前待排序区间长度为k,则共需要k-1次关键字的比较。
最坏情况是每次划分选取的基准元素都是当前区间的最小(或者最大)元素,那么划分的结果将是左边的子区间(或者右边的子区间)为空,而右边的子区间(或者左边的子区间)长度为k-1,仅比之前少一个元素。此时的时间复杂度为O(n^2)。
最好情况是每次划分选取的基准元素都正好是当前区间的中位数,划分的结果是左、右子区间元素个数大致相等,总的复杂度为O(n lgn)。
尽管快速排序的最坏情况复杂度逼近平方级别,但就平均性能而言,它是基于关键字比较的内部排序算法中速度最快的(这个网上有许多算法的时间测试,这里不再赘述),它的平均时间复杂度为O(n lgn)。
3、例子
(1)第一轮
基准元素下标 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
72 | 72 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 48 | 85 |
48 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 48 | 85 | |
48 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 88 | 85 | |
48 | 6 | 57 | 42 | 60 | 42 | 83 | 73 | 88 | 85 | |
48 | 6 | 57 | 42 | 60 | 72 | 83 | 73 | 88 | 85 |
(2)第二轮
a)区间[1,5]
基准元素下标 | 1 | 2 | 3 | 4 | 5 |
48 | 48 | 6 | 57 | 42 | 60 |
42 | 6 | 57 | 42 | 60 | |
42 | 6 | 57 | 57 | 60 | |
42 | 6 | 48 | 57 | 60 |
b)区间[7,10]
基准元素下标 | 7 | 8 | 9 | 10 |
83 | 83 | 73 | 88 | 85 |
73 | 73 | 88 | 85 | |
73 | 83 | 88 | 85 |
c)总的序列
42 | 6 | 48 | 57 | 60 | 72 | 73 | 83 | 88 | 85 |
(3)第三轮
a)区间[1,2]
基准元素下标 | 1 | 2 |
42 | 42 | 6 |
6 | 6 | |
6 | 42 |
b)区间[4,5]
基准元素下标 | 4 | 5 |
57 | 57 | 60 |
57 | 60 |
c)区间[7,7],直接返回
d)区间[9,10]
基准元素下标 | 9 | 10 |
88 | 88 | 85 |
85 | 85 | |
85 | 88 |
e)总的序列
6 | 42 | 48 | 57 | 60 | 72 | 73 | 83 | 85 | 88 |
排序完成
四、预期结果和实验中的问题
1、预期结果
程序能够正确地将一个序列按照不递减的顺序排序。下图为一个例子。
2、实验中的问题及思考
快速排序还有一些改进的版本,当然比较常见的是在选择基准元素的时候采用随机选择的方式。据研究表明,选择黄金分割点处的数作为基准元素的期望速度最快,这个我还没有仔细学习过。
附:c++源代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 #define MaxN 120 7 8 int gap[200]; //步长 2^k+1 第一项改为1 9 int n; 10 11 template <class T> class My_list 12 { 13 private: 14 T Elem[MaxN]; //待排序的元素 15 int Len; //元素个数 16 public: 17 void Init() 18 { 19 memset(Elem, 0, sizeof(Elem)); 20 Len = 0; 21 } 22 void Insert_back(T x) 23 { 24 Elem[++Len] = x; 25 } 26 void Print() 27 { 28 int i; 29 for(i = 1; i < Len; i++) 30 printf("%d ", Elem[i]); 31 printf("%d\n", Elem[i]); 32 } 33 int GetLen() 34 { 35 return Len; 36 } 37 void QuickSort(int st, int ed) 38 { 39 if(st < ed) 40 { 41 int i = st, j = ed, x = Elem[st]; 42 while(i < j) 43 { 44 while(i < j && Elem[j] > x) //找右侧比x大的元素 45 j--; 46 if(i < j) 47 Elem[i++] = Elem[j]; 48 while(i < j && Elem[i] < x) //找左侧比x小的元素 49 i++; 50 if(i < j) 51 Elem[j--] = Elem[i]; 52 } 53 Elem[i] = x; 54 QuickSort(st, i - 1); //分治左侧区间 55 QuickSort(i + 1, ed); //分治右侧区间 56 } //if 57 } 58 }; 59 60 void Read(My_list <int> &L) 61 { 62 int i, x; 63 L.Init(); 64 printf("请输入需要排序的数的个数。\n"); 65 scanf("%d", &n); 66 printf("请输入需要排序的数列。\n"); 67 for(i = 1; i <= n; i++) 68 { 69 scanf("%d", &x); 70 L.Insert_back(x); //把x插入到最后 71 } 72 } 73 74 int main() 75 { 76 int GapNum; 77 My_list <int> L; 78 Read(L); 79 L.QuickSort(1, n); 80 printf("升序排序后的数列:\n"); 81 L.Print(); 82 return 0; 83 }
View Code
转载于:https://www.cnblogs.com/CQBZOIer-zyy/p/5185409.html
[数据结构]快速排序相关推荐
- 数据结构----快速排序
数据结构----快速排序 原理:参考趣学数据结构 代码: #include<stdio.h> #include<stdlib.h> int quickSort(int a[], ...
- 用数据结构c语言写成绩排序,C语言数据结构 快速排序实例详解
C语言数据结构 快速排序实例详解 一.快速排序简介 快速排序采用分治的思想,第一趟先将一串数字分为两部分,第一部分的数值都比第二部分要小,然后按照这种方法,依次对两边的数据进行排序. 二.代码实现 # ...
- 数据结构——快速排序
系列文章:数据结构与算法系列--从菜鸟到入门 描述 快速排序是基于分治模式的,下面按分治模式来进行分析: 分解: 数组 A[p..r]被划分成两个(可能空)子数组,A[p..q-1]和 A[q+1.. ...
- 数据结构 快速排序的三种实现 (hoare版本 挖坑法 前后指针版本)与非递归实现
快速排序 hoare版本 挖坑法 前后指针版本 非递归实现快速排序 快速排序:快速排序算法通过多次比较和交换来实现排序 基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另 ...
- 数据结构--快速排序
快速排序是效率比较高的一种排序算法,其思想主要是递归 package mainimport "fmt"func QuickSort(left int, right int, arr ...
- python算法与数据结构-快速排序算法
设定一个中间值,如下所示: low从开始位置找low是找比54小的,26比54小合格 high是从末尾位置找比54大的,如下所示: low和high重合后第一轮循环结束 第一轮递归后的结果如下所示: ...
- python算法与数据结构-快速排序算法(36)
阅读目录 一.快速排序的介绍 二.快速排序的原理 三.快速排序的步骤 四.快速排序的图解 五.快速排序的python代码实现 六.快速排序的C言语代码实现 七.快速排序的时间复杂度 八.快速排序的稳定 ...
- 数据结构 快速排序(详解)
快速排序 1:快速排序的思想 快速排序运用了分治的思想,即通过一趟排序 将序列分为两部分,根据选取的基准, 将比基准小的数放在基准前面,将比基准大的数放在的数放在基准后面:然后对两部分进行递归处理,以 ...
- 重学数据结构——快速排序,二分法查找
每次提起快排,内心中都有点隐隐作痛. 当时腾讯的那个面试官让我写快排的前两遍排序结果,结果,我当时居然没写上来-- 这个,就是所谓的关键时刻掉链子吧,这么经典的快排都不会,真是丢死人了-- 今天在实验 ...
最新文章
- 初识CISCO_DHCP Server
- OSPF Router-ID的选择
- java多线程 ThreadPoolExecutor 策略的坑
- apache2怎么知道从哪个默认文件夹下去查找网页
- 深入new/delete:Operator new的全局重载
- nacos配置ap_Nacos 1.0.0 功能预览
- Linux下的TCP/IP编程----IO复用及IO复用服务端
- 计算机英语一级考试试题,全国计算机一级考试试题及答案
- 解决Error: That port is already in use.
- 运动目标检测单高斯背景建模
- JavaScript高级程序设计读书笔记(第5章引用类型之Array类型)
- Linux内存管理之mmap
- 超详细的Python实现百度云盘模拟登陆(模拟登陆进阶)
- 云计算怎么学?学习云计算有什么用?
- FLASH连连看算法分析及源代码
- 反向延长线段什么意思_《反向延长线》
- 云栖大会人脸识别闸机【技术亮点篇4】--户外闸机高20%的抗撞击能力
- 360校招笔试题总结3
- 联想笔记本查看电池寿命、近期用电情况和续航估计报告
- 闲置硬盘自制nas私有云_旧笔记本电脑diy nas私有云
热门文章
- 在python语言中下列是二进制整数_Python从菜鸟到高手(5):数字
- re.search中与正则表达式*结合使用的注意事项
- mysql大表join小表速度很慢_mysql多表join中,为什么子查询会那么慢,怎么解决-问答-阿里云开发者社区-阿里云...
- php调用应用程序api,使用PHP调用openAPI
- 信息安全与网络安全,你分清了吗?
- redis.conf 配置项说明
- Nginx映射本地静态资源时,浏览器提示跨域问题解决
- Angular中调用css3动画实现侧边栏的显示与隐藏
- Winform中双击DevExpress的TreeList的树形节点怎样获取当前节点
- Python中通过MyQR生成gif动图二维码