《算法导论》学习笔记——快速排序

快速排序

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

  下面这张图显示了该过程。

201353493284961.png

  随着算法的执行,数组被划分为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。

201354207034113.png

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

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

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

相关文章

JavaTCP连接

输入输出操作 可以这样理解&#xff1a; BufferedReader/BufferedWriter使用三部曲&#xff1a; 服务器操作 import java.io.*; import java.net.ServerSocket; import java.net.Socket;public class Server {private static int port 8002;//设置端口号public static v…

JavaScript中的If和Else语句(香草)

Generally if statements have the following syntax: 通常&#xff0c; if语句具有以下语法&#xff1a; if(condition){Our code;}The condition, here can be anything from the mathematical expression, Boolean, relation operations etc. 条件&#xff0c;这里可以是数…

不创建 sequence 自增字段

drop table t_log;create table t_log (log_id number primary key,user_name varchar2(100),log_date date);--新建一个表&#xff0c;有id 用户名 和 日期字段create or replace trigger tri_logonafter logon on databasebegininsert into t_log values(nvl((select max(…

完整案例:实现延迟队列的两种方法

延迟队列是指把当前要做的事情,往后推迟一段时间再做。 延迟队列在实际工作中和面试中都比较常见,它的实现方式有很多种,然而每种实现方式也都有它的优缺点,接下来我们来看。 延迟队列的使用场景 延迟队列的常见使用场景有以下几种: 超过 30 分钟未支付的订单,将会被取…

Java API概述及应用

Java API概述及应用5.1_Scanner和Random的使用&#xff08;1&#xff09;Scanner&#xff08;2&#xff09;Random生成随机数5.2_ArrayList集合的使用&#xff08;1&#xff09;ArrayList的定义及限制&#xff08;2&#xff09;函数调用&#xff08;3&#xff09;字符串字符串加…

定位position详解:relative与absolute

定位标签&#xff1a;position 包含属性&#xff1a;relative&#xff08;相对&#xff09; absolute&#xff08;绝对&#xff09; 1.position:relative; 如果对一个元素进行相对定位&#xff0c;首先它将出现在它所在的位置上。然后通过设置垂直或水平位置&#xff0c;让这个…

实战:布隆过滤器安装与使用及原理分析

我们前面有讲到过 HyperLogLog 可以用来做基数统计,但它没提供判断一个值是否存在的查询方法,那我们如何才能查询一个值是否存在于海量数据之中呢? 如果使用传统的方式,例如 SQL 中的传统查询,因为数据量太多,查询效率又低有占用系统的资源,因此我们需要一个优秀的算法…

转:RMAN 备份与恢复 实例

转载自&#xff1a;http://blog.csdn.net/tianlesoftware/article/details/4699320 1. 检查数据库模式&#xff1a; sqlplus /nolog conn /as sysdba archive log list (查看数据库是否处于归档模式中) 若为非归档,则修改数据库归档模式。 startup mount alter…

有重复数字的组合问题_带数字重复的组合和问题

有重复数字的组合问题Description: 描述&#xff1a; This is a standard interview problem to make some combination of the numbers whose sum equals to a given number using backtracking. 这是一个标准的面试问题&#xff0c;它使用回溯功能将总和等于给定数字的数字进…

第四章语法分析和语法分析程序

第四章语法分析和语法分析程序4.1_自顶向下的语法分析4.1.1_自顶向下分析过程的基本特点①消除文法直接左递归②回溯的消除及LL(1)文法4.1.2_递归下降法4.1.3_预测分析法&#xff08;也叫LL1法&#xff0c;注意分析过程中非终结符号逆序入栈&#xff09;4.2_自底向上的语法分析…

实战:RediSearch 高性能的全文搜索引擎

RediSearch 是一个高性能的全文搜索引擎,它可以作为一个 Redis Module(扩展模块)运行在 Redis 服务器上。 RediSearch 主要特性如下: 基于文档的多个字段全文索引高性能增量索引文档排序(由用户在索引时手动提供)在子查询之间使用 AND 或 NOT 操作符的复杂布尔查询可选的…

智能优化算法应用:基于法医调查算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于法医调查算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于法医调查算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.法医调查算法4.实验参数设定5.算法结果6.…

转:Oracle物理文件

转载&#xff1a;http://www.worlduc.com/blog2012.aspx?bid19969111 -------------------初始化参数文件--------------------------------------------- 在9i之前&#xff0c;参数文件只有一种&#xff0c;它是文本格式的&#xff0c;称为pfile&#xff0c;在9i及以后的版本…

c语言两个浮点数相加_C语言中两个浮点数或双精度数的模数

c语言两个浮点数相加As we know that modules also known as the remainder of the two numbers can be found using the modulus (%) operator which is an arithmetic operator in C/C. The modules operator works with integer values i.e. modulus operator is used to fi…

java线程的5个使用技巧

Java线程的5个使用技巧 Published: 21 Jan 2015 Category: java Java线程有哪些不太为人所知的技巧与用法&#xff1f; 萝卜白菜各有所爱。像我就喜欢Java。学无止境&#xff0c;这也是我喜欢它的一个原因。日常工作中你所用到的工具&#xff0c;通常都有些你从来没有了解过的东…

算法复习第五章贪心法

算法复习第五章贪心法概述TSP最近邻点策略最短连接策略图着色问题最小生成树&#xff08;Prim算法、Kruskal&#xff09;0-1bag问题活动安排问题多机调度概述 TSP 最近邻点策略 最短连接策略 图着色问题 最小生成树&#xff08;Prim算法、Kruskal&#xff09; 0-1bag问题 活动…

实战:定时任务案例

我在开发的时候曾经遇到了这样一个问题,产品要求给每个在线预约看病的患者,距离预约时间的前一天发送一条提醒推送,以防止患者错过看病的时间。这个时候就要求我们给每个人设置一个定时任务,用前面文章说的延迟队列也可以实现,但延迟队列的实现方式需要开启一个无限循环任…

c语言putchar函数_C语言中的putchar()函数与示例

c语言putchar函数C语言中的putchar()函数 (putchar() function in C) The putchar() function is defined in the <stdio.h> header file. putchar()函数在<stdio.h>头文件中定义。 Prototype: 原型&#xff1a; int putchar(const char *string);Parameters: co…

算法复习第六章第七章

算法复习第六章第七章第六章回溯法TSP问题0-1bag问题图着色问题八皇后问题第七章分支限界法0-1bag问题TSP问题第六章回溯法 TSP问题 0-1bag问题 图着色问题 八皇后问题 第七章分支限界法 0-1bag问题 TSP问题

扫描识别系统

扫描识别系统&#xff0c;是指能够利用扫描仪进行扫描的相关文件&#xff0c;比方普通文档&#xff0c;政府公文&#xff0c;二代身份证&#xff0c;条码……等等。通过扫描仪扫描后不单单生成常见的JPG&#xff0c;PDF等格式的图像。而是利用先进的OCR技术&#xff0c;进行相关…