您的位置:首页 > 其它

第三章 简单排序

2015-11-08 21:44 239 查看
一、概要
三种简单的排序:冒泡排序、选择排序、插入排序。

二、冒泡排序
假设由n个队员,并且根据所站的位置从左到右分别给每一个队员编号,从0到n-1。
冒泡排序的过程如下:
从队列的最左边开始,比较第0号和第1号,如果左边的队员比右边高,则交换两个队员。否则不做任何事。然后右移一个位置,比较第1号和第2号,重复上诉步骤,直到最后一个队员。这个属于第一轮冒泡,能够把最高的队员放在最右边。然后进行第二轮,依然从第0号开始,这一轮排序到n-2号队员。重复进行上诉操作,直到无需再排序了。

三、冒泡排序代码

class ArrayBub {
private long[] a;
private int nElems;

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

public void insert(long value) {
a[nElems++] = value;
}

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

//排序算法
public void bubbleSort() {
int out;
int in;

for(out = nElems -1;out > 1;out—)
for(in = 0;in < out;i++) {
if (a[in] > a[in+1])
swap(in, in+1);
}

private void swap(int one, int two) {
long temp = a[one];
a[one] = a[two];
a[two] = temp;
}
}

class BubbleSortApp {
public static void main(String[] args) {
int maxSize = 100;
ArrayBub arr = new ArrayBub(maxSize);

arr. insert(77);
arr. insert(27);
arr. insert(71);
arr. insert(44);
arr. insert(23);
arr. insert(10);
arr. insert(87);
arr. insert(99);
arr. insert(32);

arr.display();

arr.bubbleSort();
arr.display();
}
}
冒泡算法的思路是要将最小的数据项放在数组的最开始(下标为0),并将最大的数据项放在数组的最后(下标为nElems-1),内层从数组的最开始算起,每次循环加一进行比较排序,外层从nElems-1开始,每次循环减一进行每一轮排序。

四、不变性
在许多算法中,有些条件在算法执行时时不变的。这些条件称为不变性。在冒泡算法中,它的不变性就是out右边的所有数据项是有序的。
在调试算法的时候,我们可以反复检查它的不变性是否为真,如果不是,就说明出错了。

五、冒泡排序的效率
可以发现,如果有n个数据项,第一趟排序中有n-1次比较,第二趟排序中有n-2次比较,如此类推:
(n-1)+(n-2)+(n-3)+…+1=n*(n-1)/2
与n平方成正比,因此冒泡排序的效率为O(N^2)

六、选择排序
同样是为球队排序,排序从球员队列的最左边开始,记录下最左边球员的身高,然后开始用下一个的球员身高和它相比较,如果这个球员更矮,则纪录下新的最矮纪录,然后继续看下一个球员,直到全部球员比较结束。然后纪录到身高最矮的球员和最左边的球员调换位置。接下来,从第二个球员开始,重复上诉步骤,直到最后一个球员。

七、选择排序代码

class ArraySel {

private long[] a;
private int nElems;

public ArraySel(int max) {

a = new long[max];
nElems = 0;
}

public void insert(long value) {
a[nElems++] = value;
}

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

//选择算法
public void selectionSort() {
int out;
int in;
int min;

for(out = 0;out < nElems-1;out++) {
min = out;
for(in = out+1;in < nElems;in++)
if (a[in] < a[min])
min = in;
swap(out, min);
}

}

private void swap(int one, int two) {
long temp = a[one];
a[one] = a[two];
a[two] = temp;
}

}

class SelectSortApp {
public static void main(String[] args) {
int maxSize = 100;
ArraySel arr = new ArraySel(maxSize);

arr. insert(77);
arr. insert(27);
arr. insert(71);
arr. insert(44);
arr. insert(23);
arr. insert(10);
arr. insert(87);
arr. insert(99);
arr. insert(32);

arr.display();

arr.selectionSort();

arr.display();
}

}

八、不变性
在选择排序中,下标小于或等于out的位置的数据项总是有序的。

九、选择排序的效率
选择排序改进了冒泡排序的缺点,将交换次数从O(N^2)减少到O(N),但是比较次数仍然是O(N^2),因此二者的时间效率相同,但是选择排序无疑是更快的。

十、插入排序
在大多数情况下,简单排序中,插入排序是最快的一种。
假设队伍前一半已经排序好了,这个时候,在队伍中间有一个作为标记的队员,TA左边的所有队员已经是有序的,这时只要找到“被标记”队员在左边有序队列中合适的位置,就可以了。因此,我们先让“被标记”队员站出来,和左边有序队伍中最右边的那个队员比较,如果“被标记”队员更矮,那么最右边的队员右移一位,然后“被标记”队员继续和有序队伍右边倒数第二个队员比较,同样的规则,直到发现被比较的队员比“被标记”队员要矮,那么此时空出来的位置就是“被标记”的队员的。按照这个规则,我们就是从队伍的第一个依次标记到最后一个。

十一、插入排序的代码

class ArrayIns {

private long[] a;
private int nElems;

public ArrayIns(int max) {

a = new long[max];
nElems = 0;
}

public void insert(long value) {
a[nElems++] = value;
}

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

//插入算法
public void insertSort() {
int out;
int in;

for(out = 1;out < nElems;out++) {
long temp = a[out];
in = out;
while(in > 0 && a[in-1] >= temp) {
a[in] = a[in-1];
in—;
}
a[in] = temp;
}
}
}

class InsertSortApp {

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

arr. insert(77);
arr. insert(27);
arr. insert(71);
arr. insert(44);
arr. insert(23);
arr. insert(10);
arr. insert(87);
arr. insert(99);
arr. insert(32);

arr.display();

arr.insertSort();

arr.display();
}

}

十二、插入排序中的不变性
插入排序中,比out下标小的数据项都是局部有序的。

十三、插入排序的效率
1+2+3+…+N-1=N*(N-1)/2,第一趟最多比较一次,第二趟最多比较两次。。。然而在每一趟排序发现插入点之前,平均只有全体数据项的一半真的进行了比较,因此应该是N*(N-1)/4。总体而言,插入排序的算法,比冒泡排序快一倍,比选择排序略快。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: