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

发布于:2024-08-15 ⋅ 阅读:(157) ⋅ 点赞:(0)

写这个算法纯粹是为了学习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()


网站公告

今日签到

点亮在社区的每一天
去签到