冒泡排序
外层循环从1到n-1,内循环从当前外层的元素的下一个位置开始,依次和外层的元素比较,出现逆序就交换,通过与相邻元素的比较和交换来把小的数交换到最前面。
下面展示一些 内联代码片
。
for(int i=0;i<arr.length-1;i++){//外层循环控制排序趟数
for(int j=0;j<arr.length-1-i;j++){//内层循环控制每一趟排序多少次
if(arr[j]>arr[j+1]){
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
选择排序
冒泡排序是通过相邻的比较和交换,每次找个最小值。选择排序是:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
下面展示一些 内联代码片
。
private static void sort(int[] array) {
int n = array.length;
for (int i = 0; i < n-1; i++) {
int min = i;
for (int j = i+1; j < n; j++) {
if (array[j] < array[min]){//寻找最小数
min = j; //将最小数的索引赋值
}
}
int temp = array[i];
array[i] = array[min];
array[min] = temp;
}
}
插入排序
通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。可以理解为玩扑克牌时的理牌;
private static void sort(int[] array) {
int n = array.length;
/**
*从第二位数字开始,每一个数字都试图跟它的前一个比较并交换,并重复;直到前一个数字不存在或者比它小或相等时停下来
**/
for (int i = 1; i < n; i++) {//从第二个数开始
int key = array[i];
int j = i -1;
while (j >= 0 && array[j]>key) {
array[j + 1] = array[j]; //交换
j--; //下标向前移动
}
array[j+1] = key;
}
}
快速排序
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
private static void sort(int[] array) {
shuffle(array);
sort(array, 0, array.length - 1);
}
private static void sort(int[] array, int lo, int hi) {
if(hi<=lo+M) {
Insert.sort(a,lo,hi);
return;
}
int lt = lo, gt = hi;
int v = array[lo];
int i = lo;
while (i <= gt) {
if (array[i]<v) exch(array, lt++, i++);
else if (array[i]>v) exch(array, i, gt--);
else i++;
}
// a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi].
sort(array, lo, lt-1);
sort(array, gt+1, hi);
}
private static void exch(int[] a, int i, int j) {
int swap = a[i];
a[i] = a[j];
a[j] = swap;
}
/**
*打乱数组
*/
private static void shuffle(int[] array) {
Random random = new Random(System.currentTimeMillis());
if (array == null) throw new NullPointerException("argument array is null");
int n = array.length;
for (int i = 0; i < n; i++) {
int r = i + random.nextInt(n-i); // between i and n-1
int temp = array[i];
array[i] = array[r];
array[r] = temp;
}
}
代码例子:
1 package test;
2
3 public class s {
4 public static void main(String[] args) {
5 int[] arr = { 5,2,4,9,7 };
6 sort(arr, 0, arr.length - 1);
7 }
8 public static void sort(int arr[], int low, int high) {
9 int l = low;
10 int h = high;
11 int k = arr[low];
12 while (l < h) {
13 // 从后往前比较
14 while (l < h && arr[h] >= k ){ // 如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
15 h--;// h=6
16 }
17 if (l < h) {
18 int temp = arr[h];
19 arr[h] = arr[l];
20 arr[l] = temp;
21 //进行过一次替换后,没必要将替换后的两值再次比较,所以i++直接下一位与k对比
22 l++;
23 }
24 // 从前往后比较
25 while (l < h && arr[l] <= k) { // 如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
26 l++;
27 }
28 if (l < h) {
29 int temp = arr[h];
30 arr[h] = arr[l];
31 arr[l] = temp;
32 h--;
33 }
34 // 此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
35 }
36 print(arr);
37 System.out.print("l=" + (l + 1) + "h=" + (h + 1) + "k=" + k + "\n");
38 // 递归
39 if (l > low)//先判断l>low再次经行左边排序
40 sort(arr, low, l - 1);// 左边序列。第一个索引位置到关键值索引-1
41 if (h < high)//左边依次排序执行完递归后,弹栈进行右边排序
42 sort(arr, l + 1, high);// 右边序列。从关键值索引+1到最后一个
43 }
44 // 打印数组的方法
45 private static void print(int[] arr) {
46 System.out.print("[");
47 for (int i = 0; i < arr.length; i++) {
48 if (i != (arr.length - 1)) {
49 System.out.print(arr[i] + ",");
50 } else {
51 System.out.print(arr[i] + "]");
52 System.out.println();
53 }
54 }
55 }
56 }
堆排序
堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
public static void sort(int[] a){
int N = a.length;
int[] keys = new int[N+1];
//注意,堆的数据结构是从1开始的,0不用
for (int i = 1; i < keys.length; i++) {
keys[i] = a[i-1];
}
// //构造堆,使得堆是有序的
for(int k = N/2;k>=1;k--) sink(keys,k,N);
//排序,相当于毁掉堆
while(N>1){
exch(keys,1,N--);
sink(keys,1,N);
}
//重新写回数组
for (int i = 0; i < a.length; i++) {
a[i] = keys[i+1];
}
}
private static void sink(int[] a, int k, int N) {
// TODO Auto-generated method stub
while(2*k<=N){
int j = 2*k;
if (j < N && less(a[j], a[j+1])) j++;
if (less(a[j], a[k])) break;
exch(a, k, j);
k = j;
}
}
private static boolean less(int k, int j) {
// TODO Auto-generated method stub
return k < j;
}
private static void exch(int[] a, int i, int n) {
// TODO Auto-generated method stub
int temp = a[i];
a[i] = a[n];
a[n] = temp;
}
//package test;
public class dui {
/**
* 调整为小顶堆(排序后结果为从大到小)
*
* @param array是待调整的堆数组
* @param s是待调整的数组元素的位置
* @param length是数组的长度
*
*/
public static void heapAdjustS(int[] array, int s, int length) {
int tmp = array[s];
int child = 2 * s + 1;// 左孩子结点的位置
System.out.println("待调整结点为:array[" + s + "] = " + tmp);
while (child < length) {
// child + 1 是当前调整结点的右孩子
// 如果有右孩子且小于左孩子,使用右孩子与结点进行比较,否则使用左孩子
if (child + 1 < length && array[child] > array[child + 1]) {
child++;
}
System.out.println("将与子孩子 array[" + child + "] = " + array[child] + " 进行比较");
// 如果较小的子孩子比此结点小
if (array[s] > array[child]) {
System.out.println("子孩子比其小,交换位置");
array[s] = array[child];// 把较小的子孩子向上移动,替换当前待调整结点
s = child;// 待调整结点移动到较小子孩子原来的位置
array[child] = tmp;
child = 2 * s + 1;// 继续判断待调整结点是否需要继续调整
if (child >= length) {
System.out.println("没有子孩子了,调整结束");
} else {
System.out.println("继续与新的子孩子进行比较");
}
// continue;
} else {
System.out.println("子孩子均比其大,调整结束");
break;// 当前待调整结点小于它的左右孩子,不需调整,直接退出
}
}
}
/**
* 调整为大顶堆(排序后结果为从小到大)
*
* @param array是待调整的堆数组
* @param s是待调整的数组元素的位置
* @param length是数组的长度
*
*/
public static void heapAdjustB(int[] array, int s, int length) {
int tmp = array[s];
int child = 2 * s + 1;// 左孩子结点的位置
System.out.println("待调整结点为:array[" + s + "] = " + tmp);
while (child < length) {
// child + 1 是当前调整结点的右孩子
// 如果有右孩子且大于左孩子,使用右孩子与结点进行比较,否则使用左孩子
if (child + 1 < length && array[child] < array[child + 1]) {
child++;
}
System.out.println("将与子孩子 array[" + child + "] = " + array[child] + " 进行比较");
// 如果较大的子孩子比此结点大
if (array[s] < array[child]) {
System.out.println("子孩子比其大,交换位置");
array[s] = array[child];// 把较大的子孩子向上移动,替换当前待调整结点
s = child;// 待调整结点移动到较大子孩子原来的位置
array[child] = tmp;
child = 2 * s + 1;// 继续判断待调整结点是否需要继续调整
if (child >= length) {
System.out.println("没有子孩子了,调整结束");
} else {
System.out.println("继续与新的子孩子进行比较");
}
// continue;
} else {
System.out.println("子孩子均比其小,调整结束");
break;// 当前待调整结点大于它的左右孩子,不需调整,直接退出
}
}
}
/**
* 堆排序算法
*
* @param array
* @param inverse true 为倒序排列,false 为正序排列
*/
public static void heapSort(int[] array, boolean inverse) {
// 初始堆
// 最后一个有孩子的结点位置 i = (length - 1) / 2, 以此向上调整各结点使其符合堆
System.out.println("初始堆开始");
for (int i = (array.length - 1) / 2; i >= 0; i--) {
if (inverse) {
heapAdjustS(array, i, array.length);
} else {
heapAdjustB(array, i, array.length);
}
}
System.out.println("初始堆结束");
for (int i = array.length - 1; i > 0; i--) {
// 交换堆顶元素H[0]和堆中最后一个元素
int tmp = array[i];
array[i] = array[0];
array[0] = tmp;
// 每次交换堆顶元素和堆中最后一个元素之后,都要对堆进行调整
if (inverse) {
heapAdjustS(array, 0, i);
} else {
heapAdjustB(array, 0, i);
}
}
}
public static void main(String[] args) {
int[] array = { 49, 38, 65, 97, 76, 13, 27, 49 };
heapSort(array, false);
for (int i : array) {
System.out.print(i + " ");
}
}
}