希尔排序并非是一种单纯的排序方法,而是一种对其他排序方法进行优化处理
对于冒泡,选择,插入三种排序方法,所用的时间复杂度都是O(n^2)
这对于大量数据来说太慢,希尔排序,排序方法用的是这三类,但降低了n,这使得排序速度大大加快
希尔是将整个数据划分成gap组,分别对这gap组进行排序
一次排序后,虽然整体还是无序的,但在各组是有序的,其整体相对之前较有序
并再对整体划分gap-组,使之整体更加有序,直到gap=1时(实际就是其他排序法)
但是因为数据经过几轮分组排序后,是较为有序的,而对冒泡,选择,插入来说
一个较为有序的序列排序起来比无序 效率要高得多,因此降低了时间
//希尔-二分插入
//希尔-选择
//希尔-冒泡
下面代码只是实现重载:
对于冒泡,选择,插入三种排序方法,所用的时间复杂度都是O(n^2)
这对于大量数据来说太慢,希尔排序,排序方法用的是这三类,但降低了n,这使得排序速度大大加快
希尔是将整个数据划分成gap组,分别对这gap组进行排序
一次排序后,虽然整体还是无序的,但在各组是有序的,其整体相对之前较有序
并再对整体划分gap-组,使之整体更加有序,直到gap=1时(实际就是其他排序法)
但是因为数据经过几轮分组排序后,是较为有序的,而对冒泡,选择,插入来说
一个较为有序的序列排序起来比无序 效率要高得多,因此降低了时间
gap一般以二分递减
//希尔分组
public void shellSort(double[] a,int type){
//希尔优化的分组次数,以gap=a.length/2开始,每次半分
for (int gap = a.length/2; gap >= 1;gap=gap/2) {
//开始组内排序
//1冒泡排序
//bubbleSort(a, type, gap);
//2选择排序
//selectSort(a, type, gap);
//3插入排序
insertSort(a, type, gap);
}
}
//希尔-二分插入
private void insertSort(double[] a, int type, int gap) {
//gap组要插入多少次?
//对插入来说,一次插一数,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
//所以共选(a.length/gap-1)*gap次,及a.length-gap次
for (int i = 0; i < a.length-gap; i++) {
//对于每一组组内插入
//即进行一般的插入即可(二分优化),每一组的第一个数为a[0]~a[gap-1]
//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每选一次,确定一个,使每组前序有序
double temp=a[i+gap];//对a[i+gap]插排
int low=i%gap;//该组第一个数下标
int high=i;//该组最后一个数下标
int mid;
while(low<=high){//定位
mid=i%gap+(low/gap+high/gap)/2*gap;//二分
if(type==0){
if(a[mid]>temp)
high=mid-gap;
else
low=mid+gap;
}else{
if(a[mid]<temp)
high=mid-gap;
else
low=mid+gap;
}
}
//移动
for (int k = i; k >= high+gap; k-=gap) {
a[k+gap]=a[k];
}
//插入
a[high+gap]=temp;
}
}
//希尔-选择
private void selectSort(double[] a, int type, int gap) {
//gap组要选择多少次?
//对选择来说,一次选到一数,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
//所以共选(a.length/gap-1)*gap次,及a.length-gap次
for (int i = 0; i < a.length-gap; i++) {
//对于每一组组内选择
//即进行一般的选择即可,每一组的第一个数为a[0]~a[gap-1]
//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每选一次,确定一个,使每组前序有序且比后面都小/大
int h=i;
for (int j = i; j < a.length-gap; j+=gap) {
if(type==0){
if(a[h]>a[j+gap]){
h=j+gap;
}
}else{
if(a[h]<a[j+gap]){
h=j+gap;
}
}
}
if(h!=i)
swap(a, h, i);
}
}
//希尔-冒泡
private void bubbleSort(double[] a, int type, int gap) {
//gap组要冒泡多少次?
//对冒泡来说,一次冒一泡,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
//所以共冒(a.length/gap-1)*gap次,及a.length-gap次
for (int i = 0; i < a.length-gap; i++) {
//对于每一组组内冒泡排序
//即进行一般的冒泡即可
//每一组的第一个数为a[0]~a[gap-1]
//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每冒一次,确定一个,即每组后序有序且比前面都小/大
//优化gap==1时
boolean isSwap=true;
//只有当1时才false,因为之前若一组有序就跳出,则到gap==1时,还是较无序的,相当于普通冒泡
if(gap==1)
isSwap=false;
for (int j =i%gap; j < a.length-gap-i; j+=gap) {
if(type==0){
if(a[j]>a[j+gap]){
swap(a,j,j+gap);
isSwap=true;
}
}else{
if(a[j]<a[j+gap]){
swap(a,j,j+gap);
isSwap=true;
}
}
}
if(!isSwap)
break;
}
}
下面代码只是实现重载:
package cn.hncu.sort;
public class ShellSort {
// 希尔排序并非是一种单纯的排序方法,而是一种对其他排序方法进行优化处理
// 对于冒泡,选择,插入三种排序方法,所用的时间复杂度都是O(n^2)
// 这对于大量数据来说太慢,希尔排序,排序方法用的是这三类,但降低了n,这使得排序速度大大加快
// 希尔是将整个数据划分成gap组,分别对这gap组进行排序
// 一次排序后,虽然整体还是无序的,但在各组是有序的,其整体相对之前较有序
// 并再对整体划分gap-组,使之整体更加有序,直到gap=1时(实际就是其他排序法)
// 但是因为数据经过几轮分组排序后,是较为有序的,而对冒泡,选择,插入来说
// 一个较为有序的序列排序起来比无序 效率要高得多,因此降低了时间
// gap一般以二分递减
public void shellSort(double[] a,int type){
//希尔优化的分组次数,以gap=a.length/2开始,每次半分
for (int gap = a.length/2; gap >= 1;gap=gap/2) {
//开始组内排序
//1冒泡排序
//bubbleSort(a, type, gap);
//2选择排序
//selectSort(a, type, gap);
//3插入排序
insertSort(a, type, gap);
}
}
private void insertSort(double[] a, int type, int gap) {
//gap组要插入多少次?
//对插入来说,一次插一数,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
//所以共选(a.length/gap-1)*gap次,及a.length-gap次
for (int i = 0; i < a.length-gap; i++) {
//对于每一组组内插入
//即进行一般的插入即可(二分优化),每一组的第一个数为a[0]~a[gap-1]
//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每选一次,确定一个,使每组前序有序
double temp=a[i+gap];//对a[i+gap]插排
int low=i%gap;//该组第一个数下标
int high=i;//该组最后一个数下标
int mid;
while(low<=high){//定位
mid=i%gap+(low/gap+high/gap)/2*gap;//二分
if(type==0){
if(a[mid]>temp)
high=mid-gap;
else
low=mid+gap;
}else{
if(a[mid]<temp)
high=mid-gap;
else
low=mid+gap;
}
}
//移动
for (int k = i; k >= high+gap; k-=gap) {
a[k+gap]=a[k];
}
//插入
a[high+gap]=temp;
}
}
private void selectSort(double[] a, int type, int gap) {
//gap组要选择多少次?
//对选择来说,一次选到一数,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
//所以共选(a.length/gap-1)*gap次,及a.length-gap次
for (int i = 0; i < a.length-gap; i++) {
//对于每一组组内选择
//即进行一般的选择即可,每一组的第一个数为a[0]~a[gap-1]
//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每选一次,确定一个,使每组前序有序且比后面都小/大
int h=i;
for (int j = i; j < a.length-gap; j+=gap) {
if(type==0){
if(a[h]>a[j+gap]){
h=j+gap;
}
}else{
if(a[h]<a[j+gap]){
h=j+gap;
}
}
}
if(h!=i)
swap(a, h, i);
}
}
private void bubbleSort(double[] a, int type, int gap) {
//gap组要冒泡多少次?
//对冒泡来说,一次冒一泡,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
//所以共冒(a.length/gap-1)*gap次,及a.length-gap次
for (int i = 0; i < a.length-gap; i++) {
//对于每一组组内冒泡排序
//即进行一般的冒泡即可
//每一组的第一个数为a[0]~a[gap-1]
//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每冒一次,确定一个,即每组后序有序且比前面都小/大
//优化gap==1时
boolean isSwap=true;
//只有当1时才false,因为之前若一组有序就跳出,则到gap==1时,还是较无序的,相当于普通冒泡
if(gap==1)
isSwap=false;
for (int j =i%gap; j < a.length-gap-i; j+=gap) {
if(type==0){
if(a[j]>a[j+gap]){
swap(a,j,j+gap);
isSwap=true;
}
}else{
if(a[j]<a[j+gap]){
swap(a,j,j+gap);
isSwap=true;
}
}
}
if(!isSwap)
break;
}
}
//默认从小到大排
public void shellSort(double[] a){
shellSort(a,0);
}
//对某一段排序
public boolean shellSort(double[] a,int first,int end,int type){
if(first<0)
return false;
if(end>=a.length)
return false;
if(first>end)
return false;
double[] b=new double[end-first+1];
System.arraycopy(a, first, b, 0, b.length);
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[first+i]=b[i];
}
return true;
}
public boolean shellSort(double[] a,int first,int end){
return shellSort(a, first, end, 0);
}
//float[]数组
public void shellSort(float[] a,int type){
double[] b=new double[a.length];
for (int i = 0; i < b.length; i++) {
b[i]=a[i];
}
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[i]=(float)b[i];
}
}
public void shellSort(float[] a){
shellSort(a, 0);
}
public boolean shellSort(float[] a,int first,int end,int type){
if(first<0)
return false;
if(end>=a.length)
return false;
if(first>end)
return false;
float[] b=new float[end-first+1];
System.arraycopy(a, first, b, 0, b.length);//截取
shellSort(b, type);//排序
for (int i = 0; i < b.length; i++) {//放回
a[first+i]=b[i];
}
return true;
}
public boolean shellSort(float[] a,int first,int end) {
return shellSort(a, first, end, 0);
}
//long[]数组
public void shellSort(long[] a,int type){
double[] b=new double[a.length];
for (int i = 0; i < b.length; i++) {
b[i]=a[i];
}
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[i]=(long)b[i];
}
}
public void shellSort(long[] a){
shellSort(a, 0);
}
public boolean shellSort(long[] a,int first,int end,int type){
if(first<0)
return false;
if(end>=a.length)
return false;
if(first>end)
return false;
long[] b=new long[end-first+1];
System.arraycopy(a, first, b, 0, b.length);
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[first+i]=b[i];
}
return true;
}
public boolean shellSort(long[] a,int first,int end) {
return shellSort(a, first, end, 0);
}
//int[]数组
public void shellSort(int[] a,int type){
double[] b=new double[a.length];
for (int i = 0; i < b.length; i++) {
b[i]=a[i];
}
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[i]=(int)b[i];
}
}
public void shellSort(int[] a){
shellSort(a, 0);
}
public boolean shellSort(int[] a,int first,int end,int type){
if(first<0)
return false;
if(end>=a.length)
return false;
if(first>end)
return false;
int[] b=new int[end-first+1];
System.arraycopy(a, first, b, 0, b.length);
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[first+i]=b[i];
}
return true;
}
public boolean shellSort(int[] a,int first,int end) {
return shellSort(a, first, end, 0);
}
//short[]数组
public void shellSort(short[] a,int type){
double[] b=new double[a.length];
for (int i = 0; i < b.length; i++) {
b[i]=a[i];
}
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[i]=(short)b[i];
}
}
public void shellSort(short[] a){
shellSort(a, 0);
}
public boolean shellSort(short[] a,int first,int end,int type){
if(first<0)
return false;
if(end>=a.length)
return false;
if(first>end)
return false;
short[] b=new short[end-first+1];
System.arraycopy(a, first, b, 0, b.length);
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[first+i]=b[i];
}
return true;
}
public boolean shellSort(short[] a,int first,int end) {
return shellSort(a, first, end, 0);
}
//byte[]数组
public void shellSort(byte[] a,int type){
double[] b=new double[a.length];
for (int i = 0; i < b.length; i++) {
b[i]=a[i];
}
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[i]=(byte)b[i];
}
}
public void shellSort(byte[] a){
shellSort(a, 0);
}
public boolean shellSort(byte[] a,int first,int end,int type){
if(first<0)
return false;
if(end>=a.length)
return false;
if(first>end)
return false;
byte[] b=new byte[end-first+1];
System.arraycopy(a, first, b, 0, b.length);
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[first+i]=b[i];
}
return true;
}
public boolean shellSort(byte[] a,int first,int end) {
return shellSort(a, first, end, 0);
}
//char[]数组
public void shellSort(char[] a,int type){
double[] b=new double[a.length];
for (int i = 0; i < b.length; i++) {
b[i]=a[i];
}
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[i]=(char)b[i];
}
}
public void shellSort(char[] a){
shellSort(a, 0);
}
public boolean shellSort(char[] a,int first,int end,int type){
if(first<0)
return false;
if(end>=a.length)
return false;
if(first>end)
return false;
char[] b=new char[end-first+1];
System.arraycopy(a, first, b, 0, b.length);
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[first+i]=b[i];
}
return true;
}
public boolean shellSort(char[] a,int first,int end) {
return shellSort(a, first, end, 0);
}
//String[]数组
public void shellSort(String[] a,int type){
for (int gap = a.length/2; gap >= 1;gap=gap/2) {
//开始组内排序
//1冒泡排序
//bubbleSort(a, type, gap);
//2选择排序
//selectSort(a, type, gap);
//3插入排序
insertSort(a, type, gap);
}
}
private void insertSort(String[] a, int type, int gap) {
//gap组要插入多少次?
//对插入来说,一次插一数,整体为一组的话即a.length-1次,但对于分组来说,每一组要冒a.length/gap-1次
//所以共选(a.length/gap-1)*gap次,及a.length-gap次
for (int i = 0; i < a.length-gap; i++) {
//对于每一组组内插入
//即进行一般的插入即可(二分优化),每一组的第一个数为a[0]~a[gap-1]
//比较比组内 及:a[j]比a[j+gap],故j+gap<a.length 不能越界并且每选一次,确定一个,使每组前序有序
String temp=a[i+gap];//对a[i+gap]插排
int low=i%gap;//该组第一个数下标
int high=i;//该组最后一个数下标
int mid;
while(low<=high){//定位
mid=i%gap+(low/gap+high/gap)/2*gap;//二分
if(type==0){
if(a[mid].compareTo(temp)>0)
high=mid-gap;
else
low=mid+gap;
}else{
if(a[mid].compareTo(temp)<0)
high=mid-gap;
else
low=mid+gap;
}
}
//移动
for (int k = i; k >= high+gap; k-=gap) {
a[k+gap]=a[k];
}
//插入
a[high+gap]=temp;
}
}
//默认从小到大排
public void shellSort(String[] a){
shellSort(a, 0);
}
//对某一段排序
public boolean shellSort(String[] a,int first,int end,int type){
if(first<0)
return false;
if(end>=a.length)
return false;
if(first>end)
return false;
String[] b=new String[end-first+1];
System.arraycopy(a, first, b, 0, b.length);
shellSort(b, type);
for (int i = 0; i < b.length; i++) {
a[first+i]=b[i];
}
return true;
}
public boolean shellSort(String[] a,int first,int end) {
return shellSort(a, first, end, 0);
}
//交换
private void swap(double[] a, int j, int i) {
//借助第三变量
double temp=a[i];
a[i]=a[j];
a[j]=temp;
//不借助第三变量
//1
// a[i]=a[i]+a[j];
// a[j]=a[i]-a[j];
// a[i]=a[i]-a[j];
//2
// a[i]=a[i]^a[j];
// a[j]=a[i]^a[j];
// a[i]=a[i]^a[j];
}
private void swap(String[] a, int j, int i) {
String temp=a[i];
a[i]=a[j];
a[j]=temp;
}
//输出
private static void print(String[] a) {
for (String x : a) {
System.out.print(x+" ");
}
System.out.println();
}
private static void print(double[] a) {
for (double x : a) {
System.out.print(x+" ");
}
System.out.println();
}
private static void print(float[] a) {
for (float x : a) {
System.out.print(x+" ");
}
System.out.println();
}
private static void print(long[] a) {
for (long x : a) {
System.out.print(x+" ");
}
System.out.println();
}
private static void print(int[] a) {
for (int x : a) {
System.out.print(x+" ");
}
System.out.println();
}
private static void print(short[] a) {
for (short x : a) {
System.out.print(x+" ");
}
System.out.println();
}
private static void print(byte[] a) {
for (byte x : a) {
System.out.print(x+" ");
}
System.out.println();
}
private static void print(char[] a) {
for (char x : a) {
System.out.print(x+" ");
}
System.out.println();
}
}