您的位置:首页 > 编程语言 > Java开发

三大简单排序算法(java)

2016-02-06 23:42 393 查看
排序是日常生活中最常见的数据处理应用之一,排序算法也是算法学习中的基础课程之一,从最基础的三大排序算法开始,开始算法学习之路吧。

准备工作:为了便于进行算法验证,先将在类ArraySort中封装一个int型的数组,并提供insert、display等方法。

<pre name="code" class="java">public class ArraySort {

private int[] a;
private int nElems;//数组长度

public ArraySort(int max){
a = new int[max];
nElems = 0;
}

public void insert(int value){
if(nElems<a.length){
a[nElems] = value;
nElems++;
}else{
throw new ArrayIndexOutOfBoundsException("The array is full");
}
}

public void display(){
for(int j=0; j<nElems; j++){
System.out.print(a[j] + " ");
}
System.out.println();
}

private void swap(int ind1, int ind2){
int temp = a[ind1];
a[ind1] = a[ind2];
a[ind2] = temp;
}
}






1.冒泡排序

冒泡排序,顾名思义就是像气泡冒起一样,把无序数组中最大的数据项冒起到无序数组的顶端并固定其位置,每遍历无序数组一次,就能固定一个数据项的位置,无需数组长度减一,循环进行这个操作直到数组中无序的部分长度为0为止。

冒泡算法实现如下:

<pre name="code" class="java">public void bubbleSort(){
int out,in;
for(out=nElems-1; out>1; out--){
for(in=0; in<out; in++){
if(a[in]>a[in+1]){
swap(in, in+1);
}
}
}
}



整个算法包括2层循环,外层循环out表示需要“冒泡”的次数,从数组结尾开始,到数组第二个元素结束(因为无序数组长度减小到1时,这部分实际上已经是有序的了),内层循环表示每次数据项需要“冒泡”到达的位置,从0开始,到out结束。整个算法过程中,数组中下标大于out的部分是有序的。

进行数据验证(后2种排序算法可采用同样的验证方法)

public class ArraySortApp {

public static void main(String[] args){
int maxSize = 10;
ArraySort arr = new ArraySort(maxSize);

for(int i=0;i<10;i++){
int value = (int)(Math.random()*99);
arr.insert(value);
}
System.out.print("The origin array is:");
arr.display();
arr.bubbleSort();
System.out.print("The sorted array is:");
arr.display();
}
}



效率:算法总共要进行N*(N-1)/2次比较运算,平均要进行N²/4次交换操作。

2.选择排序

选择排序的核心思想是遍历数组中无序的部分,从中找出最小的一个数据项,和数组这部分钟最左边的数据项交换位置。

public void selectSort(){
int out,in,min;
for(out=0; out<nElems-1; out++){
min = out;
for(in=out; in<nElems; in++){
if(a[in]<a[min]){
min = in;
}
}
if(min!=out){		<pre name="code" class="java" style="font-size:18px;"><span style="white-space:pre">				</span>swap(min, out);
}}}


整个算法包含2层循环,外层循环out从0开始,到数组的倒数第二个元素结束(同冒泡排序一样,当数组中无序的部分长度为1时,这部分实际上是有序的),内层循环in从out开始,到数组结尾结束,找到其中最小的数据项的下标,和第out项交换位置。整个算法过程中,数组中下标小于out的部分是有序的。

效率:算法总共要进行N*(N-1)/2次比较运算,进行不到N次交换操作。

3.插入排序

插入排序是从数组第二个元素开始,以当前数据项为枢纽,下标小于此数据项的部分是相对有序的,大于部分是未处理的,将当前数据项插入到有序的部分中,并将枢纽下标+1,重复上述操作。

public void insertSort(){
int out,in;
int temp;
for(out=1; out<nElems; out++){
temp = a[out];
in = out;
while(in>0&&a[in-1]>=temp){
a[in] = a[in-1];
in--;
}
a[in] = temp;
}
}
整个算法依旧是包含2层循环,外层循环从数组第二个元素开始,直到数组结束;内层循环in从out开始递减,知道出现小于枢纽项元素的数据项为止,然后把枢纽项数据插入到这个位置,从这个位置到枢纽项下标-1位置的元素全部右移一位。

效率:算法平均要进行N*(N-1)/4次比较运算,复制的次数约等于比较的次数。

以上3种排序算法,平均情况下的算法复杂度都是O(n²),但实际情况中其效率仍存在差异。冒泡排序是最基础的排序算法,其逻辑是最为简单易懂的;选择排序相较于冒泡排序,在比较次数相同的情况下,明显减少了交换次数,当交换数据比比较数据更耗时的情况下,选择排序是更好的选择;插入排序虽然复制操作的时间复杂度也是O(n²),但相较于数据交换也减少了2/3的操作(复制只需要1步,交换需要3步),此外插入排序在处理基本有序的数据时,是更好的选择(基本有序的数组,会明显减少插入排序的内层循环次数),因此插入排序也经常应用于一些高级排序算法的最后阶段中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  排序算法