JAVA数据结构--快速排序
快排概念
快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),一种排序算法,最早由东尼·霍尔提出。在平均状况下,排序
个项目要
(大O符号)次比较。在最坏状况下则需要
次比较,但这种状况并不常见。事实上,快速排序通常明显比其他
算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。
实现思想
快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。
步骤为:
- 从数列中挑出一个元素,称为"基准"(pivot),
- 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
借用下啊哈算法的图:
i和j分别为左哨兵和右哨兵,这里枢纽元定为6,然后分别从左往右(i++)和右往左(j--)开始遍历
左哨兵查找比6大的元素,右哨兵查找比6小的元素
第一次交换结果
第二次交换结果
相遇后直接与枢纽元交换
然后再递归排序就行
快排核心算法代码
public static <T extends Comparable<? super T>> void quicksort(T[] a,int left,int right) {
/*
* 当数组不小于3时,才推荐使用快排
* */
if(left+CUTOFF<=right)
{
//取出枢纽元,枢纽元的位置为right-1
T privot=median3(a, left, right); int i=left,j=right-1;
for(;;)
{
while(a[++i].compareTo(privot)<0) {}//i哨兵向右遍历
while(a[--j].compareTo(privot)>0) {}//j哨兵向左遍历
if(i<j)
swapReferences(a, i, j);
else
break;
}
/*
* for循环终止条件为i和j相遇,此时再将枢纽元归位
* */
swapReferences(a, i, right-1); quicksort(a, left, i-1);//对左半部进行递归
quicksort(a, i+1, right);//对右半部进行递归
}
else
{}
}
全部代码实现
public class MyQuickSort {
private static final int CUTOFF=3;
public static <T extends Comparable<? super T>> void quicksort(T[] a) {
quicksort(a,0,a.length-1);
}
public static <T extends Comparable<? super T>> void quicksort(T[] a,int left,int right) {
/*
* 当数组不小于3时,才推荐使用快排
* */
if(left+CUTOFF<=right)
{
//取出枢纽元,枢纽元的位置为right-1
T privot=median3(a, left, right); int i=left,j=right-1;
for(;;)
{
while(a[++i].compareTo(privot)<0) {}//i哨兵向右遍历
while(a[--j].compareTo(privot)>0) {}//j哨兵向左遍历
if(i<j)
swapReferences(a, i, j);
else
break;
}
/*
* for循环终止条件为i和j相遇,此时再将枢纽元归位
* */
swapReferences(a, i, right-1); quicksort(a, left, i-1);//对左半部进行递归
quicksort(a, i+1, right);//对右半部进行递归
}
else
{}
}
/*
* 数组中数值交换
* */
public static <T> void swapReferences(T[] a,int index1,int index2) {
T tmp=a[index1];
a[index1]=a[index2];
a[index2]=tmp;
}
/*
* 确定枢纽元,枢纽元的位置放在right-1位置
* */
private static <T extends Comparable<? super T>> T median3(T[] a,int left,int right) {
int center=(left+right)/2;
if(a[center].compareTo(a[left])<0)
swapReferences(a, left, center);
if(a[right].compareTo(a[center])<0)
swapReferences(a, center, right);
if(a[right].compareTo(a[left])<0)
swapReferences(a, left, right); swapReferences(a, center, right-1);
return a[right-1];
}
}
JAVA数据结构--快速排序的更多相关文章
- Java数据结构和算法(五)--希尔排序和快速排序
在前面复习了三个简单排序Java数据结构和算法(三)--三大排序--冒泡.选择.插入排序,属于算法的基础,但是效率是偏低的,所以现在 学习高级排序 插入排序存在的问题: 插入排序在逻辑把数据分为两部分 ...
- Java数据结构之树和二叉树(2)
从这里始将要继续进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来 ...
- Java数据结构和算法(九)——高级排序
春晚好看吗?不存在的!!! 在Java数据结构和算法(三)——冒泡.选择.插入排序算法中我们介绍了三种简单的排序算法,它们的时间复杂度大O表示法都是O(N2),如果数据量少,我们还能忍受,但是数据量大 ...
- Java数据结构和算法 - 堆
堆的介绍 Q: 什么是堆? A: 这里的“堆”是指一种特殊的二叉树,不要和Java.C/C++等编程语言里的“堆”混淆,后者指的是程序员用new能得到的计算机内存的可用部分 A: 堆是有如下特点的二叉 ...
- Java数据结构和算法 - 高级排序
希尔排序 Q: 什么是希尔排序? A: 希尔排序因计算机科学家Donald L.Shell而得名,他在1959年发现了希尔排序算法. A: 希尔排序基于插入排序,但是增加了一个新的特性,大大地提高了插 ...
- Java数据结构与算法 - 外部存储
Q: 什么是外部存储? A: 外部存储特指某类磁盘系统,例如在大多数台式电脑或服务器中的硬盘. Q: 如何访问外部存储? A: 我们所学的数据结构都是假设数据存储在内存中,但是,在很多情况下要处理的数 ...
- Java数据结构和算法(五)二叉排序树(BST)
Java数据结构和算法(五)二叉排序树(BST) 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 二叉排序树(Binary S ...
- Java数据结构和算法(四)赫夫曼树
Java数据结构和算法(四)赫夫曼树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 赫夫曼树又称为最优二叉树,赫夫曼树的一个 ...
- Java数据结构和算法(三)--三大排序--冒泡、选择、插入排序
三大排序在我们刚开始学习编程的时候就接触过,也是刚开始工作笔试会遇到的,后续也会学习希尔.快速排序,这里顺便复习一下 冒泡排序: 步骤: 1.从首位开始,比较首位和右边的索引 2.如果当前位置比右边的 ...
随机推荐
- 最大公约数(gcd)和 最小公倍数(lcm)——辗转相除法
辗转相除法(又称欧几里得算法)是求最大公因数的算法 要求a,b的最大公约数(a>b),我们可以递归地求b,a%b的最大公约数,直到其中一个数变成0,这时另一个数就是a,b的最大公约数. C++实 ...
- 谈谈Spring 注入properties文件总结
本篇谈谈Spring 注入properties文件总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 spring提供了多种方式来注入properties文件,本文做一个 ...
- [GO]通道的关闭
并不是往通道里放多少次数据,就必须取多次少数据的(之前的例子都是放3次取3次,放10次取10次),我们可以做一个操作,当子协程没有新放入的时候,主协程不再去取,这就是关闭通道 package main ...
- C# 银行系统
今天分享一个大家都爱的Money 银行系统代码 可以随心所欲的存钱取钱 //要想成功,必须马到 //建立数组 Card[] cards = ]; //卡类初始化 public void Initia ...
- 编写高质量代码改善C#程序的157个建议——建议64:为循环增加Tester-Doer模式而不是将try-catch置于循环内
建议64:为循环增加Tester-Doer模式而不是将try-catch置于循环内 如果需要在循环中引发异常,你需要特别注意,应为抛出异常是一个相当影响性能的过程.应该尽量在循环当中对异常发生的一些条 ...
- Android adb 命令
一.概述 作为一名开发者,相信对adb指令一定不会陌生.那么在手机连接adb后,可通过am命令做很多操作: (1) 拨打电话10086 adb shell am start -a android.in ...
- getField
model.getField(field, num) field {String} 字段名,多个字段用逗号隔开 num {Boolean | Number} 需要的条数 return {Promise ...
- [LeetCode 题解]: Flatten Binary Tree to Linked List
Given a binary tree, flatten it to a linked list in-place. For example,Given 1 / \ 2 5 / \ \ 3 4 6 T ...
- Postgres数据库在Linux中优化
I/O 优化1 打开 noatime nodirtime,async 方法: 修改 /etc/fstab stat 命令查看 2 调整预读方法: 查看 sudo blockdev --getra /d ...
- 读取IE缓存文件
使用WebCacheTool项目中的WinInetAPI.cs和Win32API.cs两个类 /// <summary> /// 获取IE缓存文件 /// </summary> ...