算法导论-选择排序
选择排序分简单选择排序和堆排序两种。
1.简单选择排序
基本思想:每一次从待排序的记录中选取关键字最小的记录,顺序放在已排好序的记录后面,直到全部记录排序完毕。
特点:时间复杂度为O(n*2),空间复杂度为O(1),不稳定。
简单排序代码:
public void selectionSort(int [] a ){
for (int i = 0; i < a.length-1; i++) {
int temp = a[i] ;
int tempIndex = 0 ;
for (int j = i+1; j < a.length; j++) {
if (a[j] < temp) {
temp = a[j] ;
tempIndex = j ;
}
}
if (tempIndex > 0) {
a[tempIndex]= a[i] ;
a[i] = temp ;
}
}
}
2.堆排序
基本步骤:a.先把一个无序序列建堆;
b.输出堆顶元素,调整剩余元素成新堆,直至序列有序。
特点:像插入排序算法,它是原地的;像合并排序,时间复杂度是O(nlgn),即使最坏情况也是如此,这也是它与快速排序相比最大的优点
堆排序代码:
/**堆排序
* @author het
* @date 2010-8-7
*/
public class HeapSort {
/**
* 测试
*/
public static void main(String[] args) {
int [] a = {2,1,4,5,6,7,9,10,98,45,80,0,2,3333};
HeapSort sort = new HeapSort();
sort.MaxHeapSort(a);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
/**
* 交换数组中指定的两元素的位置
* PS:Java中的基本元素是不支持传址的,必须是对象或数组才能传址(引用)
*/
public void swap(int[] data, int x, int y) {
int temp = data[x];
data[x] = data[y];
data[y] = temp;
}
/**
* 保持堆的性质(非递归)
*/
private void MaxHeapify(int []a ,int i , int n){
int index = 2*i +1 ;//先记录i的左孩子
boolean isMax = false ;
int temp = a[i];
while(index <= n && !isMax){
if ( index < n && a[index] < a[index+1] ) {//如果右孩子比左孩子更大,用index记录右孩子下标
index ++ ;
}
if (temp > a[index]) {
isMax = true ;
}else {//将大者上移
a[i] = a[index];
i = index ;
index = 2*i +1 ;
}
}
a[i] = temp ;
}
/**
* 保持堆的性质(递归)
*/
private void MaxHeapifyRecursion(int [] a , int i , int n){
int lchild = 2*i+1 ;//i的左孩子的下标
int rchild = lchild +1 ;//i的右孩子的下标
int largest = i ;//记录 a[i],a[lchild],a[rchild]中的最大者的下标
if (lchild <= n && a[lchild] > a[largest]) {
largest = lchild ;
}
if (rchild <= n && a[rchild] > a[largest]) {
largest = rchild ;
}
//交换
if (largest != i ) {
swap(a, largest, i);
//为保持堆的性质,对有孩子的节点继续向下迭代
if(largest <= n /2 ){
MaxHeapifyRecursion(a, largest , n);
}
}
}
/**
* 建堆,时间复杂度为O(n)
*/
private void CreateHeap(int [] a){
int length = a.length -1 ;//数组元素的最大下标
//自a[a.length/2]以后都是叶子节点,故对之前的非叶子节点都调用一次MaxHeapify以建堆
for (int i = length/2 ; i >=0 ; i--) {
MaxHeapify(a, i,length);
//MaxHeapifyRecursion(a, i, length);
}
}
/**
* 堆排序(最大堆),得到升序序列,时间复杂度为O(nlgn)
*/
public void MaxHeapSort(int [] a){
CreateHeap(a);
//输出堆顶元素(交换堆顶元素a[0]与a[a.length-1]),并把剩下的元素调整成一个新堆
for (int i = a.length-1; i > 0 ; i--) {
swap(a, 0 , i);
MaxHeapify(a, 0 ,i-1);
//MaxHeapifyRecursion(a, 0, i-1);
}
}
}