基本思想:将一个待排序的数插入到已排好序的关键字中,直到所有数排好。如 2 5 8 12 插入数7 则需要找到插入的位置即位置3,则需要移动8 12 移动元素后插入。
主要的排序算法:
说明:数组A[0]不放排序元素 从A[1]开始排序
1》直接插入排序算法
package suanfa;
public class InsertSort {
//核心算法
//A是待排序数组 n是表长
public void insertSort(int[] A,int n ){
int i,j;
for(i=2;i<=n;i++){
//待插入的数据A[i]大于A[i-1],则直接插入,反之则往前进行比较,
//选择合适的插入的位置
if(A[i]<A[i-1]){
//A[0]仅是哨兵
A[0]=A[i];
//边查找边移动位置
for(j=i-1;A[i]<A[j];j--){
A[j+1]=A[j];
}
//找到插入位置
A[j+1]=A[0];
}
}
}
//测试
public static void main(String[] args) {
int[] A={0,2,12,6,8,11,31,18,27};
int n =A.length-1;
InsertSort insertSort = new InsertSort();
insertSort.insertSort(A, n);
for(int i=0;i<=n;i++){
System.out.println(A[i]);
}
}
}
直接插入排序算法可以看出是边查找边移动位置 是否可以减少查找次数呢?
2》折半插入排序
选择一个待排序数插入一个序列时,这一个序列时有序的,那么就可以想到折半查找(测试代码都一样,这里只贴核心代码)
//核心算法
//A是待排序数组 n是表长
public void insertSort(int[] A,int n ){
int i,j,low,high,mid;
for(i=2;i<=n;i++){
A[0]=A[i];//将待排序数放到A[0]暂存
low=1;
high=i-1;
//1.先利用折半查找找到插入的位置(查找和移动位置是分开进行的)
while(low<=high){
mid=(low+high)/2;
if (A[mid]>A[0]) high=mid-1;
else low=low+1;
}
//2.找到插入位置,移动元素
for(j=i-1;j>=high+1;j--){
A[j+1]=A[j];
}
//2.将待排元素插入
A[high+1]=A[0];
}
}
与直接插入排序比较,只是减少了比较的次数,但是移动次数是没有变的
3》再说一种排序算法 希尔排序
什么是希尔排序算法:(自己理解的)希尔排序本质上就是直接插入排序,从一个例子来看:
希尔排序就是将原数组先划分为几个小组,分别排序,然后将增量减小再分组 ,再排序 直到增量为1,排序就完成了。所以希尔排序我们要知道增量怎么确定,一般增量d1=n/2;d2=d1/2;.......
//核心算法
//A是待排序数组 n是表长
public void ShellSort(int[] A,int n ){
int i,j,d;//d是增量
//注意和直接插入排序进行比较 实际上是多了一层for循环 这一层循环就是分组排序的次数
for(d=n/2;d>=1;d=d/2){
//这一个for循环和直接插入排序算法基本是一样的 (把d换成1)
for(i=d+1;i<=n;i++){
if(A[i]<A[i-d]){
A[0]=A[i];
for(j=i-d;j>0&&A[0]<A[j];j=j-d){
A[j+d]=A[j];
}
A[j+d]=A[0];
}
}
}
}
插入排序:找到插入位置---移动元素---插入元素 基本就是这三个步骤