目录
1.简单选择排序
简单选择排序的基本思想非常简单,即:第一趟,从 n 个元素中找出关键字最小的元素与第一个元素交换;第二趟,在从第二个元素开始的 n-1 个元素中再选出关键字最小的元素与第二个元素交换;如此,第 k 趟,则从第 k 个元素开始的 n-k+1 个元素中选出关键字最小的元素与第 k 个元素交换,直到整个序列按关键字有序。
Java实现代码如下:
public static void simpleSelectSort(int arr[]) {
int min;
for(int i=0;i<arr.length-1;i++) {
min = i;
for(int j=i+1;j<arr.length;j++)
if(arr[j]<arr[min])
min=j;
if(min!=i) {
arr[min] = arr[min]+arr[i];
arr[i] = arr[min]-arr[i];
arr[min] = arr[min]-arr[i];
}
}
}
2.树形选择排序
3.堆排序
关于什么是大/小顶堆,自行查阅资料。堆排序的思路为:设有 n 个元素,欲将其按关键字排序。可以首先将这 n 个元素按关键字建成堆,将堆顶元素输出,得到 n 个元素中关键字最大(或最小)的元素。然后,再将剩下的 n-1 个元素重新建成堆,再输出堆顶元素,得到 n 个元素中关键字次大(或次小)的元素。如此反复执行, 直到最后只剩一个元素,则可以得到一个有序序列,这个排序过程称之为堆排序。
从对排序的过程中可以看到,在实现对排序时需要解决两个问题:
1.如何将 n 个元素的序列按关键字建成堆;
2.输出堆顶元素后,怎样调整剩余 n-1 个元素,使其按关键字成为一个新堆。
我们首先第二个问题,即输出堆顶元素后,对剩余元素重新建成堆的调整过程。
设有一个具有 m 个元素的堆,输出堆顶元素后,剩下 m-1 个元素。具体的调整方法是: 首先,将堆底元素(最后一个元素)送入堆顶,此时堆被破坏,其原因仅是根结点不满足堆的性质,而根结点的左右子树仍是堆。然后,将根结点与左、右子女中较大(或较小)的进行交换。若与左孩子交换,则左子树堆被破坏,且仅左子树的根结点不满足堆的性质;若与右孩子交换,则右子树堆被破坏,且仅右子树的根结点不满足堆的性质。继续对不满足堆性质的子树进行上述交换操作,直到叶子结点,则堆被重建。我们称这个自根结点到叶子结点的调整过程为筛选。
由此,如果我们能够建立一个堆,那么排序的过程就是不断输出堆顶并进行筛选的过程。现在的关键问题是如何由一个元素的初始序列构造一个堆,实际上建堆的方法是逐层向上对每个非终端结点进行一次筛选即可。
初始建堆首的过程,以按层从下到上的第一个非叶子结点开始。对于数组int arr[],将元素构成一颗完全二叉树,arr[i]的左子节点为arr[2i+1],右子节点为arr[2i+2];父节点为(i-1)/2。
堆调整的过程Java代码如下:
/**
* arr[low]为根节点,除了根节点外其余节点均满足大顶堆
* @param arr
* @param low
* @param high
*/
public static void heapAjust(int arr[],int low,int high) {
int min = arr[low];
for(int i=2*low+1;i<=high;i=2*i+1) {
if(i<high&&arr[i]<arr[i+1]) i++;
if(min>=arr[i]) break;
arr[low] = arr[i];
low = i;
}
arr[low] = min;
}
初始序列建堆及排序Java实现如下:
public static void heapSort(int arr[]) {
for(int i = (arr.length-2)/2;i>=0;i--)//建堆
heapAjust(arr, i, arr.length-1);
for(int i = arr.length-1;i>0;i--) {//筛选
arr[i]=arr[i]+arr[0];
arr[0]=arr[i]-arr[0];
arr[i]=arr[i]-arr[0];
heapAjust(arr, 0, i-1);
}
}
4.总结
简单选择排序的时间复杂度为O(n2),是一种不稳定的排序算法;堆排序的时间复杂度为Ο(n log n), 是一种不稳定的排序算法。选取10万个随机整数排序耗时测试如图: