gctl/lib/algorithm/heap_sort.h
2024-09-10 15:45:07 +08:00

251 lines
7.1 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************
* ██████╗ ██████╗████████╗██╗
* ██╔════╝ ██╔════╝╚══██╔══╝██║
* ██║ ███╗██║ ██║ ██║
* ██║ ██║██║ ██║ ██║
* ╚██████╔╝╚██████╗ ██║ ███████╗
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
* Geophysical Computational Tools & Library (GCTL)
*
* Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn)
*
* GCTL is distributed under a dual licensing scheme. You can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 2
* of the License, or (at your option) any later version. You should have
* received a copy of the GNU Lesser General Public License along with this
* program. If not, see <http://www.gnu.org/licenses/>.
*
* If the terms and conditions of the LGPL v.2. would prevent you from using
* the GCTL, please consider the option to obtain a commercial license for a
* fee. These licenses are offered by the GCTL's original author. As a rule,
* licenses are provided "as-is", unlimited in time for a one time fee. Please
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
* to include some description of your company and the realm of its activities.
* Also add information on how to contact you by electronic and paper mail.
******************************************************/
#ifndef _GCTL_HEAPSORT_H
#define _GCTL_HEAPSORT_H
// library's head file
#include "../core.h"
namespace gctl
{
template <typename T>
class heap_sort
{
public:
/**
* 定义向量中的元素比较函数的指针,这个函数指针专用于堆排序算法。
* 因为我们不能确定在实际使用中需要进行比较的元素类型,所以不同通过
* 定义固定类型返回值的函数指针来达到比较的目的。
*
* 此函数的定义必须为下述形式替换variable为需要进行比较的变量 此时为升序排序)
* if (a[left_index].<variable> < a[right_index].<variable>) return true;
* else return false;
* (此时为降序排序)
* if (a[left_index].<variable> > a[right_index].<variable>) return true;
* else return false;
*/
typedef bool (*compare_func_ptr)(std::vector<T> &a, int left_index, int right_index);
/**
* @brief 更新堆排序
*
* @param a 目标向量
* @param[in] i 第一排序值
* @param[in] n 第二排序值
* @param[in] fp 比较函数
*/
void update_heap(std::vector<T> &a, int i, int n, compare_func_ptr fp)
{
int iMax = i, iLeft = 2 * i + 1, iRight = 2 * (i + 1);
if (iLeft < n && fp(a, iMax, iLeft))
{
iMax = iLeft;
}
if (iRight < n && fp(a, iMax, iRight))
{
iMax = iRight;
}
if (iMax != i)
{
T tmp = a[iMax]; a[iMax] = a[i]; a[i] = tmp;
update_heap(a, iMax, n, fp);
}
return;
}
/**
* @brief 执行排序
*
* @param a 目标向量
* @param[in] fp 比较函数
*/
void execute(std::vector<T> &a, compare_func_ptr fp)
{
int n = a.size();
for (int i = (n - 1) / 2; i >= 0; i--)
{
update_heap(a, i, n, fp);
}
T tmp;
for (int i = n - 1; i > 0; --i)
{
tmp = a[i]; a[i] = a[0]; a[0] = tmp;
update_heap(a, 0, i, fp);
}
return;
}
/**
* 下面我们定义一套纯数组形式的重载
*/
/**
* 定义向量中的元素比较函数的指针,这个函数指针专用于堆排序算法。
* 因为我们不能确定在实际使用中需要进行比较的元素类型,所以不同通过
* 定义固定类型返回值的函数指针来达到比较的目的。
*
* 此函数的定义必须为下述形式替换variable为需要进行比较的变量 此时为升序排序)
* if (a[left_index].<variable> < a[right_index].<variable>) return true;
* else return false;
* (此时为降序排序)
* if (a[left_index].<variable> > a[right_index].<variable>) return true;
* else return false;
*/
typedef bool (*compare_func_ptr2)(T *a, int left_index, int right_index);
/**
* @brief 更新堆排序
*
* @param a 目标向量
* @param[in] i 第一排序值
* @param[in] n 第二排序值
* @param[in] fp 比较函数
*/
void update_heap(T *a, int i, int n, compare_func_ptr2 fp)
{
int iMax = i, iLeft = 2 * i + 1, iRight = 2 * (i + 1);
if (iLeft < n && fp(a, iMax, iLeft))
{
iMax = iLeft;
}
if (iRight < n && fp(a, iMax, iRight))
{
iMax = iRight;
}
if (iMax != i)
{
T tmp = a[iMax]; a[iMax] = a[i]; a[i] = tmp;
update_heap(a, iMax, n, fp);
}
return;
}
/**
* @brief 执行排序
*
* @param a 目标数组
* @param n 数组大小
* @param[in] fp 比较函数
*/
void execute(T *a, int n, compare_func_ptr2 fp)
{
for (int i = (n - 1) / 2; i >= 0; i--)
{
update_heap(a, i, n, fp);
}
T tmp;
for (int i = n - 1; i > 0; --i)
{
tmp = a[i]; a[i] = a[0]; a[0] = tmp;
update_heap(a, 0, i, fp);
}
return;
}
/**
* 下面我们定义一套array形式的重载
*/
/**
* 定义向量中的元素比较函数的指针,这个函数指针专用于堆排序算法。
* 因为我们不能确定在实际使用中需要进行比较的元素类型,所以不同通过
* 定义固定类型返回值的函数指针来达到比较的目的。
*
* 此函数的定义必须为下述形式替换variable为需要进行比较的变量 此时为升序排序)
* if (a[left_index].<variable> < a[right_index].<variable>) return true;
* else return false;
* (此时为降序排序)
* if (a[left_index].<variable> > a[right_index].<variable>) return true;
* else return false;
*/
typedef bool (*compare_func_ptr3)(array<T> &a, int left_index, int right_index);
/**
* @brief 更新堆排序
*
* @param a 目标向量
* @param[in] i 第一排序值
* @param[in] n 第二排序值
* @param[in] fp 比较函数
*/
void update_heap(array<T> &a, int i, int n, compare_func_ptr3 fp)
{
int iMax = i, iLeft = 2 * i + 1, iRight = 2 * (i + 1);
if (iLeft < n && fp(a, iMax, iLeft))
{
iMax = iLeft;
}
if (iRight < n && fp(a, iMax, iRight))
{
iMax = iRight;
}
if (iMax != i)
{
T tmp = a[iMax]; a[iMax] = a[i]; a[i] = tmp;
update_heap(a, iMax, n, fp);
}
return;
}
/**
* @brief 执行排序
*
* @param a 目标数组指针
* @param[in] fp 比较函数
*/
void execute(array<T> &a, compare_func_ptr3 fp)
{
int n = a.size();
for (int i = (n - 1) / 2; i >= 0; i--)
{
update_heap(a, i, n, fp);
}
T tmp;
for (int i = n - 1; i > 0; --i)
{
tmp = a[i]; a[i] = a[0]; a[0] = tmp;
update_heap(a, 0, i, fp);
}
return;
}
};
}
#endif //_GCTL_HEAPSORT_H