@MrXiao
2018-03-07T19:48:08.000000Z
字数 2769
阅读 910
算法
我们通常所说的排序算法往往指的是内部排序算法,即数据记录在内存中进行排序。
排序算法大体可分为两种:
冒泡排序算法的运作如下:
由于它的简洁,冒泡排序通常被用来对于程序设计入门的学生介绍算法的概念。冒泡排序的代码如下:
/**
* 冒泡排序算法:平均o(n^2) 稳定 相邻两个比较,最大或最小的移到最右边
*
* @author xiaoyue
* @created @2018年3月6日-下午7:16:01
*
*/
public class BubbleSort {
public static void main(String[] args) {
int A[] = { 6, 5, 3, 1, 8, 7, 2, 4 }; // 从小到大冒泡排序
int size = A.length;
for (int i = 0; i < size - 1; i++) {// 每次最大元素就像气泡一样"浮"到数组的最后
for (int j = 0; j < size - 1 - i; j++) { //依次比较相邻的两个元素,使较大的那个向后移
if (A[j] > A[j + 1]) { // 如果条件改成A[j] >= A[j + 1],则变为不稳定的排序算法
int temp = A[j];
A[j] = A[j + 1];
A[j + 1] = temp;
}
}
}
for (int i = 0; i < size; i++) {
System.out.print(A[i] + ", ");
}
}
}
选择排序也是一种简单直观的排序算法。它的工作原理很容易理解:初始时在序列中找到最小(大)元素,放到序列的起始位置作为已排序序列;然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
注意选择排序与冒泡排序的区别:冒泡排序通过依次交换相邻两个顺序不合法的元素位置,从而将当前最小(大)元素放到合适的位置;而选择排序每遍历一次都记住了当前最小(大)元素的位置,最后仅需一次交换操作即可将其放到合适的位置。
public static void main(String[] args) {
int A[] = { 8, 5, 2, 6, 9, 3, 1, 4, 0, 7 }; // 从小到大选择排序
int size = A.length;
for (int i = 0; i < size - 1; i++) {//循环比对次数,除了最后一个数
int min = i;
for (int j = i + 1; j < size; j++) {//选择用来比对的数,从当前下一位到最后一位
if (A[j] < A[min]) {
min = j;
}
}
if (min != i) { //放到已排序序列的末尾,该操作很有可能把稳定性打乱,所以选择排序是不稳定的排序算法
int temp = A[i];
A[i] = A[min];
A[min] = temp;
}
}
for (int i = 0; i < size; i++) {
System.out.print(A[i] + ", ");
}
}
具体算法描述如下:
public static void main(String[] args) {
int A[] = { 6, 5, 3, 1, 8, 7, 2, 4 };// 从小到大插入排序
int size = A.length;
for (int i = 1; i < size; i++) {
int get = A[i];// 右手抓到一张扑克牌
int j = i - 1;// 拿在左手上的牌总是排序好的
while (j >= 0 && A[j] > get) {// 将抓到的牌与手牌从右向左进行比较
A[j + 1] = A[j];// 如果该手牌比抓到的牌大,就将其右移
j--;
}
A[j + 1] = get;// 直到该手牌比抓到的牌小(或二者相等),将抓到的牌插入到该手牌右边
//(相等元素的相对次序未变,所以插入排序是稳定的)
}
for (int i = 0; i < size; i++) {
System.out.print(A[i] + ", ");
}
}
快速排序使用分治策略(Divide and Conquer)来把一个序列分为两个子序列。步骤为:
public static void main(String[] args) {
int a[] = { 49, 37, 65, 97, 76, 13, 27, 49, 78 };
int low = 0;
int high = a.length-1;
quickSort(a, low, high);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+" ");
}
}
private static void quickSort(int[] a, int low, int high) {
int i = low,j = high;
if (i > j) {
return;
}
while (i < j) {
while (i<j && a[j]>=a[low]) {//从后往前找小于基准数的位置
j--;
}
while (i<j && a[i]<=a[low]) {//从前往后找大于基准数的位置
i++;
}
if (i < j) {//注意,i,j不能相遇或交叉
swap(a,i,j);
}
}
swap(a, low, j);
quickSort(a, low, j-1);
quickSort(a, j+1, high);
}
Java系统提供的Arrays.sort函数。对于基础类型,底层使用快速排序。对于非基础类型,底层使用归并排序。请问是为什么?
答:这是考虑到排序算法的稳定性。对于基础类型,相同值是无差别的,排序前后相同值的相对位置并不重要,所以选择更为高效的快速排序,尽管它是不稳定的排序算法;而对于非基础类型,排序前后相等实例的相对位置不宜改变,所以选择稳定的归并排序。