算法(2)
上一篇是交换排序
那么这一篇就是排序的第二种,选择排序:
什么是选择排序呢?让我们来看个例子:
20,90,100,69,9,3.
选择排序:从基准第一位开始,从二十开始遍历,第一遍,选出最小的3,跟20交换 3,90,100,69,9,20
依次类推:3,9,100,69,90,20
3,9,20,69,90,100
恰好排序完成,这个就是选择排序。
下面我们来看看java算法实现他的时间:
- // 选择排序
- private static void sel_sort(int[] a) {
- //首先从第一个开始遍历选择一个最小的
- for (int i = 0; i < a.length-1; i++) {
- int min=i;
- for (int j = i+1; j < a.length; j++) {
- if (a[j]<a[min]) {
- min=j;
- }
- }
- int temp=a[min];
- a[min]=a[i];
- a[i]=temp;
- }
- System.out.println(Arrays.toString(a));
- }
时间仍然是很可怕的:291ms
那么现在我们来了解一下另一种选择排序堆排序:

由堆排序就引出一种数据结构二叉树,而堆排序用的也叫二叉堆,二叉堆分最大堆和最小堆
堆:堆是一种时间复杂度为O(nlogn)的排序算法,同时和插入算法一样,就地排序,不需要额外的空间。堆排序需要用到一种被成为最大堆的数据结构,可以看成是一颗完全二叉树,树里面除了最后一层剩下的全是填满的。因此,树里面的每个节点的子女和双亲节点的序号都可以由当前算出。
P(i)=i/2 取整 legt(i)=2*i right(i)=2*i+1;
上面就是一个最大堆。父节点的值大于子节点的值。这个特点可以使他实现nlogn的排序
首先构建最大堆,然后在最大堆中把根和最后一个交换,构建。
import java.util.Arrays;
public class HeapSorter {
public static void heapSort(int[] a) {
bulidHeap(a);
int n=a.length;
int i=0;
for(i=n-1;i>=1;i--){
swap(a, 0, i);
heapify(a, 0, i);
}
}
// 构建堆
private static void bulidHeap(int[] a) {
int n = a.length;// 数组元素的个数
for (int i = n / 2 - 1; i >= 0; i--) {// 因为堆的性质,(n/2+1)~n的元素都是叶子节点
heapify(a, i, n);
}
}
private static void heapify(int[] a, int i, int n) {
int left = 2 * i + 1;// 左孩子的下标
int right = 2 * i + 2;// 右孩子的下标
int largest = 0;// 寻找三个节点中最大值节点的下标
if (left < n && a[left] > a[i]) {
largest = left;
} else if (right < n && a[right] > a[i]) {
largest = right;
} else {
largest = i;
}
if (largest != i) {
swap(a, largest, i);
heapify(a, largest, n);
}
}
// 交换功能
private static void swap(int[] a, int largest, int i) {
int temp;
temp = a[largest];
a[largest] = a[i];
a[i] = temp;
}
public static void main(String[] args) {
// 原始数据
int a[] = new int[10000];
for (int i = 0; i < 10000; i++) {
a[i] = (int) (Math.random() * 10000);
}
// 排序
System.out.println(Arrays.toString(a));
long starTime = System.currentTimeMillis();
heapSort(a);
System.out.println(Arrays.toString(a));
long endTime = System.currentTimeMillis();
System.out.println(endTime - starTime);
}
}
public class HeapSorter {
public static void heapSort(int[] a) {
bulidHeap(a);
int n=a.length;
int i=0;
for(i=n-1;i>=1;i--){
swap(a, 0, i);
heapify(a, 0, i);
}
}
// 构建堆
private static void bulidHeap(int[] a) {
int n = a.length;// 数组元素的个数
for (int i = n / 2 - 1; i >= 0; i--) {// 因为堆的性质,(n/2+1)~n的元素都是叶子节点
heapify(a, i, n);
}
}
private static void heapify(int[] a, int i, int n) {
int left = 2 * i + 1;// 左孩子的下标
int right = 2 * i + 2;// 右孩子的下标
int largest = 0;// 寻找三个节点中最大值节点的下标
if (left < n && a[left] > a[i]) {
largest = left;
} else if (right < n && a[right] > a[i]) {
largest = right;
} else {
largest = i;
}
if (largest != i) {
swap(a, largest, i);
heapify(a, largest, n);
}
}
// 交换功能
private static void swap(int[] a, int largest, int i) {
int temp;
temp = a[largest];
a[largest] = a[i];
a[i] = temp;
}
public static void main(String[] args) {
// 原始数据
int a[] = new int[10000];
for (int i = 0; i < 10000; i++) {
a[i] = (int) (Math.random() * 10000);
}
// 排序
System.out.println(Arrays.toString(a));
long starTime = System.currentTimeMillis();
heapSort(a);
System.out.println(Arrays.toString(a));
long endTime = System.currentTimeMillis();
System.out.println(endTime - starTime);
}
}
输出结果时间:32ms比快速排序的效率看起来还要慢一点。

浙公网安备 33010602011771号