CMAKE脚本中的一个快排序算法

写这个算法纯粹是为了学习cmake的编程语法,和macro/function的参数传递的逻辑。
仅作为cmake学习的联系之用,顺便复习一下经典的快排序算法的实现原理。

可以通过以下命令来验证执行结果:

cmake -P ./QuickSort.cmake

排序结果输出为:

-- 1: 1
-- 2: 4
-- 3: 5
-- 4: 6
-- 5: 7
-- 6: 8
-- 7: 8
-- 8: 9
-- 9: 10
-- 10: 12
-- 11: 99

QuickSort.cmake源码如下:

# 文件名:QuickSort.cmake

cmake_minimum_required(VERSION 3.12)


## 对一个LIST进行快排序
function(gen_random max out)
    execute_process( COMMAND "./gen_random.sh" ${max}
                     RESULT_VARIABLE rslt
                     OUTPUT_VARIABLE out_num)

    set(${out} "${out_num}" PARENT_SCOPE)

endfunction()

function(print_vars nums len)
    math(EXPR len "${len} - 1")
    foreach(i RANGE ${len})
        message(STATUS "${nums}_${i}==${${nums}_${i}}")
    endforeach()
endfunction()


macro(swap var_a var_b)
    set(tmp ${${var_a}})
    set(${var_a} ${${var_b}})

    set(${var_b} ${tmp})
endmacro()


#
# 由于cmake本身变量没有像c/c++一样可以通过“引用”或者“指针”直接修改函数调用者的元素
# 因此采用循环算法而不是递归算法来规避这个问题
#
function(quick_sort data sorted_nums) 
    #set(${sorted_nums} ${nums} PARENT_SCOPE)

    set(i 0)
    foreach(n IN LISTS ${data})
        set(num_${i} ${n})
        math(EXPR i "${i}+1")
    endforeach()

    # 这里${data}只是input_data字符串值
    # message(STATUS "\${data}=${data}")

    list(LENGTH ${data} len)

    if (${len} LESS_EQUAL 1)
        return()
    endif()

    # 添加一个排序任务
    list(APPEND sort_task "0-${len}")

    while(TRUE)
        
        list(LENGTH sort_task tasks)

        if (${tasks} EQUAL 0)
            break()
        endif()

        list(POP_FRONT sort_task task)

        STRING(FIND ${task} "-" idx)

        STRING(SUBSTRING ${task} 0 ${idx} i)
        math(EXPR idx "${idx} + 1")
        STRING(SUBSTRING ${task} ${idx} 10 j)

        SET(start ${i})
        SET(end ${j})

        math(EXPR j "${j}-1")
        set(base ${num_${i}})

        while(${i} LESS ${j})

            while(${i} LESS ${j})

                set(cur ${num_${j}})

                if( ${base} LESS ${cur})
                    math(EXPR j "${j}-1")
                else()
                    break()
                endif()

            endwhile()

            while(${i} LESS ${j})

                set(cur ${num_${i}})

                if(${cur} LESS_EQUAL ${base})
                    math(EXPR i "${i}+1")
                else()
                    break()
                endif()

            endwhile()

            swap(num_${i} num_${j})

        endwhile()
        swap(num_${start} num_${j})

        set(split ${j})
        if (${split} GREATER ${start})
            list(APPEND sort_task "${start}-${split}")
        endif()

        math(EXPR split "${j}+1")
        if (${split} LESS ${end})
            list(APPEND sort_task "${split}-${end}")
        endif()

    endwhile()

    # 排序完毕,返回输出列表
    set(output)
    set(i 0)
    foreach(n IN LISTS ${data})
        list(APPEND output ${num_${i}})
        math(EXPR i "${i}+1")

    endforeach()

    set(${sorted_nums} ${output} PARENT_SCOPE)
    
endfunction()

#----------------------------------------------------------------
# 测试用例
#----------------------------------------------------------------
set(input_data  1 8 12 7 6 5 8 4 9 10 99)
quick_sort(input_data sorted_data)

set(i 1)
list(LENGTH sorted_data len)

#打印排序好的列表
foreach(i RANGE 1 ${len})
    math(EXPR idx "${i}-1")
    list(GET sorted_data ${idx} n)
    message(STATUS  "${i}: ${n}")
endforeach()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农心语

您的鼓励是我写作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值