在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的, 现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。
public static void insertSort(int[] a) {
int len = a.length;// 数组长度
int insertNum;// 要插入的数
for (int i = 1; i < len; i++) {
insertNum = a[i];
int j = i - 1;// 序列元素个数
while (j >= 0 && a[j] > insertNum) {// 从后往前循环,将大于insertNum的数向后移动
a[j + 1] = a[j];// 元素向后移动
j--;
}
a[j + 1] = insertNum;// 找到位置,插入当前元素
}
}
简单选择排序:
遍历整个序列,将最小的数放在最前面。
遍历剩下的序列,将最小的数放在最前面。
重复第二步,直到只剩下一个数。
public static void selectSort(int[] a) {
int len = a.length;
for (int i = 0; i < len; i++) {
int value = a[i];
int position = i;
for (int j = i + 1; j < len; j++) {// 找到最小的值和位置
if (a[j] < value) {
value = a[j];
position = j;
}
}
a[position] = a[i];
a[i] = value;
}
}
设置开始比较的位数,和结束的位数。
两两比较,将最小的放到前面去。
重复1、2步,直到循环次数完毕。
public static void bubbleSort(int[] a) {
for(int i=0;i<a.length;i++) {
for(int j=i+1;j<a.length;j++) {
if(a[j]<a[i])swap(a,i,j);
}
}
}
/**
* 交换数
*/
private static void swap(int[] item, int i, int j) {
item[i] = item[i]^item[j];
item[j] = item[i]^item[j];
item[i] = item[i]^item[j];
}
选择要排序的数组里面的一个基值p(关于基值的选法,这里默认取第一个),小于p的数放在左边,大于p的数放在右边。
递归的将p左边和右边的数都按照第一步进行,直到不能递归。
public static void quickSort(int[] a,int start,int end) {
if(start >= end)return ;
int baseNum=a[start];
int l=start;
int r=end;
do {
while(a[l]<baseNum&&l<end) {
l++;
}
while(a[r]>baseNum&&r>start) {
r--;
}
if(l<=r) {
if(l<r){
System.out.println("当前基值:"+baseNum+" 交换位置"+l+":"+a[l]+"和"+r+":"+a[r]);
swap(a,l,r);
System.out.println("交换结果:"+Arrays.toString(a));
}
l++;
r--;
}
}while(l<r);
if(r>start)quickSort(a,start,r);
if(l<end)quickSort(a,l,end);
}
将数的个数设为n,取奇数k=n/2,将下标差值为k的数分为一组,构成有序序列。
再取k=k/2 ,将下标差值为k的书分为一组,构成有序序列。
重复第二步,直到k=1执行简单插入排序。
public static void sheelSort(int[] a) {
int len = a.length;
while (len != 0) {
len = len / 2;
for (int i = 0; i < len; i++) {// 分组
for (int j = i + len; j < a.length; j += len) {// 元素从第二个开始
int k = j - len;// k为有序序列最后一位的位数
int temp = a[j];// 要插入的元素
while (k >= 0 && temp < a[k]) {// 从后往前遍历
a[k + len] = a[k];
k -= len;// 向后移动len位
}
a[k + len] = temp;
}
}
}
}
将序列构建成大顶堆。
将根节点与最后一个节点交换,然后断开最后一个节点。
重复第一、二步,直到所有节点断开。
public static void heapSort(int[] a) {
//从最后一个非叶子节点开始,建堆
for (int i = a.length / 2 - 1; i >= 0; i--) {
adjustHeap(a, i, a.length);
}
// 下面,开始排序逻辑
for (int j = a.length - 1; j > 0; j--) {
// 元素交换
// 说是交换,其实质就是把大顶堆的根元素,放到数组的最后;换句话说,就是每一次的堆调整之后,都会有一个元素到达自己的最终位置
swap(a, 0, j);
// 元素交换之后,毫无疑问,最后一个元素无需再考虑排序问题了。
// 接下来我们需要排序的,就是已经去掉了部分元素的堆了,这也是为什么此方法放在循环里的原因
// 而这里,实质上是自上而下,自左向右进行调整的
adjustHeap(a, 0, j);
}
}
private static void adjustHeap(int[] a, int i, int length) {
// 先把当前元素取出来,因为当前元素可能要一直移动
int temp = a[i];
// 可以参照sort中的调用逻辑,在堆建成,且完成第一次交换之后,实质上i=0;也就是说,是从根所在的最小子树开始调整的
// 接下来的讲解,都是按照i的初始值为0来讲述的
// 这一段很好理解,如果i=0;则k=1;k+1=2
// 实质上,就是根节点和其左右子节点记性比较,让k指向这个不超过三个节点的子树中最大的值
// 这里,必须要说下为什么k值是跳跃性的。
// 首先,举个例子,如果a[0] >
// a[1]&&a[0]>a[2],说明0,1,2这棵树不需要调整,那么,下一步该到哪个节点了呢?肯定是a[1]所在的子树了,
// 也就是说,是以本节点的左子节点为根的那棵小的子树
// 而如果a[0}
// 所以,这里面的用意就在于,自上而下,自左向右一点点调整整棵树的部分,直到每一颗小子树都满足大根堆的规律为止
for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {
//2*i+1是i节点的左子节点坐标
// 让k先指向子节点中最大的节点
if (k + 1 < length && a[k] < a[k + 1]) {
k++;
}
// 如果发现子节点更大,则进行值的交换
if (a[k] > temp) {
swap(a, i, k);
// 下面就是非常关键的一步了
// 如果子节点更换了,那么,以子节点为根的子树会不会受到影响呢?
// 所以,循环对子节点所在的树继续进行判断
i = k;
// 如果不用交换,那么,就直接终止循环了
} else {
break;
}
}
}
新人瞎整理的,原理后面在补充。