1.冒泡排序算法的运作如下:(从后往前)
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
若文件的初始状态是正序的,冒泡排序最好的时间复杂度为 ;若初始文件是反序的,冒泡排序的最坏时间复杂度为 ,综上,因此冒泡排序总的平均时间复杂度为 ,是一种稳定排序算法。
public void doBubbleSort(int src[]) {
int len = src.length;
int temp;
for(int i=len-1;i>0;--i) {
for(int j=0;j<i;++j) {
if(src[j+1]<src[j]) {
temp = src[j];
src[j] = src[j+1];
src[j+1] = temp;
}
}
printResult(i, src);
}
}
2.快速排序:首先在要排序的序列 a 中选取一个中轴值,而后将序列分成两个部分,其中左边的部分 b 中的元素均小于或者等于 中轴值,右边的部分 c 的元素 均大于或者等于中轴值,而后通过递归调用快速排序的过程分别对两个部分进行排序,最后将两部分产生的结果合并即可得到最后的排序序列。
下面我们通过一个案例来演示一下快速排序的基本步骤: 以序列 46 30 82 90 56 17 95 15 共8个元素
初始状态: 46 30 82 90 56 17 95 15 选择46 作为基准值,i = 0, j = 7
i = 0 j = 7
15 30 82 90 56 17 95 46 15 < 46, 交换 15 和 46,移动 i, i = 1
i = 1 j = 7
15 30 82 90 56 17 95 46 30 < 46, 不需要交换,移动 i , i = 2
i = 2 j = 7
15 30 46 90 56 17 95 82 82 > 46, 交换82 和 46,移动 j , j = 6
i = 2 j = 6
15 30 46 90 56 17 95 82 95 > 46, 不需要交换,移动 j , j = 5
i = 2 j = 5
15 30 17 90 56 46 95 82 17 < 46, 交换46 和 17,移动 i, i = 3
i = 3 j = 5
15 30 17 46 56 90 95 82 90 > 46, 交换90 和 46,移动 j , j = 4
3 = i j = 4
15 30 17 46 56 90 95 82 56 > 46, 不需要交换,移动 j , j = 3
i = j = 3
i = j = 3, 这样序列就这样分割成了两部分,左边部分{15, 30, 17} 均小于 基准值(46);右边部分 {56, 90,95,82},均大于基准值。这样子我们就达到了分割序列的目标。在接着对子序列用同样的办法进行分割,直至子序列不超过一个元素,那么排序结束,整个序列处于有序状态。
3.直接选择排序: 第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,与R[1]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列。时间复杂度为 O(n2) ,是一种不稳定的排序方法。共需要进行n-1次选择和交换,每次选择需要进行 n-i 次比较 (1<=i<=n-1),而每次交换最多需要3次移动,因此,总的比较次数C=(n*n - n)/2。4.堆排序:堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。最坏情况下时间复杂度为nlogn。堆排序为不稳定排序,不适合记录较少的排序。操作过程:
1)初始化堆:将R[1..n]构造为堆(每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换(交换之后可能造成被交 换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整));
2)将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆。
5.直接插入排序:数组分为有序区(初始化为一个元素)和无序区,每次从无序区找一个数插入到有序区并保证其仍有序,辅助空间复杂度S(n)=O(1)。是一个就地排序。是一个稳定的排序方法。
6.希尔排序:增量的取值规则为第一次取总长度的一半,第二次取一半的一半,依次累推直到1为止