《算法导论》学习笔记——快速排序
快速排序
1.快速排序原理
快速排序是一种应用很广泛的排序算法,与归并排序类似,快速排序也采用了分治策略。对于一个待排序的数组A[p...r]进行快速排序,根据分治思想,可以分为如下三个步骤:
- 分解:数组A[p...r]被划分为两个(有可能为空)子数组A[p...q-1]和A[q+1...r],使得A[p...q-1]中的每一个元素都小于等于A[q],而A[q]也小于等于A[q+1...r]中的每一个元素。其中,计算下标q也是划分过程的一部分。
-解决:通过递归调用快速排序,对子数组A[p...q-1]和A[q+1...r]进行快速排序。
-合并:注意到与归并排序不同,快速排序算法中的子数组都是基于原址排序的,所以不需要合并操作,即数组A[p...r]已经排好了顺序。
对于快速排序来说,算法的关键是找到正确的划分q,该过程的伪代码如下:
PARATITION(A, p, r)x = A[r]i = p - 1for j = p to r - 1if A[j] <= A[r]i = i + 1exchange A[i] with A[j]exchange A[i + 1] with A[r]return i + 1
下面这张图显示了该过程。
随着算法的执行,数组被划分为4个(可能为空)区域,如下图所示:
1. 若p <= k <= i,则A[k] <= x;
2. 若i+1 <= k <= j-1,则 A[k] >x;
3. 若j < k < r,则A[k]与x的大小关系不明确;
4. 若k = r,则A[k] = r。
2.快速排序的性能
根据上面的分析,快速排序的运行时间依赖于对待排序数组A[p...r]的划分是否平衡,而是否划分平衡依赖于划分元素的选取,如果划分是平衡的,那么快速排序算法性能与归并排序一样;如果划分不平衡,那么快速排序的性能就接近于插入排序了,注意这里是接近,而不是相等!
结论:平均情况下,快速排序的时间复杂度与最好划分情况下数量级一致,均为O(nlogn),注意这里是数量级一致并不意味着时间复杂度相等!
3.快速排序的随机化版本
上述的快速排序在讨论平均性能时我们假设输入数据的所有排列都是等概的。但实际情况可能并非如此,有可能出现元素大小分布极不均衡的情况。可以采用一种称为随机抽样(random sampling)的随机化技术,使主元A[r]是一个随机抽取于数组中的元素,因为主元元素是随机抽取的,我们期望在平均情况下,对输入数组的划分是比较均衡的。采取这样的操作只需要在原来的算法上改动很小的部分即可,伪代码如下:
RANDOMIZED-PARTITION(A, p, r)i = RANDOM(p, r)exchange A[r] with A[i]return PARATITION(A, p, r)
4.代码实现(C/C++,Java,Python)
实现了快速排序最基本算法,没有考虑随机化版本=。=
C
#include <stdio.h>
#include <stdlib.h>void swap(int* a, int* b) {int tmp;tmp = *a;*a = *b;*b = tmp;
}int partition(int* array, int low, int high) {int mid, index;mid = low - 1;for(index = low; index < high; index++){if(array[index] <= array[high]) {mid += 1;swap(&array[mid], &array[index]);}}swap(&array[mid + 1], &array[high]);return mid + 1;
}void quicksort(int* array, int low, int high) {int mid;if(low < high){mid = partition(array, low, high);quicksort(array, low, mid - 1);quicksort(array, mid + 1, high);}
}int main() {int *array, length, i;printf("Enter the length of array: ");scanf("%d", &length);array = (int* )malloc(length * sizeof(int));for(i = 0; i < length; i++)scanf("%d", &array[i]);quicksort(array, 0, length - 1);for(i = 0; i< length; i++)printf("%d ", array[i]);free(array);return 0;
}
C++
#include <iostream>
#include <vector>
using namespace std;void swap(int* a, int* b) {int tmp;tmp = *a;*a = *b;*b = tmp;
}int partition(vector<int> &array, int low, int high) {int mid, index;mid = low - 1;for(index = low; index < high; index++){if(array[index] <= array[high]) {mid += 1;swap(&array[mid], &array[index]);}}swap(&array[mid + 1], &array[high]);return mid + 1;
}void quicksort(vector<int> &array, int low, int high) {int mid;if(low < high){mid = partition(array, low, high);quicksort(array, low, mid - 1);quicksort(array, mid + 1, high);}
}int main() {vector<int> array;int length, element;cout << "Enter the length of array: ";cin >> length;cout << "Enter the element of array: ";for(int i = 0; i < length; i++){cin >> element;array.push_back(element);}quicksort(array, 0, length - 1);for(int i = 0; i< length; i++)cout << array[i] << " ";return 0;
}
Java
import java.util.*;public class QuickSort {public static void display(Iterator<Integer> it) {while(it.hasNext()) {Integer element = it.next();System.out.print(element + " ");}}public static void main(String[] args) {ArrayList<Integer> array = new ArrayList<Integer>();Scanner in = new Scanner(System.in);System.out.print("Enter the length of array: ");int length = in.nextInt();System.out.print("Enter the element of array: ");for(int i = 0; i < length; i++)array.add(in.nextInt());in.close();Sort sort = new Sort(array);sort.quickSort(sort.getLow(), sort.getHigh());display(array.iterator());}
}class Sort {public Sort(ArrayList<Integer> array) {this.array = array;}public int getLow() {return 0;}public int getHigh() {return array.size() - 1;}public void quickSort(int low, int high) {int mid;if(low < high) {mid = partition(low, high);quickSort(low, mid - 1);quickSort(mid + 1, high);}}public int partition(int low, int high) {int index = low - 1;for(int i = low; i < high; i++) {if(array.get(i) <= array.get(high)) {index += 1;int[] list = swap(array.get(index), array.get(i));array.set(index, list[0]);array.set(i, list[1]);}}int[] list = swap(array.get(index + 1), array.get(high));array.set(index + 1, list[0]);array.set(high, list[1]);return index + 1;}public int[] swap(int a, int b) {int[] list = new int[2];list[0] = b;list[1] = a;return list;}private ArrayList<Integer> array;
}
Python
quickSort.py
def swap(A, i, j):tmp = A[j]A[j] = A[i]A[i] = tmpdef partition(A, low, high):mid = low - 1for i in range(low, high):if A[i] <= A[high]:mid += 1swap(A, mid, i)swap(A, mid + 1, high)return mid + 1def quickSort(A, low, high):if low < high:mid = partition(A, low, high)quickSort(A, low, mid - 1)quickSort(A, mid + 1, high)
test.py
import quickSortA = [8, 7, 3, 0, 5, 4, 2, 9, 6, 1, 4]
quickSort.quickSort(A, 0, len(A) - 1)
print A
转载于:https://www.cnblogs.com/zhxbao/p/quick_sort.html
《算法导论》学习笔记——快速排序相关推荐
- 算法导论中C语言代码,算法导论-学习笔记与进度
算法导论 阅读进度 第一部分 基础知识 第一章 计算中算法的角色 Done 1.1 算法 输入与输出 算法可以解决哪些问题 数据结构 技术 一些比较难的问题 1.2 作为一种技术的算法 效率 算法和其 ...
- 算法导论学习笔记 第7章 快速排序
对于包含n个数的输入数组来说,快速排序是一种时间复杂度为O(n^2)的排序算法.虽然最环情况的复杂度高,但是快速排序通常是实际应用排序中最好的选择,因为快排的平均性能非常好:它的期望复杂度是O(nlg ...
- 【算法导论学习笔记】第3章:函数的增长
原创博客,转载请注明: http://www.cnblogs.com/wuwenyan/p/4982713.html 当算法的输入n非常大的时候,对于算法复杂度的分析就显得尤为重要,虽然有时我们能通 ...
- 算法导论学习笔记 第6章 堆排序
在本章中介绍了另一种排序算法:堆排序(heapsort).与归排序一样,但不同于插入排序的是,堆排序的时间复杂度式(Onlgn).而与插入排序相同,但不同于归并排序的是,堆排序同样具有空间原址性(我理 ...
- 算法导论学习笔记 第2章 算法基础
本章介绍了一个贯穿本书的框架,后续的算法设计都是在这个框架中进行的. 本章通过插入排序和归并排序两种常见的算法来说明算法的过程及算法分析,在分析插入排序算法时,书中是用了循环不变式证明了算法的正确性, ...
- 【转】算法导论学习笔记 一 分治算法
分治策略是一种常见的算法.在分治策略中,我们递归的求解一个问题,在每层递归中应用如下三个步骤: 1. 分解,将问题分解成规模更小但解决方案相同的子问题 2. 解决,递归的求解子问题,如果子问题足够小则 ...
- 算法导论学习笔记1_循环不变式
循环不变式 1. 循环不变式和数学归纳法 2. 循环不变式的三条性质 3. 利用循环不变式分析插入排序 4. 练习题 2.1.3 1. 循环不变式和数学归纳法 在数学中,数学归纳法常用于证明给定命题在 ...
- 算法导论学习笔记 6.5 优先队列
优先队列(priority queue)是一种用来维护由一组元素构成的集合S的数据结构,其中的每一个元素都有一个相关的值,称为关键字(key).一个最大优先队列支持一下操作: INSERT(S, x) ...
- 生日悖论问题——《算法导论学习笔记》
1 生日悖论问题 1.1 原始问题 一个房间里的人数必须达到多少,才能使两个人生日相同的机会达到50%?不考虑闰年情况,也就是一年按照365天来计算. 解答: 假设房间里的人数是k,我 ...
- 算法导论读书笔记(7)
算法导论读书笔记(7) 目录 快速排序 快速排序的简单Java实现 快速排序的性能 最坏情况划分 最佳情况划分 快速排序的随机化版本 比较排序 快速排序 快速排序是一种原地排序算法,对包含 n 个数的 ...
最新文章
- 【转】对random_state参数的理解
- php自动断词,PHP自动分页、防止英文单词被截段、去除HTML代码
- 一次zabbix的渗透
- Get和Post的参数传值
- python面向编程:类继承、继承案例、单继承下属性查找、super方法
- 多核编程文章汇总[z]
- Tomcat7实现Servlet3异步请求
- e1载波把32个信道按_什么是Wi-Fi 6?这12个问题为你讲清楚
- checkbox是否被选中
- 计算机图形学完整笔记(四):消隐
- 15日精读掌握《高德纳:具体数学》计划完成报告
- 如何修复老照片,Bringing-Old-Photos-Back-to-Life机器学习开源项目安装使用 | 机器学习
- shiro中anon配置不生效
- Magento后台产品列表添加自定义属性
- Linux 系统调用的本质
- stanford-corenlp 中各词性含义标注
- POP3协议,SMPT协议,IAMP协议介绍:
- Unity3D中如何制作天空盒
- 21届毕业生毕业一年内的状态
- 3.1 ElasticSearch River插件开发
热门文章
- php mysql bootstart_PHP MySQL 创建数据库
- 平板的android版本是5.0.2,EMUI5.0荣耀平板2升级固件下载
- 湖南省普通高等学校计算机应用水平,湖南省普通高等学校非计算机专业学生计算机应用水平二级考试大纲...
- 复杂电网三相短路计算的matlab仿真,复杂电网三相短路计算的MATLAB仿真电力系统分析课设报告 - 图文...
- c语言程序设计算机基础知识,2018春C语言程序设计(合肥工业大学)
- linux es数据库 head,elasticsearch安装es-sql插件
- 判断是否有小数_一线老师笔记:数学判断题拿高分的技巧
- 没数据时y轴不显示_Matplotlib数据可视化
- 操作系统页面置换算法(opt,lru,fifo,clock)实现
- 关于gedit的编码问题