本文介绍了4种排序算法及其实现,分别是冒泡排序(Bubble Sort)、二元选择排序(Binary Selection Sort)、插入排序(Straight Insertion Sort)以及希尔排序(Shell’s Sort)。
冒泡排序的源码为:
package SortAlgorithms;
import java.util.Arrays;
class BubbleSort {
BubbleSort(int[] array)
{
System.out.println("Bubble sorting:");
for(int i = 0;i<array.length;i++)
{
for(int j = 0;j<array.length-i-1;j++)
{
if(array[j]>array[j+1])
{
exchange(array,j,j+1);
}
}
System.out.println(Arrays.toString(array));
}
}
static void exchange(int[] array, int i, int j)
{
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
上文中定义了一个static函数exchange,利用了static对象不与包含它的类的任何对象关联的特性,即就是没有创建对象,也可以调用这一方法。冒泡排序是一种简单的但是广泛应用的排序算法。以从小到大排序为例,其特点是,重复比较两个相邻元素的大小,并将较大元素统一移到右边,较小元素移到左边。元素列重复遍历,直到排序完成。冒泡排序第一次遍历完成,将会把最大的元素移到序列最右侧,第二次遍历完成,将会把第二大的元素移到序列的右侧倒数第二个……因此,有N个元素的序列,遍历N次该序列才可以将该序列排序完成。
二元选择排序源码如下:
package SortAlgorithms;
import java.util.Arrays;
public class SimpleSelectionSort {
SimpleSelectionSort(int[] array)
{
System.out.println("Simple Selection sorting:");
for(int i = 0;i<array.length/2;i++)
{
int pointEnd = array.length-i-1;
for(int j = i;j<array.length-i;j++)
{
if(array[j]<array[i])
{
BubbleSort.exchange(array,j, i);
}
if(array[i]>array[pointEnd])
{
BubbleSort.exchange(array,i,pointEnd);
}
}
System.out.println(Arrays.toString(array));
}
}
}
二元选择排序是基于选择排序而来,因此这里先介绍一下选择排序的思路:仍然以从小到大排序为例,首先,找到序列的最小元素,将其与序列第一个元素交换,接着,在剩下的元素里找到最小的元素,将其与第二个元素交换……这样就实现了整个序列的排序,因此,假设一个长度为N的序列,仍然需要遍历N次才能排序完成。而二元选择排序的算法与此同时类似,只是每次遍历序列(剩余序列)的时候,同时找到序列(剩余序列)的最大值和最小值,并将最小值和序列(剩余序列)的第一个元素相交换,将最大值和序列(剩余序列)的最后一个元素相交换。
插入排序源码如下:
package SortAlgorithms;
import java.util.Arrays;
class StraightInsertionSort {
StraightInsertionSort(int[] array)
{
System.out.println("Straight insertion sorting:");
for(int i = 1;i<array.length;i++)
{
int j = i;
do
{
if(array[j]<array[j-1])
{
BubbleSort.exchange(array,j,j-1);
}
j = j - 1;
}
while(j>0);
System.out.println(Arrays.toString(array));
}
}
}
关于插入排序的介绍内容引用《算法导论》:插入排序类似于排序一手扑克牌,开始的时候手中并没有扑克牌并且桌子上的牌面向下,我们每次从桌子上拿走一张牌并放在手中的正确位置。为了找到它的正确位置,我们依次将其与之前排好的数进行对比。拿在手上的牌都是已经排序好的。
因此,新插入的数总是依次从已经排序好的序列从大到小进行对比,直到找到其的正确位置。
希尔排序源码如下:
package SortAlgorithms;
import java.util.Arrays;
class ShellSort {
private void Sort(int[] array, int h)
{
for(int i = h;i<array.length;i++)
{
int j = i;
do
{
if(array[j]<array[j-h])
{
BubbleSort.exchange(array,j,j-h);
}
j = j - h;
}
while(j>=h);
System.out.println(Arrays.toString(array));
}
}
ShellSort(int[] a)
{
System.out.println("Shell's sort:");
int h = a.length/3;
while(h>=1)
{
System.out.println("h is " + h);
Sort(a,h);
h = h/2;
}
}
}
关于希尔排序的介绍引用自《算法》:希尔排序是一种插入排序的快速的排序算法。希尔排序的思想是使数组中任意间隔为h的元素都是有序的。用这种方式,对于任意以1结尾的h序列,都可以将数组排序完成。希尔排序算法的性能不仅取决于h,还取决于各个h之间的数学性质,如公因子等等,目前,彻底理解希尔排序的性能仍然是一项挑战。
下面给出本文的测试代码:
package SortAlgorithms;
import java.util.Arrays;
public class SortTest {
private static int[] arrayReset()
{
int[] array = {10,7,6,5,4,3,2,1,0,100};
System.out.println("Array has been reset.");
System.out.println("Array is "+Arrays.toString(array));
return array;
}
public static void main(String[] args)
{
int[] a = arrayReset();
new BubbleSort(a);
a = arrayReset();
new StraightInsertionSort(a);
a = arrayReset();
new ShellSort(a);
a = arrayReset();
new SimpleSelectionSort(a);
}
}
运行结果如下:
/Library/Java/JavaVirtualMachines/jdk-12.0.2.jdk/Contents/Home/bin/java "-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=49488:/Applications/IntelliJ IDEA.app/Contents/bin" -Dfile.encoding=UTF-8 -classpath /Users/liangqian/IdeaProjects/排序算法/out/production/排序算法 SortAlgorithms.SortTest
Array has been reset.
Array is [10, 7, 6, 5, 4, 3, 2, 1, 0, 100]
Bubble sorting:
[7, 6, 5, 4, 3, 2, 1, 0, 10, 100]
[6, 5, 4, 3, 2, 1, 0, 7, 10, 100]
[5, 4, 3, 2, 1, 0, 6, 7, 10, 100]
[4, 3, 2, 1, 0, 5, 6, 7, 10, 100]
[3, 2, 1, 0, 4, 5, 6, 7, 10, 100]
[2, 1, 0, 3, 4, 5, 6, 7, 10, 100]
[1, 0, 2, 3, 4, 5, 6, 7, 10, 100]
[0, 1, 2, 3, 4, 5, 6, 7, 10, 100]
[0, 1, 2, 3, 4, 5, 6, 7, 10, 100]
[0, 1, 2, 3, 4, 5, 6, 7, 10, 100]
Array has been reset.
Array is [10, 7, 6, 5, 4, 3, 2, 1, 0, 100]
Straight insertion sorting:
[7, 10, 6, 5, 4, 3, 2, 1, 0, 100]
[6, 7, 10, 5, 4, 3, 2, 1, 0, 100]
[5, 6, 7, 10, 4, 3, 2, 1, 0, 100]
[4, 5, 6, 7, 10, 3, 2, 1, 0, 100]
[3, 4, 5, 6, 7, 10, 2, 1, 0, 100]
[2, 3, 4, 5, 6, 7, 10, 1, 0, 100]
[1, 2, 3, 4, 5, 6, 7, 10, 0, 100]
[0, 1, 2, 3, 4, 5, 6, 7, 10, 100]
[0, 1, 2, 3, 4, 5, 6, 7, 10, 100]
Array has been reset.
Array is [10, 7, 6, 5, 4, 3, 2, 1, 0, 100]
Shell's sort:
h is 3
[5, 7, 6, 10, 4, 3, 2, 1, 0, 100]
[5, 4, 6, 10, 7, 3, 2, 1, 0, 100]
[5, 4, 3, 10, 7, 6, 2, 1, 0, 100]
[2, 4, 3, 5, 7, 6, 10, 1, 0, 100]
[2, 1, 3, 5, 4, 6, 10, 7, 0, 100]
[2, 1, 0, 5, 4, 3, 10, 7, 6, 100]
[2, 1, 0, 5, 4, 3, 10, 7, 6, 100]
h is 1
[1, 2, 0, 5, 4, 3, 10, 7, 6, 100]
[0, 1, 2, 5, 4, 3, 10, 7, 6, 100]
[0, 1, 2, 5, 4, 3, 10, 7, 6, 100]
[0, 1, 2, 4, 5, 3, 10, 7, 6, 100]
[0, 1, 2, 3, 4, 5, 10, 7, 6, 100]
[0, 1, 2, 3, 4, 5, 10, 7, 6, 100]
[0, 1, 2, 3, 4, 5, 7, 10, 6, 100]
[0, 1, 2, 3, 4, 5, 6, 7, 10, 100]
[0, 1, 2, 3, 4, 5, 6, 7, 10, 100]
Array has been reset.
Array is [10, 7, 6, 5, 4, 3, 2, 1, 0, 100]
Simple Selection sorting:
[0, 10, 7, 6, 5, 4, 3, 2, 1, 100]
[0, 1, 7, 6, 5, 4, 3, 2, 10, 100]
[0, 1, 2, 6, 5, 4, 3, 7, 10, 100]
[0, 1, 2, 3, 5, 4, 6, 7, 10, 100]
[0, 1, 2, 3, 4, 5, 6, 7, 10, 100]
Process finished with exit code 0
本文中的代码源文件均已经上传至GitHub,源码链接为:
排序算法https://github.com/Mr-memorandum/Algorithms.git
全文完。
如果您想了解更多C++/Java/机器学习相关的知识,欢迎扫描下方的二维码,关注“梁公子的备忘录”,每天一篇相关的技术分享,期待与您一起学习,共同进步!