Lua版常用排序算法实现

准备工作

是参考这里,根据自己理解写的lua版,若有问题或者更好方案,可以留言讨论哦!
时间复杂度从小到大: 冒泡(O(n2))–>选择(O(n2))–>插入(O(n2))–>快速(O(nlogn))–>希尔(分段,O(n1.5))–>堆排序(O(n))

  1. 打印表数
-- 打印表数据
local function printTable(arg)
    if arg == nil then
        print("输入表为空")
        return
    end

    if type(arg) ~= "table" then
        print(arg)
        return
    end

    local t = "{"
    for k, v in pairs(arg) do
        t = t .. v .. ","
    end
    print(t .. "}")
end
  1. 数组数据交换
-- 数组i,j位置交换数据
local function Swap(tab,i,j,isPrint)
	local length = #tab
	if i == j or i < 1 or j < 1 or j > length or i > length then
		return
	end
    local temp = tab[i]
    tab[i] = tab[j]
    tab[j] = temp
    if isPrint ~= nil then
    	printTable(arr)
    end
end
  1. 准备数据
-- 准备相同的数组
local arr0 = {2,5,3,6,7,1,4,8,0,9}
local arr1 = {2,5,3,6,7,1,4,8,0,9}
local arr2 = {2,5,3,6,7,1,4,8,0,9}
local arr3 = {2,5,3,6,7,1,4,8,0,9}
local arr4 = {2,5,3,6,7,1,4,8,0,9}
local arr5 = {2,5,3,6,7,1,4,8,0,9}
  1. table数据翻转(补充)
    下了实现的排序方法默认是升序的,为了降序加了参数isDes,可以利用这个翻转函数,但是为了练手自己又写了降序的方法,自行参考
-- table数据翻转
function ReverseTable(tab)
	local length = #tab
	if length < 1 then
		return
	end
	local start = 1
	while start < length do
		Swap(tab,start,length)
		start = start + 1
		length = length - 1
	end
end

冒泡排序

  • 思路
    两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止
  • 排序方法
-- 冒泡排序: isDes是否为降序
function BubbleSort(tab,isDes) 
    if tab == null  or type(tab) ~= "table" then
        return
    end
    
    local length = #tab
    if length < 1 then 
        return
    end

    if isDes then
        for i = length, 1 , -1 do
        	for j = i+1,length do
	            if tab[j - 1] < tab[j] then
	                Swap(tab,j-1,j)
	            end
        	end
    	end
        return
    end

	for i = 1, length do
        for j = length,i +1, -1 do
            if tab[j - 1] > tab[j] then
                Swap(tab,j-1,j)
            end
        end
     end

end
  • 优化排序
-- 冒泡排序: isDes是否为降序,优化版
function BubbleSortOpt(tab,isDes) 
    if arr == null  or type(tab) ~= "table" then
        return
    end
    
    local length = #tab
    if length < 1 then 
        return
    end

    local flag = true
    if isDes then
        for i = length, 1, -1 do
	        if not flag then
	            break
	        end
	        flag = false
	        for j = 1,i-1 do
	            if tab[j ] < tab[j+1] then
	                Swap(tab,j,j + 1)
	                flag = true
	            end
        	end
    	end
        return
    end
	for i = 1, length do
        if not flag then
            break
        end

        flag = false
        for j = length,i +1, -1 do
            k = k+1
            if tab[j - 1] > tab[j] then
                Swap(tab,j-1,j)
                flag = true
            end
        end
    end
end
  • 排序测试
printTable(arr0)
-- 升序
BubbleSort(arr0)
printTable(arr0)
BubbleSortOpt(arr1)
printTable(arr1)
-- 降序
BubbleSort(arr2,true)
printTable(arr2) 
BubbleSortOpt(arr3,true)
printTable(arr3)
  • 优化说明
    添加一个标识flag,当再一次遍历已经是有序的时候(无需再交换数据),就可以停止了遍历了

选择排序

  • 思路
    每次从在n-i+1(i=1,2,…,n-1) 个数据中找到最小(或最大)的数据,与i位置数据进行交换
  • 排序方法
-- 选择排序: isDes是否为降序
function SelectSort(tab,isDes) 
    if tab == null  or type(tab) ~= "table" then
        return
    end
    local length = #tab
    if length < 1 then 
        return
    end

    if isDes then
       for i = 1, length do
	        local max = i
	        for j = i+1,length do
	            if tab[max] < tab[j] then
	                max = j
	            end
	        end

	        if i ~= max then
	            Swap(tab,i,max)
	        end
	    end
        return
    end

     for i = 1, length do
        local min = i
        for j = i+1,length do
            if tab[min] > tab[j] then
                min = j
            end
        end

        if i ~= min then
            Swap(tab,i,min)
        end
    end

end
  • 优化排序
-- 选择排序: isDes是否为降序,优化版
function SelectSortOpt(tab,isDes)
	if tab == nil or type(tab) ~= "table" then
		return
	end

	local length = #tab
	if length < 1 then
		return
	end

	local temp,index,i = 1,1, 1
	if isDes then
		while i <= length do
			if i < temp and tab[i] < tab[temp] then
				Swap(tab,i, temp)
				i = i + 1
			end

			index = i
			for j = i + 1, length do
				if tab[j] > tab[index] then
					temp = index
					index = j
				elseif tab[j] > tab[temp] then
					temp = j
				end
			end

			if i ~= index then
				Swap(tab, i, index)
			end
			i = i + 1
		end
		return
	end

	while i <= length do
		if i < temp and tab[i] > tab[temp] then
			Swap(tab,i,temp)
			i = i + 1
		end
		index = i
		for j = i +1 , length do
			if tab[j] < tab[index] then
				temp = index
				index = j
			elseif tab[j] < tab[temp] then
				temp = j
			end
		end
		if i ~= index then
			Swap(tab,i,index)
		end
		i = i + 1
	end

end
  • 排序测试
printTable(arr0)
-- 升序
SelectSort(arr0) 
printTable(arr0)
SelectSortOpt(arr1) 
printTable(arr1)
-- 降序
SelectSort(arr2,true) 
printTable(arr2)
SelectSortOpt(arr3,true) 
printTable(arr3)
  • 优化说明
    一次循环中,在找到最小(或最大)值之前,min(或max)所标识的就是当前的最小(或最大)值,找到数组的最小(或最大)值后用temp先缓存当前的min(或max),在下次循环之前,temp所标记的就是剩余数值中最小(或最大)的值了,可以先进行一次交换,可省一次循环

插入排序

  • 思路
    将一个数据插入到已排好序的表中,从而得到一个新的、个数增1的有序表
  • 排序方法
-- 插入排序: isDes是否为降序
function InsertSort(tab,isDes) 
    if tab == null  or type(tab) ~= "table" then
        return
    end
    local length = #tab
    if length < 1 then 
        return
    end

    if isDes then
        for i = 2, length do
            if tab[i] > tab[i - 1] then
                local j,temp = i-1,tab[i]
                while j > 0 and tab[j] < temp do
                    tab[j+1]= tab[j]
                    j = j -1
                end
                tab[j+1] = temp
            end
        end
        return
    end

    for i = 2, length do
         if tab[i] < tab[i - 1] then
             local j,temp = i-1,tab[i]
             while j > 0 and tab[j] > temp do
                 tab[j+1]= tab[j]
                 j = j -1
             end
             tab[j+1] = temp
         end
     end
end
  • 优化排序
    插入排序算的优化是 希尔排序,后面会有 希尔排序 算法实现
  • 排序测试
printTable(arr0)
-- 升序
InsertSort(arr0) 
printTable(arr0)
-- 降序
InsertSort(arr1,true) 
printTable(arr1)

希尔排序(插入排序升级版)

  • 思路
  1. 基本有序:
    小的关键字基本在前面,大的关键字基本在后面,不大不小的基本在中间。
  2. 跳跃分割策略:
    将相距某个“增量”的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序。
  • 排序方法
-- 希尔排序: isDes是否为降序
function ShellSort(tab,isDes) 
    if tab == null  or type(tab) ~= "table" then
        return
    end
    local length = #tab
    if length < 1 then 
        return
    end
    -- math.modf计算整数和小数部分,div为整数部分,dd为小数部分
    local div,dd = math.modf(length) 
    if isDes then
        repeat
            div,dd = math.modf(div / 3+ 1) 
            --print(div,dd)
            for i = div+1,length do 
                if tab[i] > tab[i - div] then
                    local j,temp = i-div,tab[i]
                    while j > 0 and tab[j] < temp do
                        tab[j+div]= tab[j]
                        j = j -div
                    end 
                    tab[j+div] = temp
                end
            end
        until div < 2

        return
    end

    repeat
        div,dd = math.modf(div / 3+ 1) 
        print(div,dd)
        for i = div+1,length do
            if tab[i] < tab[i - div] then
                local j,temp = i - div,tab[i]
                while j > 0 and tab[j] > temp do
                    tab[j+div] = tab[j]
                    j = j - div
                end
                tab[j+div] = temp
            end
        end
    until div < 2
end
  • 排序测试
printTable(arr0)
-- 升序
ShellSort(arr0) 
printTable(arr0)
-- 降序
ShellSort(arr1,true) 
printTable(arr1)
  • 优化说明
  1. 希尔排序的关键并不是随便分组后各自排序,而是将相隔某个增量的数组组成一个子序列,实现跳跃式的移动。
  2. 增量的选择实验证明当增量序列为delt[k]=2^(t-k+1)-1( 0<=k<=t<=log2(n+1))时,效果较佳,但注意最后增量值必须等于1。
  3. 此时时间复杂度为O(n^1.5)
  4. 希尔排序因为是跳跃式记录,故不是一个稳定的排序算法。

快速排序

  • 思路
    通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键值均比另一部分记录的关键值小,则可以分别对这两部分记录继续进行排序,以达到整个序列有序的目的
  • 排序方法
local function Partition(tab,startIndex,endIndex)
	local pivotKey = tab[startIndex]
	while startIndex < endIndex do
		while startIndex < endIndex and tab[endIndex] >= pivotKey do
			endIndex  = endIndex -1
		end
		Swap(tab,startIndex, endIndex)

		while startIndex < endIndex and tab[startIndex] <= pivotKey do
			startIndex = startIndex + 1
		end
		Swap(tab,startIndex,endIndex)
	end
	return startIndex
end

local function GoToQuickSort(tab,startIndex,endIndex)
	if type(tab) == "table" and startIndex <= endIndex then
		_QuickSort(tab,startIndex,endIndex)
	end
end

function _QuickSort(tab,startIndex,endIndex)
	if startIndex == nil or type(startIndex) ~= "number" then
		startIndex = 1
	end

	if endIndex == nil or type(endIndex) ~= "number" then
		endIndex = length
	end

	if startIndex < endIndex then
		local pivotkey = Partition(tab,startIndex, endIndex)
		GoToQuickSort(tab,startIndex,pivotkey - 1)
		GoToQuickSort(tab,pivotkey + 1,endIndex)
	end

end

function QuickSort(tab,isDes)
	if tab == nil or type(tab) ~= "table" then
		return
	end

	local length = #tab
	if length <= 1 then
		return
	end
	_QuickSort(tab,1,length)
	-- _QuickSort 实现升序,这里使用翻转实现降序
	if isDes then
		ReverseTable(tab)
	end
end
  • 排序测试
printTable(arr0)
QuickSort(arr0)
printTable(arr0)
QuickSort(arr1,true)
printTable(arr1)
  • 优化说明
  • 最优与平均时间复杂度O(nlogn)
  • 最坏时间复杂度O(n^2)
  • 空间复杂度O(logn)
  • 快速排序是一种不稳定的排序方法

归并排序

堆排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值