《Java数据结构和算法》第二版 Robert lafore 编程作业 第三章
参考 https://blog.csdn.net/zhch152/article/details/7906162
-
3.1 bubbleSort.java程序(清单3.1)和BubbleSort专题applet中,in索引变量都是从左到
右移动的,直到找到最大数据项并把它移动到右边的out变量外。修改bubbleSort()方法,
使它成为双向移动的。这样,in索引先像以前一样,将最大的数据项从左移到右,当它到
达out变量位置时,它掉头并把最小的数据项从右移到左。需要两个外部索引变量,一个在
右边(以前的out变量),另一个在左边。//3.1 public void bubbleSort() { int left ,right, in; for(right =nElems-1,left=0;right>left;right--,left++){ //从左到右选出最大 for(in= left;in<right;in++){ com++;//比较次数 if(a[in]>a[in+1]){ swap++;//交换次数 swap(in,in+1); } } //从右到左选出最小 for(in--;in>left;in--){ com++; if(a[in-1]>a[in]){ swap++; swap(in,in-1); } } }
3.2 在isertSort.java程序(清单3.3)中给ArrayIns类加一个median()方法.这个方法将返回
数组的中间值.(回忆一下,数组中一半数据项比中间值大,一半数据项比中间值小。)/** * 3.2返回数组的中间值 如果数组长度为奇数 则放回中间值 否则取两个中间值的平均值 * @return */ public long media(){ //将数组排序 this.insertionSort(); int midIndex =nElems/2; if(nElems%2 == 0){ return nElems==0?0:(a[midIndex]+a[midIndex-1])/2; }else{ return a[midIndex]; } }
3.3 在insertSort.java程序(清单3.3)中增加一个名为noDups()的方法,这个方法从已经有
序的数组中删掉重复的数据项而不破坏有序性。(可以用insertionSort()方法对数据排序,
或者也可以简单地用main()方法将数据有序地插入到表中。)一种解决方法是每发现一个重
复的数据,就从这个位置开始到数组结尾都向前移动一个位置,但这样就导致消耗很长的
O(N2)的时间级,起码在有很多重复数据项的情况下是这样的。在设计的算法中,不论有多
少重复数据,要确保数据项最多只能移动一次。这样算法只消耗O(N)数量级的时间。 -
/** * 3.3删除重复元素(已排序) */ public void noDups(){ //先循环找出重复元素并设为空 if(nElems ==0 ) return; long lastVal = a[0]; int newElems = nElems; int lastDupIndex = -1;//记录上个重复的索引 for (int i=1;i< nElems;i++){ if(a[i] == lastVal){//等于 newElems--; a[i]=0;//默认为0 if(lastDupIndex == -1){ lastDupIndex = i; } }else {//大于 lastVal = a[i]; if(lastDupIndex != -1){ a[lastDupIndex] =a[i]; a[i]=0;//默认为0 lastDupIndex++; } } } nElems =newElems; }
3.4 还有一种简单排序算法是奇偶排序。它的思路是在数组中重复两趟扫描。第一趟扫描选择所有
的数据项对,a[j]和a[j+1],j是奇数(j=1,3,5,……)。如果它们的关键字的值次序颠倒,就交
换它们。第二趟扫描对所有的偶数数据项进行同样的操作(j=2,4,6,……)。重复进行这样两趟
的排序直到数组全部有序。用oddEvenSort()方法替换bubbleSort.java程序(清单3.1)中的
bubbleSort()方法。确保它可以在不同数据量的排序中运行,还需要算出两趟扫描的次数。奇
偶排序实际上在多处理器环境中很有用,处理器可以分别同时处理每一个奇数对,然后又同时
处理偶数对。因为奇数对是彼此独立的,每一对都可以用不同的处理器比较和交换。这样可以非
常快速地排序。//3.4 奇偶排序 public void oddEventSort(){ int count=0; boolean isChange = true; int start = 0;//0 偶交换 1 奇交换 while (isChange){ count++; isChange = false; for(int i= start ;i<nElems-1;i+=2){ com++; if(a[i]>a[i+1]){ swap++; isChange = true; swap(i,i+1); } } start = start ==0?1:0; } System.out.println("count "+count); }
3.6 有一个有趣的方法用来删除数组中相同的数据项。插入排序算法中用一个循环嵌套算法,将
数组中的每一个数据项与其他数据项一一比较。如果要删除相同的数据项,可以这样做(参见第
2章第2.6小节)。修改insertSort.java中的insertionSort()方法,使它可以在排序过程中
删除相同的数据项。方法如下:当找到一个重复数据项的时候,通常用一个小于任何值的关键值
来改写这个相同数据项(如果所有值都是正数,则可取-1)。于是,一般的插入排序算法就会像
处理其他数据项一样,来处理这个修改了关键值的数据项,把它移到下标为0的位置。从现在开
始,算法可以忽略这个数据项。下一个相同的数据项将被移到下标为1的位置,依此类推。排序
完成后,所有相同的数据项(现在关键值为-1)都在数组的开头部分。可以改变数组的容量并
把需要的数据前移动数组下标为0的位置。/** * 3.6 插入排序并移除重复数据 */ public void insertSortedNoDup() { int in,out; int dupNum = 0; for(out =0;out <nElems;out++){ long temp = a[out]; for(in =out-1;in>=0;in--){ com++; if(temp > a[in]){ break; } else if(temp == a[in]){ for(int index = in;index >dupNum;index--){ a[index] =a[index -1]; } dupNum++; a[dupNum-1]=-1; break; }else { swap++; a[in + 1] = a[in]; } } a[in+1] = temp; } System.out.println("dupSize" +dupNum); for (int i=dupNum;i<nElems;i++){ a[i-dupNum] = a[i]; } nElems -=dupNum; }