在这里只写出这三种排序的思路和代码,关于他们的时间,空间复杂度以及稳定性,将在写完高级排序后做具体分析。
一、冒泡排序:顾名思义,将小的(或大的也可以)冒出,将大的沉下去。(这里以将小的元素冒出为例)假设有n个元素,每一次选中一个元素后与后面每一个元素进行比较,若是比后面的元素大,则进行交换,若比后面的元素小则与下一个元素进行比较,直至最大的元素沉到底下即下标值为n。进行第二轮比较,则只需将第一个元素比较到下标为n-1的元素,不断重复,直到只剩两个元素时,此时第一个元素和第二个比较,若比第二个大,交换反之不动,排序完成。代码如下。
public void BubbleSort() { //假设有五个元素(nElems值则为6,看上面注释)则共需要拿四个元素出来比较 for(out=nElems-1;out>1;out--) { for(in=0;in<out;in++)//假设有五个元素,第一次比较需要四次,4,3,2..... { if(array[in]>array[in+1])//若前一个元素比后一个元素大 { swap(in,in+1);//交换元素 } } }
二、选择排序:与冒泡排序类似,不过注意!它每一次选中一个元素出来与后面的元素比较,若是发现有元素比选中的元素还要小,会将小的元素的下标值覆盖掉选中元素的下标值,(这也是我们在设计程序时要新建一个变量来保存一开始选中元素的下标值的原因)重复此操作,直至获得最小元素的下标值,然后和一开始选中的的元素进行交换。代码如下:
//选择排序
//选择排序
public void SelectSort() { for(out=0;out<nElems-2;out++) { int min=out;//min来保存每次比较元素后得到较小的元素的下标值 for(in=out+1;in<nElems;in++) { if(array[min]>array[in]) { min=in;//注意,每次比较后,小的元素不断覆盖min,直至得到最小元素的下标值 } } swap(out,min);//把最小的元素和下标值为out的元素进行交换 } }
三、插入排序:插入排序是选中后面的元素然后往前比较,但前面的元素比选中的元素大时则覆盖选中的元素(同理我们也需要将事先选中的元素进行保存),也可称为移动,比如:a[0]=1,a[1]=5,a[2]=3,当选中的元素为3时,往前比较一次后,是a[0]=1.a[1]=?,a[2]=3,注意此时a[1]位置是空的,这也是插入排序巧妙的地方,不断将大的元素往前移动直到 事先保存好的元素遇到比它小的元素,才从这个空的位置插入,比如:上面的3遇到1以后,执行插入语句,才插入到a[1]位置。代码如下。
public void insertSort() {
for(out=1;out<nElems;out++)
{
//每次比较前对保存out下标值对应的元素,并把out赋值给in,作为每次进行比较前的第一个元素的下标值
in = out;
int temp = array[out];
while(in>0&&array[in-1]>temp)
{
//当前一个元素的比后一个元素大时直接复制(移动),直到temp遇到到一个比它小的数就ok了
array[in]=array[in-1];
--in;
}
array[in]=temp;//最后只需将先前保存好的temp值插入in位置
}
}
完整代码如下:
package csnd;
package csnd; class Sort { int out,in,nElems,temp; int array[]; public Sort() { nElems=0; } public Sort(int n) { array = new int[n]; nElems=0; } public void insert(int j) { array[nElems]=j; nElems++;//注意,在这里当最后一个元素插入后,nElems值还会加一 } //冒泡排序 public void BubbleSort() { //假设有五个元素(nElems值则为6,看上面注释)则共需要拿四个元素出来比较 for(out=nElems-1;out>1;out--) { for(in=0;in<out;in++)//假设有五个元素,第一次比较需要四次,4,3,2..... { if(array[in]>array[in+1])//若前一个元素比后一个元素大 { swap(in,in+1);//交换元素 } } } } //选择排序 public void SelectSort() { for(out=0;out<nElems-2;out++) { int min=out;//min来保存每次比较元素后得到较小的元素的下标值 for(in=out+1;in<nElems;in++) { if(array[min]>array[in]) { min=in;//注意,每次比较后,小的元素不断覆盖min,直至得到最小元素的下标值 } } swap(out,min);//把最小的元素和下标值为out的元素进行交换 } } //插入排序 public void insertSort() { for(out=1;out<nElems;out++) { //每次比较前对保存out下标值对应的元素,并把out赋值给in,作为每次进行比较前的第一个元素的下标值 in = out; int temp = array[out]; while(in>0&&array[in-1]>temp) { //当前一个元素的比后一个元素大时直接复制(移动),直到temp遇到到一个比它小的数就ok了 array[in]=array[in-1]; --in; } array[in]=temp;//最后只需将先前保存好的temp值插入in位置 } } private void swap(int temp1, int temp2) { int temp = array[temp1]; array[temp1] = array[temp2]; array[temp2] = temp; } public void display(){ for(int i=0;i<nElems;i++) System.out.print(array[i]+" "); System.out.println(); } }
public class TestBubble {
public static void main(String[] args) {
Sort theArray = new Sort(20);
for(int i=0;i<20;i++)
{
//这里用随机数来生成一个数组,10可以用其他数表示,意思是指随机产生该数范围内的
int n=(int)(Math.random()*(10));
theArray.insert(n);
}
System.out.println("原先数组:");
theArray.display();//先调用display方法,打印出原来的数组
// System.out.println("调用冒泡排序方法后:");
// theArray.BubbleSort();//调用冒泡排序方法,排序数组
// theArray.display();//排序后再次打印
System.out.println("调用选择排序方法后:");
theArray.SelectSort();
theArray.display();
// System.out.println("调用插入排序方法后:");
// theArray.insertSort();
// theArray.display();
}
}
//可通过注释查看不同调用方法后的结果,这里只列举选择排序后的结果
原先数组:
5 9 9 1 5 1 8 1 4 1 2 5 4 3 4 1 9 0 6 8
调用选择排序方法后:
0 1 1 1 1 1 2 3 4 4 4 5 5 5 6 8 8 9 9 9