在算法中,有一个重要的概念就是循环不变式,循环不变式主要用来帮助我们理解算法的正确性。关于循环不变式,我们必须证明三条性质:
1.初始化:循环的第一次迭代之前,它为真。
2.保持:如果循环的某次迭代之前它为真,那么下次迭代之前它仍为真。
3.终止:在循环终止时,不变式为我们提供了一个有用的性质,该性质有助于证明算法是正确的。
我们用插入排序来解释这个性质:
/**
* 编写插入排序, 运用 循环不变式的思想 本质上就是 迭代化归的过程
* 特点
* 1.初始化
* 2.保持
* @author Neuclil
*
*/
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {31, 41, 59, 26, 41, 58};
insertSort(a);
for(int i=0; i<a.length; i++){
System.out.print(a[i] + " ");
}
System.out.println();
insertSort2(a);
for(int i=0; i<a.length; i++){
System.out.print(a[i] + " ");
}
}
//递增的方式
public static void insertSort(int[] a){
int j ;
for(int i=1; i<a.length; i++){
int temp = a[i];//得到需要插入的数据,默认0-i的数据已经排好, 这里i=0初始化是排好的
for( j= i; j>0; j--){
//此时要迭代的构造循环不变式。 这是一个一般的插入过程
if(a[j-1] > temp){
a[j] = a[j-1];
}else{
break;
}
}
//循环退出 有两个可能 1.a[j-1]<temp 此时 a[j] = temp; 2.j=0 此时a[j] = temp
a[j] = temp;
}
}
//递减的方式
public static void insertSort2(int[] a){
int j ;
for(int i=1; i<a.length; i++){
int temp = a[i];//得到需要插入的数据,默认0-i的数据已经排好, 这里i=0初始化是排好的
for( j= i; j>0; j--){
//此时要迭代的构造循环不变式。 这是一个一般的插入过程
if(a[j-1] < temp){
a[j] = a[j-1];
}else{
break;
}
}
//循环退出 有两个可能 1.a[j-1]<temp 此时 a[j] = temp; 2.j=0 此时a[j] = temp
a[j] = temp;
}
}
//编写二进制加法的算法
public static int[] binaryAdd(int[] a, int[] b){
//迭代的构造
//c[j] = (a[j] + b[j] + flag) % 2;
//初试化 j = 0 flag =0; 否则 flag =( a[j-1] + b[j-1] )/2;
int[] c = new int[a.length+1];
int flag = 0;
for(int i =0; i<a.length; i++){
int key = a[i] + b[i] ;
c[i] = (key + flag) % 2;//0 1 2 3
flag = (key + flag ) / 2;
}
c[a.length] = flag;
return c;
}
}