6.希尔排序
希尔排序类似于插入排序,是一种缩小增量的排序。
①首先设置整个数组的步长,设置步长为数组的一半;
②继续将步长设置为原步长的一半;
③当步长为一时,结束。
代码:(以数组长度为10为例)
public static void main(String[] args) {
int[] arr=new int[] {5,9,2,1,7,6,3,4,8,0};
sort(arr);
System.out.println(Arrays.toString(arr));
}
//逐步写出整个希尔排序
public static void sort(int[] arr) {
//将10个数据划分为五组,定义一个i代指步长
for(int i=5;i<arr.length;i++) {
//j应该指向数组当中的第一个元素
for(int j=i-5; j>=0;j-=5) {
if(arr[j] >arr[j+5]) {
int temp=arr[j];
arr[j]=arr[j+5];
arr[j+5]=temp;
}
}
}
//将10个数据划分为2组,定义一个i代指步长
for(int i=2;i<arr.length;i++) {
//j应该指向数组当中的第一个元素
for(int j=i-2; j>=0;j-=2) {
if(arr[j] >arr[j+2]) {
int temp=arr[j];
arr[j]=arr[j+2];
arr[j+2]=temp;
}
}
}
//将10个数据划分为1组,定义一个i代指步长
for(int i=1;i<arr.length;i++) {
//j应该指向数组当中的第一个元素
for(int j=i-1; j>=0;j-=1) {
if(arr[j] >arr[j+1]) {
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
总体来看就是
public static void shell(int[] arr) {
//grp表示步长
for(int grp =arr.length/2;grp>0;grp/=2) {
//将10个数据划分为2组,定义一个i代指步长
for(int i=grp;i<arr.length;i++) {
//j应该指向数组当中的第一个元素
for(int j=i-grp; j>=0;j-=grp) {
if(arr[j] >arr[j+grp]) {
int temp=arr[j];
arr[j]=arr[j+grp];
arr[j+grp]=temp;
}
}
}
}
}
结果图
7.堆排序(大、小顶堆)
堆排序运用到完全二叉树(完全二叉树:从上到下,从左到右依次铺满)
堆排序是利用了平衡二叉树的一些特点来实现完全二叉树
堆排序的基本思想:
① 利用平衡二叉树的特点构建大、小顶堆;
② 将堆顶元素和最后一个元素进行位置互换;
③ 重复前两个步骤。
堆排序的步骤:
一、(arr.length-1)/2:最后一个拥有子树的节点
二、定义一个指针指向左右子树当中最大的一个
三、最大的子节点和父节点进行对比,如果子节点大于父节点,交换位置
四、将堆顶元素和最后一个元素进行位置互换
代码:
public class dui {
public static void main(String[] args) {
int[] arr=new int[] {5,9,2,1,7,6,3,4,8,0};
sort(arr);
System.out.println(Arrays.toString(arr));
}
public static void sort(int [] arr) {
//构建大顶堆
for(int i=(arr.length)/2;i>=0;i--) {
adjustHeap(arr,i,arr.length);
}
//将堆顶元素和最后一个元素进行位置互换
for(int i=arr.length-1;i>0;i--) {
int temp=arr[i];
arr[i]=arr[0];
arr[0]=temp;
//重新构建大顶堆
adjustHeap(arr,0,i);
}
}
public static void adjustHeap(int[] arr,int parent,int length){
int temp=arr[parent];
//定义左孩子,找到左孩子
int leftChild=2*parent+1;
while(leftChild<length) {
int rightChild=leftChild+1;
if(rightChild<length && arr[leftChild]<arr[rightChild]) {
leftChild=rightChild;
}
//判断父节点的值是否大于子节点的值
if(temp>=arr[leftChild]) {
break;
}
//否则子节点到父结点中去
arr[parent]=arr[leftChild];
//将选下来的原来父结点的值再次进行筛选
parent=leftChild;
leftChild=2*leftChild+1;
}
arr[parent]=temp;
}