默认首元素为最(大/小)值,接着与剩余元素逐一比较找出真正的最值元素;
中间过程的状态描述:
序列前段部分的元素有序,后段为待排序部分.
该假设之所以默认选择首元素位为最值,是为了遍历方便;
也可以默认最后一个元素位为最值,甚至是任一中间元素,只不过是需要修改对待排序区间的描述
(选择中间元素,则有可能使得简单问题变得复杂化).
精炼代码
template <typename T>
void DirectSelectionSort(T* arr, const std::size_t n) {
assert(arr);
for (std::size_t i = 0; i < n - 1; ++i) {
std::size_t minIndex = i;//升序;
for (std::size_t j = i + 1; j < n; ++j) {
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
}
if (minIndex != i) {
std::swap(arr[minIndex], arr[i]);
}
}
}
代码草稿
//直接选择排序;
//最原始默认首元素为最(大/小)值,接着与剩余元素逐一比较找出真正的最值元素;
template <typename T>
//void DataSort::DirectSelectionSort(T* arr, const std::size_t n) {
void DirectSelectionSort(T* arr, const std::size_t n) {
assert(arr);
for (std::size_t i = 0; i < n - 1; ++i) {
//for (std::size_t i = 0, j = i + 1; i < n - 1; ++i) {
std::size_t minIndex = i;//升序时使用;
//std::size_t maxIndex = i;//降序时使用;
for (std::size_t j = i + 1; j < n; ++j) {
//for ( j = i + 1; j < n; ++j) {
if (arr[j] < arr[minIndex]) {
//std::swap(arr[j], arr[i]);//该行代码会导致多余的元素交换操作,故而引入最值索引进行优化;
minIndex = j;
}
//该if条件语句可修改成如下三目运算;
//minIndex = arr[j] < arr[minIndex] ? j : minIndex;
}
if (minIndex != i) {
std::swap(arr[minIndex], arr[i]);
}
/*std::cout << "DirectSelectionSort 当前序列: i = " << i << " j = " << j << " minIndex = " << minIndex << std::endl;
RandomArrayFuntionHelper::PrintArray(arr, n); */
}
}
精炼代码
//双端选择排序;
template <typename T>
void HeadTailSelectionSort(T* arr, const std::size_t n) {
assert(arr);
for (std::size_t i = 0, j = i + 1; i < (n >> 1); ++i) {//位运算需要括号,不分有无符号;
std::size_t minIndex = i;//该索引往左侧有序;
std::size_t maxIndex = n - 1 - i;//该索引往右侧有序(初始值状态除外);
if (arr[i] >= arr[n - 1 - i]) {
std::swap(arr[i], arr[n - 1 - i]);
}
for (j = i; j < n - i; ++j) {
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
maxIndex = arr[j] > arr[maxIndex] ? j : maxIndex;
}
if (minIndex != i) {
std::swap(arr[minIndex], arr[i]);
}
if (maxIndex != n - 1 - i) {
std::swap(arr[maxIndex], arr[n - 1 - i]);
}
}
}
温馨提示:
断言语句 assert(arr); 开头需要include头文件cassert(C++),即:
#include
代码草稿
//双端选择排序;
template <typename T>
//void DataSort::HeadTailSelectionSort(T* arr, const std::size_t n) {
void HeadTailSelectionSort(T* arr, const std::size_t n) {
assert(arr);
//双端扫描,中间部分为无序区间,外层循环次数可减半;
//for (std::size_t i = 0; i < n / 2; ++i) {
////for (std::size_t i = 0, j = i + 1; i < n / 2; ++i) {
for (std::size_t i = 0, j = i + 1; i < (n >> 1); ++i) {//位运算需要括号,不分有无符号;
//假设最终要求数列升序,则应使得左小右大;
//借助 i 实现两端索引向中间挪位,当然也可分别 ++minIndex 和 --maxIndex;
std::size_t minIndex = i;//该索引往左侧有序;
std::size_t maxIndex = n - 1 - i;//该索引往右侧有序(初始值状态除外);
//首先要确保最大最小匹配:存在设计漏洞即——当最小索引所在位置即是所有元素的最大值时,会导致一轮刷选结果的最大索引获取的是第二大的值;
//https://wenku.baidu.com/view/a6120c53bd64783e08122b2f.html;
if (arr[i] >= arr[n - 1 - i]) {
std::swap(arr[i], arr[n - 1 - i]);
}
//for (std::size_t j = i + 1; j < n - i ; ++j) {
for ( j = i ; j < n - i; ++j) {
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
maxIndex = arr[j] > arr[maxIndex] ? j : maxIndex;
}
if (minIndex != i) {
std::swap(arr[minIndex], arr[i]);
}
if (maxIndex != n - 1 - i) {
std::swap(arr[maxIndex], arr[n - 1 - i]);
}
//参考文献:https://www.doc88.com/p-6816672556940.html
/*std::cout << "HeadTailSelectionSort 当前序列: i = " << i << " j = " << j << " minIndex = " << minIndex << " maxIndex = "<< maxIndex << std::endl;
RandomArrayFuntionHelper::PrintArray(arr, n);*/
}
}
双向选择排序算法参考文章:
两端选择排序算法
选择排序算法过程演示,请参考:
排序算法过程演示
交流方式
QQ —— 2636105163(南国烂柯者)
温馨提示:
转载请注明出处!!
2020年3月29日20:55:40