读书笔记——算法导论

第2章算法入门
浮于表面不如深入其中,送给自己,自己是最大的敌人,那么就尽最大努力去克服自己,沉思,冷静,不浮躁!

 

勘误:在算法导论第9页,扼要的扼

内容提要:

(1)伪代码的表示方法

(2)插入排序算法分析

(3)循环不变式

(4)算法设计之分治法(divide-and-conquer)

(5)合并排序算法分析

 

1.伪代码的表示方法

①伪代码与流程的编程语言类似;

②伪代码可以用英语表示,当然中文也可以;

③不关心其他细节,比如异常处理等软件工程需要关注的问题

约定:①必要的缩进;②控制语句:while、for、repet、if、then、else等等;③注释表示有点特征哈;④多重赋值;⑤变量的定义是不需要的,直接用即可;⑥数组的访问同C;⑦参数值传递;⑧布尔运算的短路能力;⑨空指针为NIL等等等等

2.插入排序算法分析

输入:n个数,可以表示为有序列<a1,a2,…an>;

输出:同样n个数,只是顺序变了变为<a1’,a2’,…,an’>,其中a1’<=a2’<=…<=an’或者相反的结果。

另一个术语:这些待排序的数字也叫关键字即key

实例:数组A={5,2,4,6,1,3}

分析使用插入排序过程:

第1步:5,2,4,5,1,3

该步骤在第1个元素插入的情况下准备开始插第2个元素2

此时,从2之前的一个元素开始搜索,因为前面的元素已经有序了,那么我们只要从2之前的元素倒序的方式开始找比2小且第一次出现的数字,然后将2插入到该数字之后,那么当前情况下我们往前找,结果发现5比2大,则继续往前搜索,发现前途一片空白,所以直接将2插入到空白之后,即5之前

结果:2,5,4,5,1,3

第2步:2,5,4,5,1,3

该步骤需要插入元素4,我们从4之前的一个元素5从5开始往前搜,第一次比较发现4比5小,继续往前搜,发现4比2大则把4插入到2之后。

第3步:2,4,5,5,1,3

该步骤需要插入元素5,我们从5之前的一个元素开始搜,第一次为5,发现不大于5(实际上是和5相等),则将5插入到5之后。

第4步:2,4,5,5,1,3

该步骤需要插入元素1,我们从1之前的一个元素开始搜,第一次为5,pass,第二次为5,pass,第三次为4,pass,第四次为2还是pass,继续往前走,发现前面没人了,咋办,直接插入空白之后。

第5步:1,2,4,5,5,3

好了,终于到最后一步了,大松一口气哈。

此次需要插入元素3,从3之前的一个元素开始搜索,第一次为5,过,第二次为5,继续过,第三次为4,过,第四次为2,发现不大于3(即小于3了),那么咋办?插入到2之后呗。

好了该实例终于分析完毕了,我想现在对于插入排序的排序过程应该有了很深刻的了解了吧

小结:

插入排序的实质就是,从第2个元素开始插入,然后一个劲地以倒序的方式从前面的元素中搜索不大于待插入的元素的元素(包括小于和等于啦),一旦找到,则将元素插入该元素之后,这样不断重复地插入就完成了插入排序的过程。

写了这么多,下面给出插入排序的代码:

代码:

void insertSort( int* A, int n );

int main(intargc, char* argv[])

{undefined

int A[6]={5,2,4,5,1,3};

 

printf("插入排序前:\n");

for( int i = 0; i <6; i++ )

{undefined

printf("%d\t",A[i]);

}

printf("\n");

 

insertSort(A,6);

printf("插入排序后:\n");

for( int i = 0; i <6; i++ )

{undefined

printf("%d\t",A[i]);

}

printf("\n");

 

return 0;

}

 

void insertSort( int* A, int n )

{undefined

int key = 0;

int i = 0;

int j = 0;

 

for ( i = 1; i < n; i++ )

{undefined

//待插入元素赋值给key

key = A[i];

 

//从待插入的元素之前倒序进行搜索

j = i - 1;

//终止条件为直至第一个元素,或者找到的元素不大于待插入元素

while ( j >= 0&& A[j]>key )

{undefined

//边查找不大于key的元素边挪元素到其后一格

A[j+1]=A[j];

j--;

}

 

//将待插元素插入到所找到的不大于待插元素之后

A[j+1]=key;

 

 

}

}

运行结果:

 

3.关于循环不变式

初始化:在第一轮迭代之前它是正确的

保持:在循环的某一次迭代开始之前它是正确的,在下一次迭代开始之前它也是正确的

终止:循环结束后,不变式给了我们一个有用的性质,那就是所得的最终序列是有序的,按升序或者降序排列。

通俗一点讲:

初始化:就是在第一次迭代之前已经有一个元素,因为只有一个元素,我们可以称之为降序的(或者升序)

保持:在某一次排序的过程前,待插入的元素之前所有的元素都是降序的(或者升序),那么插入该元素之后这些元素还是降序的(或者升序)

终止:在排序结束之后,由以上两点,可以知道所有的序列都是按照降序(或者升序)排列了

 

练习答案:

2.1-1以图2-2为模型,说明INSERT_SORT在数组A=<31,41,59,26,41,58>上执行过程。

第1步:31,41,59,26,41,58

待插元素为41,此时从41之前的元素倒序搜索,发现31不大于41,则插入到31之前

第2步:31,41,59,26,41,58

待插元素为59,此时从59之前的元素倒序搜索,第一次发现41不大于59,则插入到41之后

第3步:31,41,59,26,41,58

待插元素为26,此时从26之前的元素倒序搜索,第一次发现59大于26,继续往前搜索,第二次发现41大于26,继续往前搜索发现31大于26,继续往前搜索,发现前途一片空白,直接插入。

第4步:26,31,41,59,41,58

待插元素为41,此时从41前一个元素倒序搜索,第一次发现59大于41,继续搜索,第二次发现41不大于41,则此时直接将41插入该元素41之后。

第5步:26,31,41,41,59,58

待插元素为58,此时从58 前一个元素倒序搜索,第一次发现59大于58,继续搜索,第二次发现41不不大于58,则停止搜索,将待插元素58插入到元素41之后。

 

2.2-2重写INSERTION-SORT,使之按非升序(而不是按非降序)排序。

//降序

void insertSort2( int* A, int n )

{undefined

int i = 0;

int j = 0;

int key = 0;

 

for ( i = 1; i < n; i++ )

{undefined

key = A[i];

j = i - 1;

 

while( j >= 0&& A[j]<key )

{undefined

A[j+1] =A[j];

j--;

}

 

A[j+1]=key;

}

}

 

2.1-3考虑下面的查找问题

输入:一列数A=<a1,a2,…,an>和一个值v。

输出:下标i,使得v=A[i],或者当v不在A中出现为NIL

写出针对这个问题的线性查找的伪代码,它顺序地扫描整个序列以查找v,利用循环不变式证明算法正确性,确保所给出的循环不变式满足三个必要的性质。

伪代码:

SEARCH(A,v)

For i=1 to length(A)

If( A[i] == v )

Return i

Return NIL

证明:

初始化:在迭代之前,没有元素能够等于v

保持:在每一轮循环都没有找到等于v的元素

终止:当找到v之前,前面都有等于v的元素,直至找到v,算法停止

我不知道我的解答对不对-_-!

 

2.2-4有两个各存放在数组A和B中的n位2进制整数,考虑他们相加的问题。两个整数的和以二进制形式存放在具有n+1个元素的数组C中,请给出这个问题的形式化描述,并写出伪代码

输入:n位2进制整数A和B

输出:A+B的结果

代码:

void binAdd( int*A,int* B, int* C, intn );

int _tmain(intargc, _TCHAR*argv[])

{undefined

int A[7]={1,1,0,1,0,1,1};

int B[7]={1,1,0,1,1,1,1};

int C[8]={0};

 

 

printf("A为:");

for ( int i= 0; i < 7;i++ )

{undefined

printf( "%d",A[i] );

}

 

printf("\nB为:");

for ( int i = 0; i <7; i++ )

{undefined

printf("%d",B[i]);

}

binAdd(A,B,C,7);

printf("\n结果:");

for (inti=0; i< 8;i++)

{undefined

printf( "%d",C[i] );

}

return 0;

}

 

 

void binAdd( int*A,int* B, int* C, intn )

{undefined

int i = n - 1;

//从最低位开始相加,也就是数组的最高位

for ( ; i > 0; i-- )

{undefined

//判断是否大于等于,需要进位

if ( A[i] + B[i] >= 2 )

{undefined

C[i+1] =A[i] + B[i] - 2;

//若需要进位,直接放到原数组中去计算

A[i-1] += 1;

}

else

{undefined

C[i+1] =A[i] + B[i];

}

}

//最后一步,因为C比A和B都多出一位,所以直接将结果放置C[1],并将进位放置C[0]

if ( A[0] + B[0] >= 2 )

{undefined

C[1] = A[0]+B[0]-2;

C[0] = 1;

 

}

else

{undefined

C[1]= A[0]+B[0];

C[0] = 0;

}

}
————————————————
版权声明:本文为CSDN博主「xizero00」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xizero00/article/details/7406318

posted @ 2022-01-18 17:52  往心。  阅读(108)  评论(0编辑  收藏  举报