标签:ret 重复 rgs 思路 out 循环 rate pac pack
我们在学习算法时,经常遇到的一个问题是,看的懂但是写不出来。究其原因,是没有理解到位。
那么怎么才能理解到位呢?我认为关键是“分解”,就是把算法中的节点按层次和步骤分解出来。
一步一步的实现。
今天先来分解一下排序算法中的一个算法——选择排序。
为什么叫选择排序呢?
一种最简单的排序算法是这样的:首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小的元素那么它就和自己交换)。再次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。如此往复,直到将整个数组排序。这种方法叫做选择排序。
可以发现,选择排序的关键点就是选择“最小值”。这个名称,就是这个算法的核心思想。我们先来看一个完整的算法的实现。
///选择排序 public static void SelectSort0(int[] a){ int min=0; for(int i=0;i<a.length;i++){ min=i; for(int j=i+1;j<a.length;j++){ if(a[min]>a[j]){ min=j; } } int tmp=0; tmp=a[i]; a[i]=a[min]; a[min]=tmp; } for(int i=0;i<a.length;i++){ System.out.print(a[i] + " "); } }
这个算法,看完之后比较容易懂,但是不好记。下面我就用分解的方式来对这个算法进行拆解。
第一步:找最小值(索引)
给定一个数组,从中找到第一次出现的最小的值(其索引),这个算法要如何实现呢?
我想用一个循环就可以搞定,代码如下:
public static int FindMinIndex(int[] a){ int min=0; for(int i=0;i<a.length;i++){ if(a[min]>a[i]){ min=i; } } return min; }
选择排序的思想就是每次遍历,找到当先序列的最小的索引,和当前的起始索引的元素进行交换。
因此我们需要一个可以自己指定“起始索引”的重载版本:
public static int FindMinIndex(int[] a,int beginIndex){ int min=beginIndex; for(int i=beginIndex;i<a.length;i++){ if(a[min]>a[i]){ min=i; } } return min; }
其中,第二个参数,是数组a的起始遍历的索引。
第二步:交换索引元素
这个很简单,直接上代码
public static void Exchange(int[] a,int i,int j){ int temp=a[i]; a[i]=a[j]; a[j]=temp; }
第三步:进行组合
在选择排序的主方法中,对数组进行一次遍历。每次遍历,找到最小的值的元素对应的索引,和当前的起始索引的元素进行交换。遍历完毕,则数组排序完毕。
public static void SelectSort(int[] a){ for(int i=0;i<a.length;i++){ int beginIndex=i; int min = FindMinIndex(a,beginIndex); Exchange(a,min,i); } }
完整代码如下:
package asen.yang; public class selectSort { public static void main(String[] args) { // TODO Auto-generated method stub int[] a={5,1,4,8,3,9,0,2,7,6,1,2,5}; SelectSort(a); for(int i=0;i<a.length;i++){ System.out.print(a[i]+ " "); } } public static int FindMinIndex(int[] a){ int min=0; for(int i=0;i<a.length;i++){ if(a[min]>a[i]){ min=i; } } return min; } public static int FindMinIndex(int[] a,int beginIndex){ int min=beginIndex; for(int i=beginIndex;i<a.length;i++){ if(a[min]>a[i]){ min=i; } } return min; } public static void Exchange(int[] a,int i,int j){ int temp=a[i]; a[i]=a[j]; a[j]=temp; } public static void SelectSort(int[] a){ for(int i=0;i<a.length;i++){ int beginIndex=i; int min = FindMinIndex(a,beginIndex); Exchange(a,min,i); } } ///选择排序 public static void SelectSort0(int[] a){ int min=0; for(int i=0;i<a.length;i++){ min=i; for(int j=i+1;j<a.length;j++){ if(a[min]>a[j]){ min=j; } } int tmp=0; tmp=a[i]; a[i]=a[min]; a[min]=tmp; } for(int i=0;i<a.length;i++){ System.out.print(a[i] + " "); } } }
在学习算法时,如果对最终的代码记不清楚,那可以尝试使用分解的方式,记住其关键点。然后再组合。
而对于向排序这样的经典算法,几乎所有的开发语言的类库中都已经实现了。我们学习的目的,并不仅仅是重复已经实现的东西,更重要的是在学习中,掌握思想。而思想,更多的体现在其中的关键点上。因此对算法进行分解,找准关键点,理解核心思想,才是学习算法时,所更应该重点关注的角度。
接下来会按照这个思路,进行其他算法的分解。从这个角度,在学习算法的过程中,会有更多的收获。
标签:ret 重复 rgs 思路 out 循环 rate pac pack
原文地址:https://www.cnblogs.com/asenyang/p/8794322.html