JavaScript算法练习(排序篇一)

最近萌生了重新学习算法的想法。由于目前正在研究前端,索性就把JS作为我们联系算法的基本语言吧。又由于本人对CoffeeScript的喜欢加上其本身写出来的代码更像是伪代码,所以代码实现部分是就用CoffeeScript了。闲话不多说,排序篇一就只练习两个最基础排序吧。经典的快速排序和堆排序。下面为了方便和容易理解,两种算法分别针对从大到小和从小到大实现一遍。

(一)快速排序

先说快速排序的基本思路,这个大家都应该知道,针对入门者来说我认为有两个地方需要注意。

首先这排序本身肯定都有一个基本动作,对于程序来说你要告诉他基本动作让后让他不停的重复。我们假设快排的基础动作为sort()。那么快排中sort()要完成的任务就是:给定一个Arr[index],它会使得Arr中index前面的数一定都比Arr[index]大,index后面的一定都比Arr[index]小。如[12, 23,34, 4, 45, 8, 9]针对index = 3也就是元素34来说,sort()会使得数组变成[12, 23, 4, 8, 9,34, 45]。然后每次在剩下的前后两部分分别在选取一个index执行同样的sort()过程。

其次,他的结束条件,用比较通俗的话来说就是当边界与index重合的时候便不再执行sort(),如上面例子在针对34后面的部分sort()时就符合结束条件,sort()不会在执行。

有了基本动作和结束条件就比较好写了。我们就假设每一次sort()动作都选取当前边界的中点作为index,也就是index = (start+end)/2,那么程序如下:

Array::swap = (begin, end) -> //这个排序会交换数组内元素的位置
	swap = this[begin]
	this[begin] = this[end]
	this[end] = swap
	return this

Array::quickSort = () ->
	sort = (array, _begin, _end)-> //基本动作,执行边界为array[_begin]到array[_end]
		if _begin >= _end
			return
		begin = _begin
		end = _end
		now = Math.floor (begin+end)/2

		while begin < end

			while array[begin] >= array[now] && now > begin
				begin++
			if array[now] > array[begin]
				array.swap(now, begin)
				now = begin

			while array[end] <= array[now] && now < end
				end--
			if array[now] < array[end] 
				array.swap(now, end)
				now = end

		if _begin < now-1
			sort(array, _begin, now)
		if _end > now+1
			sort(array, now, _end)

	sort(this, 0, this.length-1)

	return this
 

arr = [5,12,1,134,1,23,51,2,34,4,2,5]
console.log arr.quickSort()

(二)堆排序

堆排序的话也要分基本动作,它的基本动作相对比快排要复杂点。临时有事。。。。晚上回来继续吧==||。

现在回来补齐,继续上面堆的概念不再详细描述,通俗点就是数组表示的二叉树。我们说最大二叉堆就是一定满足根比孩子大,这样说数组中最大的就是二叉树的根,也就是Arr[0],我们的思路就是每次把最大的数(Arr[0])取出来,然后将剩下的长度为(Arr.length-1)的数组再次变成最大二叉堆,这样这个数组里面的最大的0元素便是以前Arr中第二大的数。。。。。以此类推排序就可以完成。因此,其实你可以有这种想法:

while Arr.len>1

BuildHeap(Arr);

pop(Arr[0]);

不过这样每次建立二叉堆效率实在是低,所以为了减少不停的建立堆,我们可以有如下策略:每次不要改变堆的结构,只是把堆中不合适的元素向下移动。于是我们只需要建立一次堆,然后将最大的元素Arr[0](假设为max1)与组后一个元素对调,然后保持max1在Arr[len-1]不动,再针对Arr[0...len-2]个元素调整肯定不合适的Arr[0](现在为以前的最后一个元素)。基于这个思想,代码如下:

Array::swap = (begin, end)->
	swa = this[begin]
	this[begin] = this[end]
	this[end] = swa
	return this

Array::MaxHeapify = (i, end)->
	if typeof i isnt "number"
		i = Number(i)
	len = end || this.length
	lch = 2*i + 1
	rch = 2*i + 2
	if lch < len and this[i] < this[lch]
		largest = lch
	else
		largest = i
	if rch < len and this[largest] < this[rch]
		largest = rch

	if i != largest
		this.swap(i, largest)
		# console.log this
		this.MaxHeapify(largest, len)
	return this

Array::BuildMaxHeap = ->
	len = this.length
	index = Math.floor(len/2)
	while index >= 0
		this.MaxHeapify(index--) 
	return this

Array::HeapSort = ->
	len = this.length
	this.BuildMaxHeap()
	while len > 1
		this.swap(0, len-1)
		this.MaxHeapify(0, len-1)
		len--

	return this

arr = [5,12,1,134,1,23,51,2,34,4,2,5]

console.log arr.HeapSort()


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值