** 人脑趋向于将问题扁平化,这样思考问题时的认知负荷小。这就是我们常说的清清楚楚。**
如果你习惯沿着让人脑舒适的路线来设计算法,你就无法最大限度的发挥电脑的特长,让电脑高效的解决问题。比如,递归。要把递归过程中的每个环节想清楚,对于人脑来说是存在巨大的认知负荷的。人脑的运行内存是很小的,偏偏递归是一种内存开销大的编程模式。
今天尝试用js来实现快速排序法(虽然js的Array已经自带有排序函数,但是为了训练思维,还是动手去体会了一下个中的各种坑)。网上有一篇文章,用漫画的形式非常清楚的解说了快速排序法的原理。看完原理之后,原本以为自己动手可以很轻松的写出这个算法来。然而现实并不是那么一回事。
坑一
从漫画看明白了,快速排序法通过递归的方式一遍遍将数组切割成左右两个部分,然后通过相同的方式进行换位操作。但是在写代码时,我却下意识的希望一开始就将排序过程中那些出现的“子数组”在一开始就计算出来。但是,实际上这是不可能的,“子数组”是在一遍遍递归过程中生成的。所以,还是扁平化思维在作祟,否则,这是显而易见的问题。
坑二
我没有接受过C语言编程的训练,所以对指针的理解很粗浅,更缺乏感性认识。在快速排序法中,一开始我试图用for循环来实现指针偏移,但是实际上这里的逻辑决定了一开始你并不知道循环的长度有多少。所以,合理的应该是使用while循环来实现。另外,循环语句执行的结果是什么?一开始,下意识会认为是确定要进行换位的数(元素)——即结果(这又是一种扁平化思维的影响),但是实际上更为合理的方法应该是确定指针的位置,有了指针无论如何你都可以根据它去得到你想要的东西。
代码
最后将实现代码记录一下:
var arr=[213, 35, 2, 700, 277, 21, 486, 17, 919, 615];
fsort(arr,0,arr.length-1);
function fsort(arr,left,right){
var i,j,t,temp;
if(left>right){
/*console.log('complete');
console.log(arr);*/
return;
}
console.log(arr.slice(left,right+1))
i=left;
j=right;
temp=arr[left];//基准数
while(i!=j){
while(arr[j]>=temp && i<j)j--;
while(arr[i]<=temp && i<j)i++;
if(i<j){
t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
arr[left]=arr[i];
arr[i]=temp;
fsort(arr,left,i-1);
fsort(arr,i+1,right);
}
反思
就像前些天写将思维简图的录入数据结构化的算法一样,算法首要确定的是元素之间的关系。在这个例子中,“关系”即“指针”;在思维简图的例子中,“关系”则是那些自己创造的描述节点关系的字段值。先瞄准计算出这些内容,才能帮你更好的发挥电脑的能力,也让编程更加灵活。
网友评论