CS 61B homework10
读懂题目后就很简单了!取每个digit用的移位和&15的方法。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public static int[] countingSort(int[] keys, int whichDigit) { // Replace the following line with your solution. int[] counts = new int[16]; int Digit; for(int i=0;i<keys.length;i++){ Digit = keys[i]>>(4*whichDigit); Digit = Digit & 15; counts[Digit]++; } int total=0; for(int i=0;i<counts.length;i++){ int c = counts[i]; counts[i] = total; total = total + c; } int[] y = new int[keys.length]; for(int i=0;i<keys.length;i++){ Digit =( keys[i]>>(4*whichDigit) ) &15; y[counts[Digit]] = keys[i]; counts[Digit]++; } return y; } /** * radixSort() sorts an array of int keys (using all 32 bits * of each key to determine the ordering). * @param key is an array of ints. Assume no key is negative. * @return an array of type int, having the same length as "keys" * and containing the same keys in sorted order. * * Note: Return a _newly_ created array. DO NOT CHANGE THE ARRAY keys. **/ public static int[] radixSort(int[] keys) { // Replace the following line with your solution. int[] result = keys; for(int i=0;i<8;i++){ result = countingSort(result,i); //不断变换指向,指向一个新的返回array,而没有改变keys,虽然最开始result指向了keys } return result; }
keys are [ 60013879 11111119 2c735010 2c732010 7fffffff 4001387c 10111119 529a7385 1e635010 28905879 11119 0 7c725010 1e630010 111111e5 61feed0c 3bba7387 52953fdb 40013879 ]
After sort :
keys are [ 0 11119 10111119 11111119 111111e5 1e630010 1e635010 28905879 2c732010 2c735010 3bba7387 40013879 4001387c 52953fdb 529a7385 60013879 61feed0c 7c725010 7fffffff ]
刚刚看了熊孩子的代码,其中radixsort他是这样写的,最开始用了一个循环对keys进行copy。。然后我就想到,数组之间A=B这样的赋值只是指向的变换。
public static int[] radixSort(int[] keys) { int[]radixsort=new int[keys.length]; for(int i=0;i<keys.length;i++) radixsort[i]=keys[i]; for(int i=0;i<8;i++){ radixsort=countingSort(radixsort,i); } return radixsort; }
所以我在我的代码radixsort中,return keys,因为我想既然是指向,keys会随着result变换
public static int[] radixSort(int[] keys) { // Replace the following line with your solution. int[] result = keys; for(int i=0;i<8;i++){ result = countingSort(result,i); } return keys; }
然后结果是,keys没有随着result变换啊==
于是我做了一下实验:
发现,数组之间的赋值确实是指向的变换啊,那为啥我的keys没变???
于是仔细看了下我的代码,原来是这句中有点不一样了,哈哈哈哈
result = countingSort(result,i); //不断变换指向,指向一个新的返回array,而没有改变keys,虽然最开始result指向了keys
最后补充一下自己对counting sort算法理解,便于以后不用花太多时间复习
原array:
第一个循环:
经过第一次循环之后counts
第二次循环
经过第二次循环之后counts(观察和第之前counts的变化,我们称之前的counts为counts1,这次的counts为counts2,可以发现,counts1的结果为counts2的每一个减去前面的一个,例如counts1中位置0对应内容为counts2中位置1对应内容减去位置0对应内容)
前面两个循环放在一起说,
两个循环出来counts是什么呢?couts的内容是每个key最后排出来后所在位置
那为啥明明原来的key中没有2但是2对应下却有位置3呢?那就再看看3下面对应的也是位置3,所以会把2给取代掉,最后出来就没有2啦
那这个到底怎么实现的呢?想象一下,在第二个循环中,每个counts[j]都赋值为total,total的意思是目前为止有几个了,那是不是counts[j]应该是total+1才对呢?显然不对,因为我们的total是从0开始的,数组储存方式也是从0开始的,如果total是0,就代表前面有0个数,第一个排的数自然排在位置0(counts[j]=0);如果total是1,就代表前面有1个数,现在要排的是第二个数,排在位置1 。这样看来正好counts = total就好。
那这样理解循环3就很容易了吧!through所有要排的数,放在应该在的位置。
诶?那里面的counts[x[i].key]++ 是什么意思?
就是相同的数,按照输入的先后顺序进行排序。看到count2中从位置0到位置1,内容从0跳到2,为啥呢,因为有两个0啊,我们要为两个0分配 位置0 和位置1 两个位置,那哪一个是位置0哪一个是位置1呢?按照输入的先后顺序,第一个0由于在前面此时的counts[0]=0,分配完这个之后,counts[0]++,下一次分配0的时候counts[0]=1啦,这样一来第二个0就会出现在位置1 。
那从count2中怎么知道最后一个数有几个呢?对,从count2是看不出最后一个数有几个的,当然也不用知道!只要知道最后一个数(即数列中的最大数)第一次出现的起始位置是什么就好,反正如果最后一个数输入的有重复的话,会在原来的基础上counts[最后一个数]加一哒。
还有什么问题吗?有!按照这样的算法,那我们一开始怎么确定counts的大小,怎么initial它呢?
那就是需要知道输入数列中的最大值了!然而为了counting sort能高效的排列range分布很大的数列,我们用radix sort。从一开始就确定好了counts的length大小即radix。逐位排序!
通过这种自我精神分裂式的问答,用最朴实(可能只有自己能懂)的语言,我相信下一次复习这个算法的时候一定思路会非常清晰的!!没有看视频,为了节省时间直接看的handout,以后有空补齐这一课的视频!