package 第十章_内部排序;
public class 折半插入排序 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int a[] = {100,32,62,42,782,3432,322,62,82,92,22};
int dlta [] ={5,3,1};
ShellSort(a,dlta);
binaryInsertSort2(a);
for(int i:a)
System.out.print(i+"\t");
}
//折半插入排序
//折半插入排序和直接插入排序有点不同,直接插入排序直接从按第一个数位有序的从第2个数开始赋值给key并且从i-1位开始依次向前遍历当找到(j>0 && args[j] > key)时,此时要把j到i-1依次向后移动
//因为i位上的数已经被保存在key中,所以不存在被覆盖的情况
//而折半插入排序的过程是从第二位开始
//**************************************************************************
public static void binaryInsertSort2(int[] data) {
for (int i = 1; i < data.length; i++) {
if (data[i] < data[i - 1]) {
// 缓存i处的元素值
int tmp = data[i];
// 记录搜索范围的左边界
int low = 0;
// 记录搜索范围的右边界
int high = i - 1;
while (low <= high) {
// 记录中间位置
int mid = (low + high) / 2;
// 比较中间位置数据和i处数据大小,以缩小搜索范围
if (data[mid] < tmp) {
low = mid + 1;
} else {
high = mid - 1;
}
}
//将low~i处数据整体向后移动1位
for (int j = i; j > low; j--) {
data[j] = data[j - 1];
}
data[low] = tmp;
}
}
}
//**************************************************************************
//希尔排序
//希尔排序的思想:
/**
* 希尔排序实在插入排序的基础上进行的改进优化,因为插入排序在数量级比较小的情况下具有较好的效率,同时插入排序的实现也比较哦啊简单,所以希尔排序综合这两种情况,进行了
*思路:确定步长,可以通过一个二维数组将步长存储下来
* 通过步长交换数字,循环次数时存储二维数组的长度
*其实shell排序在与直接插入排序是差不多的,知识shell排序在每次的比较从相邻两个之间的比较直接跳转到相隔step个元素
*其中while(j>=0 && key < args[j])
*{
* args[j+step] = args[j];
* j-= step;
*}
*和while(j>=0 && key < args[j])
*{
* args[j+1] = args[j];
* j--;
*}
*完全相似,只是在step = 1 时参数完全一样
*/
//**************************************************************************
/**
*
* @param arr 用于排序的数组
* @param stepLength 步长 ,即增量序列
* 希尔排序应为跨幅比较大,所以也是不稳定排序
*/
public static void shellInsert(int arr[],int stepLength){
/**
* i = stepLength 在循环开始时,将i的位置直到合适的位置,此时与arr[i]作比较的另一个数组元素的下标便是arr[i - stepLength]
* 例如如下序列:
* 49 38 65 97 76 13 27 49 55 04 假设步长为5,那么此时arr[i] = 13 那么另一个55值便是arr[i - stepLength] = arr[0]=49
*/
for(int i= stepLength;i<arr.length;i++)
{
if(arr[i] < arr[i-stepLength])//13 < 49
{
int key = arr[i];//key = 1356555
int j = i - stepLength;//j = 5 - 5 = 0
while(j >= 0 && key < arr[j])//arr[j] = arr[0] = 49
{
arr[j+stepLength] = arr[j]; //arr[j+stepLength] = arr[0+5]= key = 13
j -= stepLength;//j=-5
}
arr[j+stepLength] = key;
}
}
}
public static void shell(int args[],int step)
{
for(int i=0;i<args.length;i++)
{
if(args[i] < args[i+step])
{
int key = args[i];
int j = i - step;
while(j>= 0 && key < args[j])
{
j -= step;
}
args[j+step] = key;
}
}
}
public static void ShellSort(int [] arr,int dlta[])
{
//按增量序列dlta[0 .... t-1]对顺序表进行希尔排序
for(int k = 0;k < dlta.length;k++)//步长所组成的二维数组将作为循环的次数
{
shellInsert(arr,dlta[k]);//将步长传入到进行计算
}
}
}
public class 折半插入排序 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int a[] = {100,32,62,42,782,3432,322,62,82,92,22};
int dlta [] ={5,3,1};
ShellSort(a,dlta);
binaryInsertSort2(a);
for(int i:a)
System.out.print(i+"\t");
}
//折半插入排序
//折半插入排序和直接插入排序有点不同,直接插入排序直接从按第一个数位有序的从第2个数开始赋值给key并且从i-1位开始依次向前遍历当找到(j>0 && args[j] > key)时,此时要把j到i-1依次向后移动
//因为i位上的数已经被保存在key中,所以不存在被覆盖的情况
//而折半插入排序的过程是从第二位开始
//**************************************************************************
public static void binaryInsertSort2(int[] data) {
for (int i = 1; i < data.length; i++) {
if (data[i] < data[i - 1]) {
// 缓存i处的元素值
int tmp = data[i];
// 记录搜索范围的左边界
int low = 0;
// 记录搜索范围的右边界
int high = i - 1;
while (low <= high) {
// 记录中间位置
int mid = (low + high) / 2;
// 比较中间位置数据和i处数据大小,以缩小搜索范围
if (data[mid] < tmp) {
low = mid + 1;
} else {
high = mid - 1;
}
}
//将low~i处数据整体向后移动1位
for (int j = i; j > low; j--) {
data[j] = data[j - 1];
}
data[low] = tmp;
}
}
}
//**************************************************************************
//希尔排序
//希尔排序的思想:
/**
* 希尔排序实在插入排序的基础上进行的改进优化,因为插入排序在数量级比较小的情况下具有较好的效率,同时插入排序的实现也比较哦啊简单,所以希尔排序综合这两种情况,进行了
*思路:确定步长,可以通过一个二维数组将步长存储下来
* 通过步长交换数字,循环次数时存储二维数组的长度
*其实shell排序在与直接插入排序是差不多的,知识shell排序在每次的比较从相邻两个之间的比较直接跳转到相隔step个元素
*其中while(j>=0 && key < args[j])
*{
* args[j+step] = args[j];
* j-= step;
*}
*和while(j>=0 && key < args[j])
*{
* args[j+1] = args[j];
* j--;
*}
*完全相似,只是在step = 1 时参数完全一样
*/
//**************************************************************************
/**
*
* @param arr 用于排序的数组
* @param stepLength 步长 ,即增量序列
* 希尔排序应为跨幅比较大,所以也是不稳定排序
*/
public static void shellInsert(int arr[],int stepLength){
/**
* i = stepLength 在循环开始时,将i的位置直到合适的位置,此时与arr[i]作比较的另一个数组元素的下标便是arr[i - stepLength]
* 例如如下序列:
* 49 38 65 97 76 13 27 49 55 04 假设步长为5,那么此时arr[i] = 13 那么另一个55值便是arr[i - stepLength] = arr[0]=49
*/
for(int i= stepLength;i<arr.length;i++)
{
if(arr[i] < arr[i-stepLength])//13 < 49
{
int key = arr[i];//key = 1356555
int j = i - stepLength;//j = 5 - 5 = 0
while(j >= 0 && key < arr[j])//arr[j] = arr[0] = 49
{
arr[j+stepLength] = arr[j]; //arr[j+stepLength] = arr[0+5]= key = 13
j -= stepLength;//j=-5
}
arr[j+stepLength] = key;
}
}
}
public static void shell(int args[],int step)
{
for(int i=0;i<args.length;i++)
{
if(args[i] < args[i+step])
{
int key = args[i];
int j = i - step;
while(j>= 0 && key < args[j])
{
j -= step;
}
args[j+step] = key;
}
}
}
public static void ShellSort(int [] arr,int dlta[])
{
//按增量序列dlta[0 .... t-1]对顺序表进行希尔排序
for(int k = 0;k < dlta.length;k++)//步长所组成的二维数组将作为循环的次数
{
shellInsert(arr,dlta[k]);//将步长传入到进行计算
}
}
}