【从浅到深的算法技巧】初级排序算法 上

5.排序

5.1 初级排序算法

作为对排序算法领域的第一次探索, 我们将学习两种初级的排序算法以及其中种的一个变体。深入学习这些相对简单的算法的原因在于:第一,我们将通过它们熟悉些术语和简单的技巧 第二,这些简单的算法在某些情况下比我们之后将会讨论的复杂算法更有效;第三,以后你会发现,它们有助于我们改进复杂算法的效率。

5.1.1 游戏规则

我们关注的主要对象是重新排列数组元素的算法,其中每个元素都有一个主键。排序算法的目标就是将所有元素的主键按照某种方式排列(通常是按照大小或是字母顺序)。排序后索引较大的主键大于等于索引较小的主键。元素和主键的具体性质在不同的应用中千差万别。在Java中,元素通常都是对象,对主键的抽象描述则是通过一种内置的机制 (Comparable接口)来完成的。

“排序算法类模版”中的Example类展示了我们的习惯约定:我们会将排序代码放在类的sort()方法中,该类还将包含辅助函数less()和exch() (可能还有其他辅助函数)以及一个示例用例main()。Example 类还包含了一些早期调试使用的代码:测试用例main()将标准输入得到的字符串排序,并用私有方法show()打印字符数组的内容。为了区别不同的排序算法,我们为相应的类取了不同的名字,用例可以根据名字调用不同的实现,例如Insertion. sort()、Merge . sort()、Quick.sort()等。

大多数情况下 ,我们的排序代码只会通过两个方法操作数据: less()方法对元素进行比较,exch()方法将元素交换位置。exch()方法的实现很简单,通过Comparable接口实现less()方法也不困难。将数据操作限制在这两个方法中使得代码的可读性和可移植性更好,更容易验证代码的正确性、分析性能以及排序算法之间的比较。

排序算法类的模板
public class Example{

	public static void sort(Comparable[] a){

		//算法......

	}

	private static boolean less(Comparable v, Comparable w){

		return v.compareTo(w) <0; }

	private static void exch(Comparable[] a,int i,int j){

		Comparable t = a[i];

		a[i] = a[j];

		a[j] = t;

	}

	private static void show(Comparable[] a){

		for (int i = 0; i < a.length; i++){

			//单行打印数组

			StdOut . println(a[i]+" ");

		}

	}

	public static boolean isSorted(Comparable[] a){

		for (int i =1;1< a.length; i++){

			if(less(a[i],a[i-1])){

				return false;

			}

			return true;

		}

	}

	public static void main(String[] args){

		String a = In.readstrings();

		assert isSorted(a);

		show(a);

	}

}

这个类展示的是数组排序实现的框架。对于我们学习的每种排序算法,我们都会为这样一个类实现sort()方法并将Example改为算法的名称。测试用例会将标准输入得到的字符串排序,代码使我们的排序方法适用于任意实现了Coparple接口的数据类型。

5.1.2 验证

无论数组的初始状态是什么, 排序算法都能成功吗?我们会在测试代码中添加一条语句asert isSorted(a); 来确认排序后数组元素都是有序的。尽管般都会测试代码并从数学上证明算法的正确性,但在实现每个排序算法时加上这条语句仍然是必要的。需要注意的是,如果我们只使用exch()来交换数组的元素,这个测试就足够了。当我们直接将值存入数组中时,这条语句无法提供足够的保证(例如,把初始输入数组的元素全部置为相同的值也能通过这个测试)。

5.1.3 运行时间

我们还要评估算法的性能。 首先, 要计算各个排序算法在不同的随机输入下的基本操作的次数(包括比较和交换,或者是读写数组的次数)。然后,我们用这些数据来估计算法的相对性能并介绍在实验中验证这些猜想所使用的工具。对于大多数实现,代码风格致会使我们更容易作出对性能的合理猜想。排序成本模型。在研究排序算法时,我们需要计算比较和交换的数量。对于不交换元素的算法,我们会计算访问数组的次教。

5.1.4 额外的内存使用

排序算法的额外内存开销和运行时间是同等重要的。 排序算法可以分为两类:除了函数调用所需的栈和固定数目的实例变量之外无需额外内存的原地排序算法,以及需要额外内存空间来存储另一份数组副本的其他排序算法。

你可能感兴趣的:(从浅到深的算法技巧,排序算法)