lua实现各大排序算法

最近用lua非常多,发现用lua写算法比cpp方便多了,就重新用lua写了一遍常用的排序算法,记录一下。

冒泡排序

最简短的排序算法

-- bubbleSort
-- 数组元素从头到尾前后两元素对比,更小(大)的数放前(后),重复数组长度-1次
-- 复杂度 0(n^2)	

function bubbleSort(t)
	for i=1, #t-1 do
		for j=1, #t-1 do
			if t[j] > t[j+1] then
				t[j], t[j+1] = t[j+1], t[j]
			end
		end
	end
end

ttt = {6,4,8,0,7,1,2,9,5,3}
print("before:")
print(table.concat(ttt,","))

bubbleSort(ttt)

print("after:")
print(table.concat(ttt,","))

插入排序

-- insertSort
-- 从头(尾)建立有序数组,遍历总数组从有序数组外取元素按大小插入有序数组中,直至遍历完总数组
-- 复杂度 0(n^2)	

function insertSort(t)
	for i=2, #t do
		for j=1, i-1 do
			local temp = t[i]
			if temp < t[j] then		-- 从已排序数组头开始遍历比较
				for k=i, j,-1 do	-- 有序数组插入位置后需向后投挪一位 给要插入的元素腾位置
					t[k] = t[k-1]
				end
				t[j] = temp
			end
		end
	end
end

function insertSort2(t)		-- 效率更高
	for i=2, #t do
		print("=====i",i)
		local temp = t[i]
		--[[	
		for j=i-1, 1, -1 do
			if temp < t[j] then	 -- way1 从已排序数组尾开始遍历比较 小于尾部元素则交换
				t[j+1] = t[j]
				t[j] = temp
			end
		end
		]]
		local j=i-1
		while j>=1 do
-- way2 从已排序数组尾开始遍历比较 找出适合的位置,顺便往后扩展挪一位 最后插入适合的位置
			if temp < t[j] then
				t[j+1] = t[j]
				j = j-1
			else
				break
			end
		end
		t[j+1] = temp
	end
end

ttt = {4,2,5,1,3}
print("before:")
print(table.concat(ttt,","))

-- insertSort(ttt)
insertSort2(ttt)

print("after:")
print(table.concat(ttt,","))

选择排序

-- selectSort
-- 遍历数组每次选择最小或最大的值替换到数组头或尾
-- 复杂度 0(n^2)	

function selectSort(t)
	for i=1, #t-1 do
		local idx = i
		for j=i+1, #t do
			if t[idx] > t[j] then
				idx = j
			end
		end
		t[i], t[idx] = t[idx], t[i]
	end
end

ttt = {6,4,8,0,7,1,2,9,5,3}
print("before:")
print(table.concat(ttt,","))

selectSort(ttt)

print("after:")
print(table.concat(ttt,","))

桶排序

-- bucketSort
-- 确定几个桶,将数组中的各个元素散列到各个桶中,后续桶要比前面桶的元素都大
-- 然后对桶中所有元素排序,最后按桶顺序,输出就是排序后的结果

-- 主要是根据数组中不同元素的大小 放入不同的桶中
-- 时间复杂度 O(n^2)	

function printTable(t)
	for i,v in pairs(t) do
		print("i,v",i,v)
		if type(v) == "table" then
			printTable(v)
		end
	end
end

function selectSort(t)
	for i=1, #t-1 do
		local idx = i
		for j=i+1, #t do
			if t[idx] > t[j] then
				idx = j
			end
		end
		t[i], t[idx] = t[idx], t[i]
	end
end

function bucketSort(t)
	local maxNum = t[1]
	local minNum = t[1]

	-- 找出数组中最大和最小值
	for i=1, #t do	
		maxNum = math.max(maxNum, t[i])
		minNum = math.min(minNum, t[i])
	end

	-- 确定桶的数量
	-- local bucketCnt = math.floor((maxNum-minNum)/#t) + 1
	local bucketCnt = 2

	-- 初始化桶
	local bucketAttr = {}
	for i=1, bucketCnt do	
		bucketAttr[i] = {}
	end

	-- 每个桶数据大小的区间范围
	local gap = math.floor((maxNum-minNum)/bucketCnt)+1

	-- 按大小范围存入不同桶中
	for i=1, #t do
		local idx = math.floor(t[i]/gap) + 1
		bucketAttr[idx][#bucketAttr[idx]+1] = t[i]
	end

-- printTable(bucketAttr)

	-- 对桶内元素排序
	for i=1, bucketCnt do	
		selectSort(bucketAttr[i])
	end

	-- 合并
	local finTable = {}
	for i=1, #bucketAttr do
		for j=1, #bucketAttr[i] do
			finTable[#finTable+1] = bucketAttr[i][j]
		end
	end

	return finTable
end

ttt = {4,9,2,8,0,5,6,3,7,1}
print("before:")
print(table.concat(ttt,","))

local fin = bucketSort(ttt)

print("after:")
print(table.concat(fin,","))

计数排序

-- countingSort
--[[ 计数排序 要求被排序的数据必须为>0的整数
	因为计数排序是将数据作为一个哈希表的key存入的 t[number] = cnt
	被排序的数中每出现一个number,cnt++
	最后对cnt>1的值,从小到大按顺序输出cnt次对应的number 就是排序后的数组
]]
-- 计数排序其实就是空间换效率的排序方式,要根据排序数组中的最大最小值范围确定空间
-- 时间复杂度 O(n+k) k是待排序列最大值
-- 空间复杂度 O(k)

function countingSort(t)
	local maxNum = t[1]
	local minNum = t[1]
	local idxTable = {}

	for i,v in ipairs(t) do
		maxNum = math.max(maxNum, v)
		minNum = math.min(minNum, v)
	end

	for i=minNum, maxNum do
		idxTable[i] = 0
	end

	for i,v in ipairs(t) do
		if idxTable[i] then
			idxTable[i] = idxTable[i] + 1
		end
	end

	local tarTable = {}
	for i=minNum, maxNum do
		while idxTable[i] > 0 do
			tarTable[#tarTable+1] = i
			idxTable[i] = idxTable[i] - 1
		end
	end

	return tarTable
end

ttt = {4,9,2,8,5,6,3,7,1}
print("before:")
print(table.concat(ttt,","))

local fin = countingSort(ttt)

print("after:")
print(table.concat(fin,","))

基数排序

-- radixSort
-- 基数排序是基于桶排序和计数排序的思想 基础的只能对正整数组进行排序
-- 分配9个桶的哈希表,获取数组中每个数的第X位的数作为桶的idx按顺序放入桶
-- 然后按桶的idx顺序0-9返回给数组。继续X++,按顺序返回给数组,最后没有>X位的数了 排序完成

-- 时间复杂度 O(n*k) k是元素位数 空间复杂度 O(n)

function radixSort(t)
	local bit = 1
	local vector = {}

	-- 找出最大值
	local maxNum = t[1]
	for i=1, #t do
		maxNum = math.max(maxNum, t[i])
	end

	while math.floor(maxNum / bit) % 10 > 0 do	-- 根据最大值的位数确定遍历次数
		-- 初始化桶
		for i=0, 9 do
			vector[i] = {}
		end
		for i=1, #t do
			-- 获得该数中bit位置的数 作为桶索引插入
			local remd = math.floor(t[i] / bit) % 10 
			vector[remd][#vector[remd]+1] = t[i]
		end

		bit = bit * 10
		local len=1
		for i=0, 9 do
			for j=1, #vector[i] do
				t[len] = vector[i][j]
				len = len + 1
			end
		end
	end
end

ttt = {44,9999,2,888,10,53,643,359,4378,123}
print("before:")
print(table.concat(ttt,","))

radixSort(ttt)

print("after:")
print(table.concat(ttt,","))

归并排序

-- 归并排序 递归和合并
-- 复杂度 0(n*logN)	

-- start到mid和mid+1到end的数据是已经排好序的,将整个t排好序

function merge(t, start, mid, tail)
	local tempT = {}
	local p1 = start
	local p2 = mid + 1
	while p1 <= mid and p2 <= tail do
		if t[p1] and t[p2] then		-- 注意越界
			if t[p1] <= t[p2] then
				tempT[#tempT+1] = t[p1]
				p1 = p1 + 1
			else
				tempT[#tempT+1] = t[p2]
				p2 = p2 + 1
			end
		end
	end

	if p1 <= mid then
		for i=p1, mid do
			tempT[#tempT+1] = t[i]
		end
	end
	if p2 <= tail then
		for i=p2, mid do
			tempT[#tempT+1] = t[i]
		end
	end

	for i, v in ipairs(tempT) do
		t[start+i-1] = tempT[i]
	end
end

function sort(t, start, tail)
	if start >= tail then return end

	local mid = math.floor((start+tail)/2)	-- 这里必须向下取整,因为122时p2=3 进入不了循环
    -- 分
	sort(t, start, mid)			-- 将左半边递归排序
	sort(t, mid+1, tail)		-- 将右半边递归排序
	-- 治
	merge(t, start, mid, tail)	-- 将整个数组排序
end


ttt = {4,9,2,8,5,6,3,7,1}
print("before:")
print(table.concat(ttt,","))

sort(ttt, 1, #ttt)

print("after:")
print(table.concat(ttt,","))

快速排序

-- quickSort
--[[
	另外一种递归的方式,从列表中取一个基准数,遍历数组将小于和大于基准数的数
	分别放到不同区间范围,基准数放在中间,利用递归的思想,将两边的数再进行取基准
	分两边的操作,直到递归完。
]]

-- 时间复杂度 O(n*logn) 空间复杂度 O(1)

function getPivot(t, start, tail)
	local pivot = start
	local biggerIdx = start + 1
	-- 保证<biggerIdx的前面都是小于pivot的数 不包含t[biggerIdx]
	for i=start+1, tail do
		if t[i] <= t[pivot] then
			t[i], t[biggerIdx] = t[biggerIdx], t[i]
			biggerIdx = biggerIdx + 1
		end
	end
	-- t[biggerIdx] 是大于t[pivot]的
	t[pivot], t[biggerIdx-1] = t[biggerIdx-1], t[pivot]
	pivot = biggerIdx - 1
	return pivot
end

function quickSort(t, start, tail)
	if start >= tail then return end 

	local pivot = getPivot(t, start, tail)
	quickSort(t, start, pivot-1)
	quickSort(t, pivot+1, tail)
end

ttt = {4,9,2,8,5,6,3,7,1}
print("before:")
print(table.concat(ttt,","))

quickSort(ttt, 1, #ttt)

print("after:")
print(table.concat(ttt,","))
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值