二分法排序

算法思想简单描述:

在插入第i个元素时,对前面的0~i-1元素进行折半,先跟他们 中间的那个元素比,

如果小,则对前半再进行折半,否则对后半 进行折半,直到left>right,

然后再把第i个元素前1位与目标位置之间 的所有元素后移,再把第i个元素放在目标位置上。


二分法排序最重要的一个步骤就是查找要插入元素的位置,

也就是要在哪一个位置上放我们要准备排序的这个元素。

当我们查找到位置以后就很好说了,和插入排序一样,

将这个位置以后的所有元素都向后移动一位。这样就实现了二分法排序。

然后是怎么查找着一个位置呢,就是不断的比较已排序的序列中的中间元素和要排序元素,

如果中间元素大于要排序元素的话,说明这个要排序的元素在已排序序列中点之前的序列。

public static void DichotomySort(int[] array)
{ 
  for (int i = 0; i < array.Length; i++)
  { 
    int start, end, mid;
    start = 0;
    end = i - 1;
    mid = 0;
    int temp = array[i];
    while (start <= end)
    { 
      mid = (start + end) / 2;
      if (array[mid] > temp) //要排序元素在已经排过序的数组前半部分
      { 
        end = mid - 1;
      }
      else                   // 要排序元素在已经排序的数组后半部分
      { 
        start = mid + 1;
      }
    }
for (int j = i - 1; j > end; j--) //找到了要插入的位置,然后将这个位置以后的所有元素向后移动 { array[j + 1] = array[j]; } array[end + 1] = temp; } }
二分插入排序实际上是对插入排序的优化。
(1)算法思想
根据插入排序的思想,在插入待排序列的第i个元素时,由于前面的序列已经有序,因此可以使用二分法寻找第i个元素的正确位置。
(2)伪代码:
BinInsertSort( int a[ ], int n )
{
  int key, left, right, middle;
  for ( int i = 1; i < n; i++ )
  {
    key = a[ i ];
    left = 0;
    right = i - 1;
    while ( left <= right )
    {
      middle = ( left + right ) / 2;
      if ( a[ middle ] > key )
        right = middle - 1;
      else
        left = middle + 1;
    }
    
    for ( int j = i - 1; j >= left; j-- )
    {
      a[ j + 1 ] = a[ j ];
    }
    
    a[ left ] = key;
  }
}

 

折半插入排序其实就是直接插入排序的一种改进,引入了二分查找算法,这样关键字的比较次数就会减少,

数量级为O(nlog^2n),但是元素移动次数还是O(n^2),所以折半插入排序的时间复杂度是O(n^2)。

另外,折半插入排序是稳定的排序算法;下面是用JAVA写的算法的两种实现方式。不过原理都是一样的

import java.util.Arrays;

public class BinarySearch1
{ 
  public static void main(String args[])
  { 
    int array[]=
    { 49,38,65,97,76,13,27};
    binarySort(array,array.length);
    System.out.println("---------排序后的结果----------");
    System.out.println(Arrays.toString(array));
  }

  //二分查找
  public static int binarySearch(int array[],int low,int high,int temp)
  { 
    int mid=0;
    while(low<=high)
    { 
      mid=(low+high)/2;
      if(array[mid]<temp&&temp<=array[mid+1])
      return (mid+1);
      else if(array[mid]<temp)
      low = mid + 1;
      else
      high = mid -1;
    }
    return high;
  }

  //二分排序
  public static void binarySort(int array[],int size)
  { 
    int i,j,k,temp;
    for(i=1;i<size;i++)
    { 
      temp=array[i];
      if(array[i]<array[0])
      k=0;
      else
      k = binarySearch(array,0,i,temp);

      for(j=i;j>k;j--)
      { 
        array[j]=array[j-1];
      }
      array[k]=temp;
      System.out.println(Arrays.toString(array));
    }
  }
} 
[38, 49, 65, 97, 76, 13, 27]
[38, 49, 65, 97, 76, 13, 27]
[38, 49, 65, 76, 97, 13, 27]
[13, 38, 49, 65, 76, 97, 27]
[13, 27, 38, 49, 65, 76, 97]
---------排序后的结果----------
[13, 27, 38, 49, 65, 76, 97]

 

package sort;

import java.util.Arrays;

public class BinarySearch2
{ 
  public static void main(String args[])
  { 
    int array[]=
    { 49,38,65,97,76,13,27};
    binaryInsertSort(array,array.length);
    System.out.println("------------排序后的结果-------------");
    System.out.println(Arrays.toString(array));
  }

  /**
   * 
   * @param array 要排序的数组
   * @param size 数组的大小
   */
  public static void binaryInsertSort(int []array,int size)
  { 
    int i,j,temp;
    int low,high,mid;
    for(i=1;i<size;i++)
    { 
      //将待插入的元素赋给temp,这个元素前面是有序数组,用于插入到有序数组中
      temp=array[i];
      low=0;
      high=i-1;
      while(low<=high)
      { 
        //有序数组的中间坐标,此时用于二分查找,减少查找次数
        mid = (low+high)/2;
        //如果有序序列中的中间元素大于待排序的元素,则有序序列的中间坐标向前搜索,否则向后搜索
        if(array[mid]>array[i])
        high=mid-1;
        else
        low = mid + 1;
      }
      /**
       * j首先赋值为要插入值的前一个元素的最后的坐标,也就是有序数组中最后一个元素的坐标
       * 然后依次向前扫描有序数组,然后如果满足条件则向后移动数据
       */

      for(j=i-1;j>=low;j--)
      { 
        array[j+1]=array[j];
      }
      //将待排序的元素插入到array数组中
      array[low]=temp;
      System.out.println(Arrays.toString(array));
    }
  }
} 
[38, 49, 65, 97, 76, 13, 27]
[38, 49, 65, 97, 76, 13, 27]
[38, 49, 65, 97, 76, 13, 27]
[38, 49, 65, 76, 97, 13, 27]
[13, 38, 49, 65, 76, 97, 27]
[13, 27, 38, 49, 65, 76, 97]
------------排序后的结果-------------
[13, 27, 38, 49, 65, 76, 97]

 

posted @ 2015-08-10 23:00  IAmAProgrammer  阅读(1513)  评论(0编辑  收藏  举报