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