整理项目

农产品分类项目

再次排序

我们在之前的课上已经看到了一些排序算法的例子。由于排序是计算机科学中如此重要的主题,实际上有许多可用的排序算法。

目前我们见过的最好的排序算法是归并排序。归并排序非常快:它可以在与N log N成正比的时间内对N个项目的列表进行排序,但是归并排序的空间效率不高,因为它需要复制它正在处理的数据。

快速排序是一种与归并排序一样快的算法,如果不是更快的话。快速排序也是就地排序算法的一个例子,它通过在原始数组中移动数字来完成赢博体育的工作。

快速排序

快速排序算法和归并排序算法一样,使用分而治之的策略。快速排序从分区步骤开始,该步骤将原始列表部分地重组为小数和大数。在初始分区步骤之后,Quicksort接着对分区步骤创建的两个较小的列表进行进一步排序。

下面是执行初始部分排序的分区方法的Java代码。分区步骤从索引开始到索引结束对数组的一部分进行操作。分区从该范围中选择一个数字作为枢轴值,然后将给定范围中的数字重新组织为小于或等于枢轴的数字、枢轴本身,然后是大于枢轴的数字。分区的目的不是对两个子列表中的数字进行完全排序。在分区完成它的工作后,它返回枢轴值结束的索引。

private static int partition(int[] list,int start,int end){//使用在end的元素作为枢轴int pivot = list[end];//主循环int i = start-1;for(int j = start;j<end;j++){//将你找到的任何小数字移到列表的左边if(list[j] <= pivot) {i++;Int temp = list[i];List [i] = List [j];List [j] = temp;}} //移动枢轴到中间列表[end] = list[i+1];List [i+1] = pivot;//返回枢轴位置,返回i+1;}

下面是快速排序方法本身的代码。

public static final int THRESHOLD = 40;private static void quicksort(int[] list,int start,int end) {if(end - start < THRESHOLD) selectionSort(list,start,end);Else {int mid = partition(list,start,end);快速排序(列表、开始mid-1);快速排序(列表,+ 1,中期结束);}}

与归并排序一样,快速排序使用递归结构,该方法在将问题分成更小的部分后调用自己。分区步骤将把从开始到结束的原始范围分解为两个较小的范围,[start,mid-1]和[mid+1,end]。为了完成这些较小范围的排序,快速排序只需使用两个较小范围调用自己。

快速排序使用的最后一个特性与Merge sort使用的策略类似:一旦您要求快速排序处理足够短的范围,它将把剩余的排序工作传递给一个更简单的算法,如选择排序。尽管选择排序对于较长的列表来说效率很低,但它对短列表的排序速度足够快,在这里很有用。

二分查找

对列表进行排序是解决许多问题必不可少的第一步。计算机科学中的一个常见问题是搜索问题。给定一个数据项列表和要搜索的特定项,我们想知道给定项是否出现在列表中。

最简单的搜索策略是线性搜索,它包含一个简单的循环来进行搜索:

公共静态布尔搜索(int A[],int x) {for(int n = 0;n < A.length;n++)如果(A[n] == x]返回true;返回错误;}

这种方法是有效的,但不是最有效的搜索方法。如果我们要搜索的列表是有序的,我们可以使用一种更有效的算法,称为二分搜索。

Public static int find(int list[],int x) {int start = 0;Int end = list。长度- 1;While (start < end) {int mid = (start+end)/2;如果(列表(中期)= = x){虽然(中期> 0 & &列表(mid-1) = = x),中期;返回中期;} if(list[mid] < x) start = mid + 1;Else end = mid - 1;} if(list[start] < x) return start+1;返回开始;}

该算法还使用了分而治之的策略。要搜索一个项目,我们到列表的中间,并将我们在那里看到的项目与我们正在搜索的项目进行比较。如果中间的项比我们要搜索的项小,我们马上就知道可以忽略在中间之前的整个列表的一半。然后,我们对列表的后半部分中的数字重复搜索过程。通过反复细分我们搜索的范围,我们可以非常迅速地缩小列表中可能包含我们正在搜索的数字的部分。

使用对象排序

到目前为止,我在这门课上展示的排序代码都是为整型数组排序而设计的。在Java的许多赢博体育程序中,我们可能不得不对对象列表进行排序。例如,我在上节课中展示的产品跟踪器示例打印了一个报告,该报告显示了每天结束时每种商品的库存数量。如果我们想按字母顺序打印这些项,我们需要某种方法对Item对象列表进行排序。

在Java中使对象可排序的标准方法是为它们配备一个称为compareTo方法的特殊方法。这个方法可以赢博体育于一个对象,并接受一个参数,这个参数是另一个你想与之比较的对象。compareTo返回一个int:如果两个对象相同,则返回0,如果赢博体育该方法的对象小于参数中的对象,则返回-1,如果赢博体育该方法的对象大于参数中的对象,则返回1。

下面是Item类的compareTo方法,它使用名称比较两个项目:

public int compareTo(Item other){返回name.compareTo(other.name);}

这段代码利用了Java中许多类已经有compareTo方法的事实。String类有一个compareTo方法,它使用字母顺序来比较String,所以我们在这里所要做的就是对我们正在比较的两个item的名称调用该方法。

要使这一切正常工作,您需要做的最后一件事是稍微修改要在其中放置compareTo方法的类的结构。为了通知其他类你的类有一个compareTo方法,你声明你的类实现了Comparable接口:

public类Item实现Comparable<Item>

一旦将此声明和compareTo方法添加到一个类中,就可以将该类与Java中用于排序对象列表的排序算法等结合使用。

我们已经看到,ArrayList是Java中存储对象列表的常用方法。要对存储在ArrayList中的对象列表进行排序,可以使用java.util.Collections类中的静态sort()方法对ArrayList进行排序。

例如,下面是Inventory类的printReport()方法的修改代码,该方法使用Collections.sort()在打印报表之前对库存列表进行排序。

public void printReport() {Collections.sort(stock);For (int n = 0;N < stock.size();n++) {Item i = stock.get(n);System.out.println(我);}}