CS 61B homework10

读懂题目后就很简单了!取每个digit用的移位和&15的方法。

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;
  }
View Code

 

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,以后有空补齐这一课的视频!

 

posted @ 2017-08-18 11:16  切力  阅读(146)  评论(0编辑  收藏  举报