1,插入排序:
(1)直接插入排序,将目标序列分成有序区和无序区,比较无序区第一个元素和有序区最后一个元素,如果前者比后者小,则将有序区后移一位,将无序区第一位插入有序区。算法实现:
public class Main{
public static void main(String[] args){
int[] a = {2,4,13,53,6,3,6};
new Main().directInsert(a);
for(int i:a)
System.out.print(i+" ");
}
void directInsert(int[] a){
for(int i=0; i<a.length-1; i++){
if(a[i+1]<a[i]){
int tmp = a[i+1];
int j = 0;
for(j=i; j>0&&a[j]>tmp; j--){
a[j+1] = a[j];
}
a[++j] = tmp;
}
}
}
}
(2)希尔排序,跳跃式的直接插入排序。先设置初始增量,从目标序列种提取出以初始增量为间隔的子序列,用直接插入排序对该子序列进行排序。然后增量减1,重复上述步骤,直至增量减为0;算法实现:
public class Main{
public static void main(String[] args){
int[] a = {2,4,13,53,6,3,6};
new Main().shellSort(a);
for(int i:a)
System.out.print(i+" ");
}
void shellSort(int[] a){
int delta = a.length/3;
for(int d=delta; d>0; d--){
for(int i=d; i<a.length; i+=d){
//当跳跃序列的无序区第一个小于有序区的最后一个,则执行插入操作
if(a[i]<a[i-d]){
int tmp = a[i];
int j = 0;
for(j=i-d; j>0&&tmp<a[j]; j-=d){
a[j+d] = a[j];
}
a[j+=d] = tmp;
}
}
}
}
}
2,选择排序:
(1)直接选择排序,先选中目标序列第0位,找到从第0位到最后一位中最小的一位,与第0位交换;选中第1位,找到从第1位到最后一位中最小的一位,与第1位交换;依次类推……算法实现:
public class Main{
public static void main(String[] args){
int[] a = {2,4,13,53,6,3,6};
new Main().selectSort(a);
for(int i:a)
System.out.print(i+" ");
}
void selectSort(int[] a){
int k=0;
for(int i=0; i<a.length-1; i++){
k = i;
for(int j=i+1; j<a.length; j++){
if(a[j]<a[k]) k = j;
}
if(k!=i){
int tmp = a[i];
a[i] = a[k];
a[k] = tmp;
}
}
}
}
(2)堆排序:堆是一种特殊的完全二叉树,可分为最大堆和最小堆。最大堆,父节点均大于子节点,从根节点到任意叶子节点的路径是降序的。最小堆,父节点均小于子节点,从根节点到任意叶子结点的路径是升序的。因此,最大堆的根节点存储的是最大值,最小堆的根节点存储的是最小值。创建最大堆的过程如下:从(n-1)/2位开始,两个指针k和j,k指向父节点,j指向子节点中的较大节点。如果子节点大于父节点,则将两者交换位置,交换之后要将k指向原子节点,j指向原子节点的子节点,重复上述判断。排序的过程是:依次对初始序列的0到limit位创建最大堆,此时最大值存储在data[0],将其与data[limit]交换,将limit减1,继续上述操作。算法实现:
public class Main{
public static void main(String[] args){
int[] a = {2,4,13,53,6,3,6};
new Main().heapSort(a);
for(int i:a)
System.out.print(i+" ");
}
void heapSort(int[] a){
for(int limit = a.length-1; limit>0; limit--){
createHeap(a,0,limit);
int tmp = a[0];
a[0] = a[limit];
a[limit] = tmp;
}
}
static void createHeap(int[] data, int low, int high){
for(int i=high/2; i>=0; i--){
int tmp = data[i];//将当前父节点保存起来,避免被覆盖
int k = i;//k指向父节点
int j = 2*k+1;//j指向子节点
while(j<=high){
if(j<high&&data[j]<data[j+1]) j++;//j指向两个子节点中较大的一个
if(data[k]<data[j]){//如果父节点小于较大的子节点,则将子节点移至父节点
data[k] = data[j];
k = j;//将k指向原子节点
j = 2*k+1;//将j指向原子结点的子节点
}else{
break;//如果父节点大于较大子节点,则无需任何操作
}
}
data[k] = tmp;//将父节点移至子节点,完成交换
}
}
}
3,交换排序
(1)冒泡排序:依次比较data[i]和data[i+1]的大小,如果data[i]>data[i+1],则两者交换,这样一趟下来的结果是,最大的值被移动到了数组的末位,然后对剩下的无序区继续进行冒泡排序,把次最大移动到倒数第二位。这样的排序操作最多要进行n-1趟。代码实现:
public class Main{
public static void main(String[] args){
int[] a = {2,4,13,53,6,3,6};
new Main().bubbleSort(a);
for(int i:a)
System.out.print(i+" ");
}
void bubbleSort(int[] a){
boolean flag;
for(int i=1; i<a.length; i++){//最多做n-1趟排序
flag = false;
for(int j=0; j<a.length-i; j++){
if(a[j+1]<a[j]){
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
flag = true;//发生了交换
}
}
if(!flag) break;//如果本趟没有发生交换,说明排序已经完成,可以提前结束
}
}
}