首先,将涉及到排序的基本操作抽象为一个接口,其中包括一下一些方法:(这里的约定是从小到大的排序)
public interface Sort {
/**
* 对数组a进行排序
* @param a
*/
public void sort(Comparable[] a);
/**
* 大小比较
* @param a
* @param b
* @return 如果a<b,返回true,否则false
*/
public boolean less(Comparable a,Comparable b);
/**
* 交换数组中连个元素的位置
* @param a
* @param i
* @param j
*/
public void exch(Comparable[] a,int i,int j);
/**
* 打印数组
*/
public void show(Comparable[] a);
/**
* 判断数组是否已经排序
* @return
*/
public boolean isSorted(Comparable[] a);
}
很多的方法是通用的,抽象成一个抽象父类:
public abstract class AbstractSort implements Sort {
@Override
public boolean less(Comparable m, Comparable n) {
return m.compareTo(n) < 0;
}
@Override
public void exch(Comparable[] a, int i, int j) {
Comparable tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
@Override
public void show(Comparable[] a) {
for(Comparable c : a){
System.out.print(c + " ") ;
}
System.out.println();
}
@Override
public boolean isSorted(Comparable[] a) {
for(int i= 1;i<a.length;i++){
if(less(a[i],a[i-1])) return false;
}
return true;
}
}
选择排序
该算法的思想最简单,即每次从非排序区查找一个最小元素放到已排序区的最后面:
/**
* 选择排序
* @author huqiao
*/
public class SelectionSort extends AbstractSort {
@Override
public void sort(Comparable[] a) {
for(int i = 0 ;i<a.length;i++){
//从非排序段中找到目前最小的,放到已排序区的最末端,即i处
for(int j = i+1;j<a.length;j++){
if(less(a[j],a[i])){
exch(a,i,j);
}
}
}
}
public static void main(String[] args) {
int size = 100000;
Integer[] a = RandomFactory.randomInt(size,400);
SelectionSort sort = new SelectionSort();
//sort.show(a);
long t = System.currentTimeMillis();
sort.sort(a);
t = System.currentTimeMillis() -t;
//sort.show(a);
System.out.println("Selection sort");
System.out.println("time:" + t);
System.out.println("random data size : " + size);
}
}
测试对10万条数据排序结果如下:
Selection sort
time:15475
random data size : 100000
插入排序
思想类似于整理扑克牌,从无序区取一个元素,从有序区的末端往前比较,直到发现一个比自己小的元素才停止。

如上图所示,黄色部分表示有序区,白色部分表示无序区,上图展示了无序区的第一个元素(即4)从有序区往前移动的轨迹(发现3比自己小,于是停止)。
代码如下:
/**
* 插入排序
* @author huqiao
*/
public class InsertSort extends AbstractSort {
@Override
public void sort(Comparable[] a) {
for(int i = 1 ;i<a.length;i++){
//拿着非排序段的第一个元素,从一排序段的末尾开始逐个比较往前移动,直到发现比自己小的元素
for(int j = i;j>0 && less(a[j],a[j-1]);j--){
exch(a,j,j-1);
}
}
}
public static void main(String[] args) {
int size = 100000;
Integer[] a = RandomFactory.randomInt(size,400);
InsertSort sort = new InsertSort();
//sort.show(a);
long t = System.currentTimeMillis();
sort.sort(a);
t = System.currentTimeMillis() -t;
//sort.show(a);
System.out.println("Insert sort");
System.out.println("time:" + t);
System.out.println("random data size : " + size);
}
}
插入排序的表现比选择排序稍好,不过优势不是很明显:
Insert sort
time:12851
random data size : 100000
希尔排序
希尔排序是在插入排序的基础上改进而来的,它要解决的问题是,插入排序中元素移动的速度太慢。比如一个最小的元素如果排在了长度为N数组的末尾,那么它最终要移动到数组的第一位需要移动的次数是N-1。希尔排序通过h有序的方式加速了元素的移动速度:
/**
* 插入排序
* @author huqiao
*/
public class ShellSort extends AbstractSort {
@Override
public void sort(Comparable[] a) {
int N = a.length;
int h = 1;
while(h<N/3) h = 3*h + 1;
while(h>=1){
for(int i = h ;i<a.length;i++){
//拿着非排序段的第一个元素,从一排序段的末尾开始逐个比较往前移动,直到发现比自己小的元素
for(int j = i;j>=h && less(a[j],a[j-h]);j-=h){
exch(a,j,j-h);
}
}
h = h/3;
}
}
public static void main(String[] args) {
int size = 100000;
Integer[] a = RandomFactory.randomInt(size,40000);
ShellSort sort = new ShellSort();
//sort.show(a);
long t = System.currentTimeMillis();
sort.sort(a);
t = System.currentTimeMillis() -t;
//sort.show(a);
System.out.println("Shell sort");
System.out.println("time:" + t);
System.out.println("random data size : " + size);
}
}
希尔排序的表现惊人,优势很明显:
Shell sort
time:54
random data size : 100000
实际情况中,许多高级排序算法相对与希尔排序的优势也不是和明显,加上算法复杂度的考虑,希尔排序不失为一种既价廉又物美的算法。
分享到:
相关推荐
八大排序算法,排序算法是比较初级的算法,在学习排序算法的同时有助于我们去理解数据结构,熟练掌握C++语法规则
内容概要:本文详细介绍了几种常用的排序算法,包括冒泡排序、选择排序、插入排序、归并排序、快速排序、堆排序、计数排序、桶排序和基数排序。文章不仅解释了每种排序算法的基本原理和时间复杂度,还提供了相应的 ...
适合人群:初级及中级软件工程师、计算机科学专业学生、对排序算法感兴趣的程序员。 使用场景及目标:①了解各种常见排序算法的工作原理及其实现方式;②提升代码实现能力和算法思维能力;③根据具体需求选择合适的...
在计算机科学领域,排序算法是数据处理的核心技术之一,它涉及到如何有效地对一组数据进行排列。...无论是初级程序员还是经验丰富的开发者,都应该熟练掌握这些基本的排序算法,以应对各种数据处理需求。
快速排序是一种高效的排序算法,由英国计算机科学家C.A.R. Hoare在1960年提出。它的基本思想是分治法(Divide and Conquer),通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的...
冒泡排序是最简单的排序算法之一,它通过重复遍历数组,比较相邻元素并交换位置(如果需要)来完成排序。虽然效率较低,但它易于理解。 2. **选择排序 (Selection Sort)** 选择排序每次从未排序部分找到最小(或...
适合人群:具备基础编程知识,希望深入了解排序算法及其实现的技术爱好者、学生或初级开发者。 使用场景及目标:适用于需要对大量数据进行高效排序的实际工程项目。目标是帮助读者理解和掌握各种排序算法的实现原理...
本资源包含三个经典的排序算法的源代码:插入排序、选择排序和冒泡排序,这些都是初级到中级程序员常学习和使用的算法。下面将详细介绍这三个排序算法的工作原理、特点以及代码实现。 1. **插入排序(Insertion ...
这两种排序算法都是初级程序员经常学习和练习的基础内容。 **冒泡排序(Bubble Sort)** 冒泡排序是一种简单的排序算法,它的基本思想是通过重复遍历待排序的数列,一次比较两个元素,如果他们的顺序错误就把他们...
这个"七种常见的VB排序算法示例程序.rar"压缩包包含了一系列的VB代码示例,涵盖了从初级到高级的不同排序算法。让我们逐一探讨这些算法的原理、实现方式以及它们在实际应用中的优缺点。 1. 起泡排序(Bubble Sort)...
1. 排序算法:包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等,它们是解决许多问题的基础,比如查找最值、数据整理等。 2. 搜索算法:如线性搜索、二分搜索、深度优先搜索(DFS)和广度优先搜索...
许多人都说算法是程序的核心,算法的好坏决定了程序的质量。...但是对于基本的排序算法还是应该掌握的,它是程序开发的必备工具。下面通过本文给大家介绍PHP实现四种基础排序算法的运行时间比较,一起看下吧。
Unicode 排序算法和 pyuca 也支持收缩和扩展。收缩是多个字母被视为一个单元的地方。在西班牙语中,ch被视为介于cand之间的字母,d 因此,例如,开头的单词ch应该排在所有其他以 开头的单词之后c。扩展是单个字母被...
代码中列举了java常见的排序算法,并备有简单的注释信息,对于初级开发人员可供参考。
适合人群:正在学习经典排序算法的学生或初级程序员,希望理解高级数据结构的实际应用以及优化技巧的人。 使用场景及目标:该文可以帮助使用者掌握堆排序的基础理论知识和技术细节,尤其适合那些想深入探究算法内部...
C语言大数的因子分解-C语言经典算法:如何较快的分解质因数,排序算法数据结构最快的排序算法 在计算机科学中,大数的因子分解是指将一个大整数分解成其质因数的乘积,这是一个非常重要的算法问题。因子分解的应用...
冒泡排序是一种基础的排序算法,它通过重复遍历待排序的序列,比较相邻元素并交换位置,使得每个元素都能找到其正确的位置。在本教程中,我们将深入探讨如何使用C#后端和jQuery前端来实现这个算法,这对于初学者来说...
本书首先会从基础出发,介绍算法的基本概念和分类,如排序算法、搜索算法、图论算法以及动态规划等。排序算法包括常见的冒泡排序、插入排序、选择排序,以及更高效的快速排序、归并排序和堆排序。这些算法的原理、...
在编程领域,排序算法是计算机科学的基础之一,尤其是在Java这样的多用途编程语言中更是不可或缺的知识点。本文将深入探讨Java中的排序算法,并结合递归原理进行分析。 首先,让我们了解什么是排序。排序是指将一组...
常见的排序算法有冒泡排序、选择排序、插入排序、快速排序、归并排序和堆排序。理解各种排序算法的时间复杂性和适用场景是算法设计的重要环节。 6. **栈和队列**:栈是一种后进先出(LIFO)的数据结构,常用于...