折半插入排序算法基本思想:
折半插入排序算法是对直接插入排序算法的一种改进。在直接插入排序算法中,向有序序列中插入一个元素,插入位置是把待插入元素关键字与有序序列中元素的关键字逐个比较得到的。
折半插入排序算法的基本思想是:
向有序序列中插入元素,那么插入位置可以不断地平分有序序列,并把待插入的元素的关键字与平分有序序列的关键字比较,以确定下一步要平分的子序列,直到找到合适的插入位置位置。
注意先分析好折半插入排序的算法,然后再看代码:
/**折半[二分法]插入排序*/
public class BinaryInsertSort implements ISort {
private Element[] elements;
public BinaryInsertSort() {
// TODO Auto-generated constructor stub
}
public BinaryInsertSort(Element[] elements) {
// TODO Auto-generated constructor stub
this.elements = elements;
}
@Override
public void output() {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
if (elements!=null){
for (Element e : elements) {
System.out.println(e);
}
}
}
@Override
public void sort() {
// TODO Auto-generated method stub
if (elements==null || elements.length==0 || elements.length==1)
return;
//数组:2 9 5 3 2 1 10
//下标:0 1 2 3 4 5 6
for (int i = 1; i < elements.length; i++) {//整个循环都是为了找插入位置
int start = 0;
int end = i;
int mid = 0;
while(start<end){
//折半
mid = (start+end)/2;
//分三种情况讨论
//情况一:折半后的中间位置元素恰好等于当前元素
if (elements[mid].compareTo(elements[i])==0){
end = mid;
break;
}
//情况二:折半后的中间位置元素小于当前元素
if (elements[mid].compareTo(elements[i])<0){
start=mid+1;//修改搜索的起始下标继续搜索
continue;
}
//情况三:折半后的中间位置元素大于当前元素
if (elements[mid].compareTo(elements[i])>0){
end = mid;
}
}
//end就是要插入的位置
insertItem(elements,end,i);
}
}
@Override
public void sort(ISortCallBack sortCallBack) {
// TODO Auto-generated method stub
if (elements==null || elements.length==0 || elements.length==1)
return;
//数组:2 9 5 3 2 1 10
//下标:0 1 2 3 4 5 6
for (int i = 1; i < elements.length; i++) {//整个循环都是为了找插入位置
if (sortCallBack!=null)
sortCallBack.visit(elements[i]);
int start = 0;
int end = i;
int mid = 0;
while(start<end){
//折半
mid = (start+end)/2;
//分三种情况讨论
//情况一:折半后的中间位置元素恰好等于当前元素
if (elements[mid].compareTo(elements[i])==0){
end = mid;
break;
}
//情况二:折半后的中间位置元素小于当前元素
if (elements[mid].compareTo(elements[i])<0){
start=mid+1;//修改搜索的起始下标继续搜索
continue;
}
//情况三:折半后的中间位置元素大于当前元素
if (elements[mid].compareTo(elements[i])>0){
end = mid;
}
}
//end就是要插入的位置
insertItem(elements,end,i);
}
}
/**
*
* 将indexSrc元素插入到elements中的indexTarget位置,indexTarget位置之后的数向后移一位
* indexSrc应该大于indexTarget
* */
private void insertItem(Element[] elements,int indexTarget,int indexSrc){
if (elements==null ||
elements.length<=1 ||
indexTarget<0 ||
indexTarget>elements.length ||
indexSrc<0 ||
indexSrc>elements.length ||
indexSrc==indexTarget){
return;
}
Element e = elements[indexSrc];//记录下带插入的元素
for (int i = indexSrc; i > indexTarget; i--) {//插入位置后的元素依次后移
elements[i] = elements[i-1];
}
elements[indexTarget] = e;//插入这个元素
}
}
测试代码:
import org.pbdevj.ds.sort.insert.BinaryInsertSort;
import org.pbdevj.ds.sort.insert.Element;
import org.pbdevj.ds.sort.insert.ISort;
import org.pbdevj.ds.sort.insert.ISortCallBack;
import org.pbdevj.ds.sort.insert.InsertSort;
public class BinaryInsertSortTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Element[] elements=new Element[]{
new Element(90),
new Element(60),
new Element(70),
new Element(60),
new Element(70),
new Element(40),
new Element(90),
new Element(10)
};
ISort sort = new BinaryInsertSort(elements);
System.out.println("before sort....");
sort.output();
System.out.println("start sort.....");
sort.sort();
System.out.println("after sort...");
sort.output();
}
}