《Scala by Example》第9章 Lists
列表像C或Java里的数组,但是有三点不同:1. 列表是不可变的。2. 列表是递归的,而数组是平坦(flat)的。3.列表支持一个很多操作的富集合,但数组没有。
9.1 使用列表
列表类型:跟数组一样,列表也是同质化的(homogeneous)。即所有元素都要是同种类型。
列表结构:所有列表由两部分组成:Nil 和 ::(cons)。
基本操作:主要有三个:head , tail , isEmpty 。这些都定义在List Object里。head 和 tail只能用在非空列表里。可以用“插入排序”的例子来进行说明。
模式匹配:::在Scala标准库里是一个case class 。所以可以使用用模式匹配
9.2 List类的定义
List是一个抽象类。List里定义了很多方法,解释如下:
分解列表。
啮合(zipping lists):把两个List结合成一个列表对,如,有列表:xs = List(X1 , ... Xn) 和 ys = List(y1 , ... , yn) , xs zip ys,则生成List对:List((X1 , Y1), ... (Xn , Yn))
操作列表:跟其他中缀操作符一样,::实现为一个对象的方法。Scala里以“:”结尾的操作符都被当成右操作符,也就是从右往左运算。
连接列表:“:::”操作符可以用来连接两个列表。
反转列表:另一个有用的操作就是反转(reversal)。给出了一种reverse方法的实现,但是这种方法跟List的长度成正比,不是很有效。之后会给出一种只有线性关系的实现。
def reverse[A](xs : List[A]) : List[A] = xs match{ case Nil => Nil case x :: xs => reverse(xs) ::: List(x) }
9.3 例子:归并排序(merge sort)
之前的插入排序(insertion sort)虽然简单,但不是很有效。平均复杂度与输入列表的长度的平方成正比。一个比插入排序更好的算法是“归并排序”。工作原理如下:
一,如果这个List有0个或者1个元素,那么它是已经排好的,可以直接返回这个列表。稍长的列表可以分成两部分,每部分包含大概原List一半的长度内容。每个子列表被一个递归的排序调用进行排序,然后两个排序好的列表被一个合并操作合并在一起。
对于一个归并排序的实现,我们仍然要指定元素类型,同时也要有用来做比较(comparison)的函数,用来确定排序规则。一个实现如下:
def msort[A](less: (A, A) => Boolean)(xs: List[A]): List[A] = { def merge(xs1: List[A], xs2: List[A]): List[A] = if (xs1.isEmpty) xs2 else if (xs2.isEmpty) xs1 else if (less(xs1.head, xs2.head)) xs1.head :: merge(xs1.tail, xs2) else xs2.head :: merge(xs1, xs2.tail) val n = xs.length / 2 if (n == 0) xs else merge(msort(less)(xs.take(n)), msort(less)(xs.drop(n))) }
msort的定义用到了柯里化,所以可以这样使用:
val intSort = msort((x : Int , y : Int) => x < y)
val reverseSort = msort((x : Int , y : Int) => x > y)
浙公网安备 33010602011771号