都是采用递归方法,针对有序数组。
以下代码,前者针对含有重复的有序数组,如【1,1,1,1,2,2,3,3,3,4,5,5,5,6】。查找最后一个值等于要查找的值。后者是普通的二分查找
# 二分查找 # 查找最后一个值等于给定值的元素 返回结果是数组的下标,不能直接返回值,因为重复值无法体现是否真正返回最后一个。 def half_find(array,value) if array.size <= 1 return nil if array[0] && array[0] == value return nil end n = array.size / 2 if value == array[n] res = half_find(array[n,array.size],value) return res if res return n end if value < array[n] half_find(array[0,n],value) else half_find(array[n,array.size],value) end end a=[] (3..9).each do |i| a.append(i) a.append(i) a.append(i) end p = half_find(a,11) p p p a[p] # 二分查找 # 查找第一个值等于给定值的元素 def half_find(array,value) if array.size <= 1 return 0 if array[0] && array[0] == value return nil end n = array.size / 2 return n if value == array[n] if value < array[n] half_find(array[0,n],value) else half_find(array[n,array.size],value) end end
写了快排,再把另一个O(nlogn)时间复制度补上,空间复杂度为O(n),因此不常用。写了注释,帮助递归理解。
附上代码:
# 归并排序 def merge_sort(array) length = array.size return array if length <= 1 n = length / 2 left = merge_sort(array[0,n]) right = merge_sort(array[n,length]) merge(left,right) end # 先从左边找到最小单位,进行排序,再找左边的右边,再右边的左边,到右边的右边,最后左边与右边 (递归) # 分治法典型 def merge(left,right) l ,r = 0,0 result = [] while l < left.size and r < right.size if left[l] < right[r] result.append(left[l]) l+=1 else result.append(right[r]) r+=1 end end result += left[l,left.size] if left[l,left.size].length > 0 result += right[r,right.size] if right[r,right.size].length > 0 result end aa = merge_sort([7,6,5,4,3,2,1]) p aa
最近复习了快排,还没用过ruby实现快排,因此动手去做了实现。顺便也网上查了下百度给的代码,是未优化的且对原排序数组有改动,因此动手实现一个优化快排。
话不多说,上代码:(ps: 可复制粘贴校准代码正确性,如有错误,望指出,O(∩_∩)O谢谢)
# 稳定快排优化代码--ruby --下标排序 适用于各场景排序 def index_quick_sort(array) # 递归终点 return array if array.length <= 1 # 选取随机下标,rand针对区间/某个数,sample针对数组,因此这里选前者更适合 random_num = rand(array.length) # 准备数组 less_array = [] greater_array = [] # 注意,这里的@array是实例变量,array是局部变量 # 因为每次都要生成一个新数组,所以局部变量恰好适合 (0..array.length-1).each do |i| next if i == random_num if array[i] < array[random_num] less_array.append(array[i]) next end if array[i] > array[random_num] greater_array.append(array[i]) next end if array[i] == array[random_num] && i < random_num #这里处理不稳定性,加上该段代码保证排序稳定 less_array.append(array[i]) else greater_array.append(array[i]) end end quick_sort(less_array) + [array[random_num]] + quick_sort(greater_array) end
# 不稳定快排优化代码--ruby --值排序 对重复值的顺序不在意的话可以考虑,在大量数据且多重复时,性能远远大于稳定快排 def value_quick_sort(array) return array if array.size <= 1 # 选取随机值,rand针对区间/某个数,sample针对数组,因此这里选前者更适合 random_value = array.sample n = array.count(random_value) value_quick_sort(array.select { |i| i < random_value}) + [random_value]*n + value_quick_sort(array.select { |i| i > random_value}) end
# 下标结合值 稳定快排,还有优化的地方,待完善,在大量数据且多重复时,性能远远大于稳定快排,数据重复越多,性能提升越大! def index_value_quick_sort(array) # 递归终点 return array if array.length <= 1 # 选取随机下标,rand针对区间/某个数,sample针对数组,因此这里选前者更适合 random_num = rand(array.length) value = array[random_num] n = array[0,random_num+1].count(value) m = 0 p = 0 # (i == value && i.object_id > value_object_id) 内存地址可否排序?待考虑,重复select,待优化 index_value_quick_sort(array.select { |i| i < value }) + array.select { |i| i if (i == value && (m += 1) && m < n) } + [value] + array.select { |i| i if (i == value && (p += 1) && p > n) } + index_value_quick_sort(array.select { |i| i > value}) end
# 网上百度百科ruby代码,稳定排序算法,未优化,默认取最后值进行快排,且会修改原数组 def quick_sort(a) (x=a.pop) ? quick_sort(a.select { |i| i <= x }) + [x] + quick_sort(a.select { |i| i > x }) : [] end
s1=[1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8, 25, 54, 54, 67, 96].size s2=[1, 1, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8, 25, 54, 54, 67, 96].size [1, 1, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8, 25, 54, 54, 67, 96] a=[2,1,3,2,54,3,6,7,5,4,8,96,67,54,3,25,1,2,2,2,2]*299 p a.length t= (Time.now) bb = index_value_quick_sort(a) p bb t1=(Time.now)
p t1 - t t=(Time.now)
aa = index_quick_sort(a) p aa t1=(Time.now)
p t1 - t p aa.length p bb.length p a.size