三大简单排序算法(java)

排序是日常生活中最常见的数据处理应用之一,排序算法也是算法学习中的基础课程之一,从最基础的三大排序算法开始,开始算法学习之路吧。


准备工作:为了便于进行算法验证,先将在类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步),此外插入排序在处理基本有序的数据时,是更好的选择(基本有序的数组,会明显减少插入排序的内层循环次数),因此插入排序也经常应用于一些高级排序算法的最后阶段中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值