目录
插入排序:
基本思想:
每一趟将一个待排序的数,按照它的大小插入到已经排好序的一组数组的适当位置上,直到所有数排序完成。例如你斗地主会理牌吧,过程相同,原理一样。
根据查找方法的不同,大致分为了三种:1:直接插入排序.2:折半插入排序.3:希尔排序.
1:直接插入排序:
基本思想:
顾名思义,就是直接把一个数插入到已经排好的有序表中,查找插入位置方法为顺序查找,从而得到一个新的有序表,直到所有数字排序完成。
过程:
先来看一张图:
在实现插入时我们可以选择从小到大比较,也可以选择从大到小比较,图例所示就是从大到小比较的顺序。
代码实现:
import java.util.Arrays;
public class InsertSort {
public static void main(String[] args){
int[] a={12,15,9,20,6,31,24};
Sort(a);//调用方法
}
public static void Sort(int[] s){
for (int i=1;i< s.length;i++){//注意i不能等于数组长度,因为数组下标从零开始而不是从1.
int temp=s[i];//存储待插入数的数值
int j;//j必须在此声明,如果在for循环内声明,j就不能拿出for循环使用,最后一步插入就无法执行
for (j=i-1;j>=0&&temp<s[j];j--){
s[j+1]=s[j];//如果大于temp,往前移动一个位置
}
s[j+1]=temp;//将temp插入到适当位置
}
System.out.println(Arrays.toString(s));//输出排好序的数组
}
}
结果:
时间复杂度:
空间复杂度:
算法特点:
(1):稳定排序。
(2):算法简便,且容易实现。
(3):更适合于初始记录基本有序(正序)的情况,初始记录无序,n较大,时间复杂度高,不宜采用。
2:折半插入排序:
基本思想:
在直接插入排序的基础上,将查找方法从顺序查找改为折半查找,就是在将 将要插入到现有 有序序列的数字寻找适当插入位置的比较次数减少了。
过程:
代码实现:
import java.util.Arrays;
public class BinsertSort {
public static void main(String[] args){
int[] a={2,6,3,8,1,4,2,7};
BInsertSort(a);//调用方法
}
private static void BInsertSort(int[] s){
for(int i=1;i<s.length;i++){
int temp=s[i];//保存要插入的数的数值
int low=0;//设置查找区间初始值 下区间值
int high=i-1;//上区间值
while(low<=high){//查找结束条件
int mid=(high+low)/2;//折半,中间值
if(s[mid]>temp){//待插入值小于中间值
high=mid-1;//上区间值变为中间值-1
}
else {//待插入值大于中间值
low=mid+1;//下区间值变为中间值+1
}
}
for (int j=i-1;j>=low;j--){
s[j+1]=s[j];//将low及low之前的数向前移动一位
}
s[low]=temp;//low就是待插入值的适当插入点
}
System.out.println(Arrays.toString(s));//输出排好序的数组
}
}
结果:
时间复杂度:
空间复杂度:
算法特点:
(1):稳定排序。
(2):适合初始记录无序,n较大的情况。
3:希尔排序:
基本思想:
又称“缩小增量排序”(Diminishing Increment Sort),因D.LShell于1959年提出而得名。实质上是采用分组插入的方法,先将整个待排序数组分割成几组,在对每组采用直接插入排序,然后再增加每组的数据量,重新分组,再直接插入排序,直到增量为1,再对整体进行一次直接插入排序。
过程:
先来看一张书上的图:
增量分别为:5,3,1。
代码实现:
import java.util.Arrays;
public class ShellSort {
public static void main(String[] args) {
int[] a={2,6,3,8,1,4,2,7};
Shellsort(a);//调用方法
}
public static void Shellsort(int[] s){
int zl=s.length/2;//设置增量为数组长度的1/2
for (;zl>0;zl=zl/2){//增量依次减少为1/2
for (int i=zl;i<s.length;i++){//对相应增量的数组分组进行直接插入排序
int temp=s[i];
int j;
for (j=i-zl;j>=0&&temp<s[j];j-=zl){//注意这里必须将j的初值设置为i-zl,否则数组下标会出界(也就是为负数)
s[j+zl]=s[j];
}
s[j+zl]=temp;
}
}
System.out.println(Arrays.toString(s));//输出排好序的数组
}
}
结果:
时间复杂度:(最好情况) (最坏情况)
空间复杂度:
算法特点:
(1):不稳定排序(数据跳跃式移动)。
(2):增量有各种取法,最后一个增量值必须为1。
(3):适合初始记录无序,n较大的情况。