欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

二分插入法

程序员文章站 2022-07-13 16:45:05
...

二分插入法每次看都无法一次理解清楚,在这里做一次笔记加深下印象。

一、Java代码如下所示:

 

public static void main(String[] args) {
		int [] values = new int[]{3,8,7,6,1,9,12,2,5,11};
		for(int i = 0 ; i < values.length ; i++){
			System.err.print(values[i] + ",");
		}
		System.err.println();
		sort(values);
		System.err.println();
		for(int i = 0 ; i< values.length; i++){
			System.err.print(values[i] + ",");
		}
	}
	public static void sort(int []  values){
		for(int i = 0 ;i < values.length ; i++)       //步骤1
			int now =  values[i];
			int left = 0;
			int right = i -1;
			int center = 0;
			while(left <= right){                //步骤2
				center = (left + right)/2;
				if(now < values[center]){    //步骤2.1
					right = center -1;
				}else{                       //步骤2.2
					 left = center + 1;
				}
			}
			for(int j = i-1 ;j >= left ; j--){   //步骤4  4.1  4.2
				 values[j+1] = values[j];
			}
			if(left != i){                       //步骤5 5.1  5.2
				 values[left] = now;
			}
		}
	}

 输出结果:

 

 

3,8,7,6,1,9,12,2,5,11,

1,2,3,5,6,7,8,9,11,12,

 

二、简单举例说一下当I=4时代码执行过程 ,详细过程如下图所示:

 

在i = 0、1、2、3执行完以后,values的顺序就变成如下列表:

        3, 6, 7, 8, 1, 9, 12, 2, 5, 11

 

此时当i=4初进循环时:

         now = 1 ; left = 0 ; right = 3 ; center = 0;

 

left (1) <= right (3) 进入while循环:

        center(1) = (left(0) + right(3))/2;

 

now(1) < values[center] (6)进入if:

       right(2) = right(3) - 1;

 

left (1) <= right (2)进入while循环:

       center(1) = (left(0) + right(2))/2;

 

now(1) < values[center] (6)进入if:

      right(1) = right(2) - 1;

 

left (1) <= right (1)进入while循环:

       center(0) = (left(0) + right(1))/2;

 

now(1) < values[center] (3)进入if:

        right(0) = right(1) - 1;

 

left (0) <= right (0)进入while循环:

        center(0) = (left(0) + right(1))/2;

 

now(1) < values[center] (3)进入if:

         right(-1) = right(0) - 1;

 

left (0) <= right (-1)跳出while循环:

        center = 0 ; left = 0 ; right=-1; now = 1; 

 

j(3)=i(4)-1 >= left(0) 进入For循环:

       values[j(3)+1] = values[j(3)];

       valus = 3, 6, 7, 8, 8, 9, 12, 2, 5, 11;

 

j(2)=i(4)-1-1 >= left(0) 进入For循环:

       values[j(2)+1] = values[j(2)];

       valus = 3, 6, 7, 7, 8, 9, 12, 2, 5, 11;

 

j(1)=i(4)-1-1-1 >= left(0) 进入For循环:

       values[j(1)+1] = values[j(1)];

       valus = 3, 6, 6, 7, 8, 9, 12, 2, 5, 11;

 

j(0)=i(4)-1-1-1-1 >= left(0) 进入For循环:

       values[j(0)+1] = values[j(0)];

       valus = 3, 3, 6, 7, 8, 9, 12, 2, 5, 11;

 

i(4) != left(0) 进入if:

       now=1 一直没变;

      values[left(0)] =now(1)

      valus = 1, 3, 6, 7, 8, 9, 12, 2, 5, 11

 

 接下来进入当I=5的循环,过程同上。

 

 

 

三、执行流程分析说明:

 

1、对排序数组values进行从索引0进行递增循环,初入循环始终将左索引(left)设置为0,右索引(right)设置为当前索引向左移一位(i-1),并将当前索引(i)对应数组的值赋值给循环内局部变量now进行备份。

 

2、循环使用左索引(left)与右索引(right)进行比较,如果左索引(left)小于或等于右索引(right)时,取出左右索引之和的中间值索引(center)在values数组中的值(values[center])与当前索引(i)在values数组中的值(now<--values[i]-->)进行比较。

 

      2.1、如果中间索引值(values[center])大于当前索引值(now<--values[i]-->)时,将得到的中间索引(center)向左移动一位重新计算出右索引(right=center-1),继续第2步进行左右索引比较、中间索引值与当前索引值比较。

 

      2.2、如果中间索引值(values[center])小于或等于当前索引值(now<--values[i]-->)时,将得到的中间索引(center)向右移动一位重新计算出左索引(left=center+1),继续第2部进行左右索引比较、中间索引值与当前索引值比较。

 

3、直到左索引(left)已经向右移动超过了右索引(right)时就跳出循环,进入下一步。此时如果2.1或2.2步已经执行过,那么此时跳出循环后得到左索引(left),就是当前索引对应数组值将要插入到数组中的索引位置。

 

4、当前索引向左一位(i-1)循环递减得到的索引与第2步骤得到的左索引(left)进行比较。

 

      4.1、如果当前索引左一位(i-1)循环递减的索引结果(i-1-n)大于或等于以上第2步骤得到的左索引时,将前者索引(i-n-1)对应的数组值赋值给该索引的右一位索引(i-1-n+1)对应的数组值。此时在数组中的(i-1-n)索引值和(i-1-n+1)索引值是相同的。接下来进入下一次第4步循环操作。

 

      4.2、如果当前索引左一位(i-1)循环递减的索引结果(i-1-n)小于第三步得到的左索引时,跳出循环进入到下一步。

 

5、判断第3步获得到的左索引与当前索引进行比较。

 

     5.1、如果不相同时,将第1步获取的now覆值给第3步获得到的左索引对应数组中的值。

 

     5.2、如果相同时,进行下一次第2步循环。