一、理解插入排序
-
比如有一串数字,1,2,5,6,3,4 ,需要将这几个数字排序。
-
插入排序指的是这样做
-
-
-
而后将4取出。
-
最终得到这个。
-
二、抽象
-
不建议直接从网上找个现成的程序背会。练习编程 就是锻炼自己抽象的能力。
-
解析一下这张图,将3取出,放到5的前面。
- 第一,要有一个数组,或者链表。以数组为例。你先要找到3这个 成员。(人脑可能一下就找到了,但是计算机要怎么找到,代码要怎么写?)
- 第二,你要记录下这个成员的值。
- 第三,你要找到插入的位置。
- 第四、你要能够交换值。
-
将4提取然后插入的操作其实和操作3是一样的。
-
整理一下抽象出来要做的事情。
三、实现
-
先找到那个3。找到->如果是顺序查找,意味着要循环,还要有判断条件。
-
先定义一个数组。
int main(int argc, const char *argv[]) { //定义一个数组 int arr[] = {1,2,5,6,3,4}; int arr_len = sizeof(arr)/sizeof(arr[0]) return 0; }
-
查找->意味着要循环。而且,人脑虽然一眼看出来3是要被提前的那个数字,代码还是要一个个的来。数组每个数字都可能是是要被提前的数字。所以,对应的代码是:
int main(int argc, const char *argv[]) { int arr[] = {1,2,5,6,3,4}; int arr_len = sizeof(arr)/sizeof(arr[0]) int i = 0; //每个成员都可能是那个3. for(i=0;i<arr_len;i++) { } return 0; }
-
-
要记录当前要插入的这个成员的值。
-
记录下来,方便后续换值。
int main(int argc, const char *argv[]) { int arr[] = {1,2,5,6,3,4}; int arr_len = sizeof(arr)/sizeof(arr[0]) int i = 0; int tmp = 0; //每个成员都可能是那个3. for(i=0;i<arr_len;i++) { //将这个值先记录下来 tmp = arr[i]; } return 0; }
-
-
然后是要找到插入的位置。
-
找到,意味着循环。 而且是从后往前找。如果i的表示的是3的位置,那就是从3的位置往前找,看看哪里能插入。
int main(int argc, const char *argv[]) { int arr[] = {1,2,5,6,3,4}; int arr_len = sizeof(arr)/sizeof(arr[0]) int i = 0; int tmp = 0; int j = 0; //每个成员都可能是那个3. for(i=0;i<arr_len;i++) { tmp = arr[i]; //从3的位置往前找。 for(j=i;j>0;j--) { } } return 0; }
-
找到意味着要比较,怎么就知道当前位置可以继续前移?在例子中,3比5小,所以3要前移,前移之后,3比4还小,所以要继续前移。而3比2大,所以就不要继续前移了,3已经找到了位置,并且这一轮停止。
看出来,这里需要比较。
int main(int argc, const char *argv[]) { int arr[] = {1,2,5,6,3,4}; int arr_len = sizeof(arr)/sizeof(arr[0]) int i = 0; int tmp = 0; int j = 0; //每个成员都可能是那个3. for(i=0;i<arr_len;i++) { tmp = arr[i]; //从3的位置往前找。 for(j=i;j>0;j--) { //比较判断,是否需要继续前移。如果比前一个值小,就要继续前移。 if(compare(&arr[j],&arr[j-1]) < 0) { //还需继续前移 } else { break; } } } return 0; }
我们知道了什么时候停止继续前移,就相当于知道了插入位置。
-
-
最后是前移的实现。其实就是交换值。
-
交换值。
int main(int argc, const char *argv[]) { int arr[] = {1,2,5,6,3,4}; int arr_len = sizeof(arr)/sizeof(arr[0]) int i = 0; int tmp = 0; int j = 0; //每个成员都可能是那个3. for(i=0;i<arr_len;i++) { tmp = arr[i]; //从3的位置往前找。 for(j=i;j>0;j--) { //比较判断,是否需要继续前移。如果比前一个值小,就要继续前移。 if(compare(&arr[j],&arr[j-1]) < 0) { //还需继续前移,调用交换值的函数。将后一个值和前一个值交换,不就是前移了吗? swap(&arr[j],&arr[j-1]); } else { break; } } } return 0; }
-
四、方法记忆
-
要想达到执行合一的境界。不能死记硬背。需要把知识记忆转换为方法记忆或者经验记忆。
-
所以这里要多练习几次。最好使用导图,或者涂鸦的方法,画一画。
参考这里:https://blog.csdn.net/renyongjian1994/article/details/118054146
-
所有代码。
#include<stdio.h> int compare(int *a,int *b) { if(a == NULL || b == NULL) { return 0; } if(*a > *b) { return 1; } if(*a == *b) { return 0; } return -1; } int swap(int *a,int *b) { int tmp = *a; *a = *b; *b = tmp; return 0; } int print_arr(int *arr,int len) { int i = 0; for(i = 0;i < len;i++) { printf("%d,",arr[i]); } printf("\n"); return 0; } int main(int argc, const char *argv[]) { int arr[] = {1,2,5,6,3,4}; int arr_len = sizeof(arr)/sizeof(arr[0]); int i = 0; int tmp = 0; int j = 0; //每个成员都可能是那个3. for(i=0;i<arr_len;i++) { //从3的位置往前找。 for(j=i;j>0;j--) { if(compare(&arr[j],&arr[j-1]) < 0) { //还需继续前移 swap(&arr[j],&arr[j-1]); } else { break; } } } print_arr(arr,arr_len); return 0; }
-
对应结果
五、整理总结
-
找到,这次对应到代码中就是:
-
数值移动,对应到代码中就是:
-
记录,对应到代码中就是:
-
一个程序就是由这些简单的元素组成。通过练习用代码实现这些元素,来提升自己的编码能力。
-
实现之后要继续优化代码,你会发现记录数值这个抽象是没用的。
六、参考
- https://blog.csdn.net/renyongjian1994/article/details/118054146
- https://blog.csdn.net/renyongjian1994/article/details/118115367