最近看算法导论回顾了下数据结构,便用基于二叉树写了堆排序算法,写得比较麻烦,用静态链表会好很多,那就直接上代码了
二叉树
存储结构
typedef double datatype; //数据类型取别名
typedef struct HeapNode //树存储结构定义
{
datatype data; //树数据域
struct HeapNode* left; //树左孩子
struct HeapNode* right; //树右孩子
int pos; //树中结构的顺序标志位
}HNode, *PHNode;
创建树
/************************************************************************/
/* 树的创建
参数:data 创建的树中的数据
参数:pos 插入的位置,初始调用为0
参数:data_length 需要插入的总个数
返回值:创建好的树*/
/************************************************************************/
PHNode CHeapSort::CreateBiTree(const double* data, const int pos, const int data_length)
{
if (nullptr == data) //判断输入数据是否为空
{
std::cout << "the input data is empty!\n";
return nullptr;
}
if ((NULL==data[pos]) || (pos>data_length)) //判断需要添加的数据是否已经完成 超过最大长度
{
return nullptr;
}
HNode *p = new HNode; //创建新结点
if (nullptr == p) //判断是否创建成功
{
std::cout << "error occurred while create tree\n";
return nullptr;
}
p->data = data[pos]; //对数据域赋值
p->pos = pos; //节点序列标志位
p->left = CreateBiTree(data, pos*2, data_length); //创建左孩子
p->right = CreateBiTree(data, pos*2+1, data_length); //创建右孩子
return p;
}
前序、中序、后序遍历树
/************************************************************************/
/*
树的前序遍历
参数: m_tree 需要遍历的树
返回值: void
*/
/************************************************************************/
void CHeapSort::PreOrder(PHNode m_tree)
{
if (nullptr != m_tree)
{
PreOrder(m_tree->left); //中序遍历左子树
std::cout << m_tree->data << " "; //显示数据
PreOrder(m_tree->right); //中序遍历右子树
}
}
/************************************************************************/
/*
树的中序遍历
参数: m_tree 需要遍历的树
返回值: void
*/
/************************************************************************/
void CHeapSort::InOrder(PHNode m_tree)
{
if (nullptr != m_tree)
{
InOrder(m_tree->left); //中序遍历左子树
std::cout << m_tree->data << " " ; //显示数据
InOrder(m_tree->right); //中序遍历右子树
}
}
/************************************************************************/
/*
树的后序遍历
参数: m_tree 需要遍历的树
返回值: void
*/
/************************************************************************/
void CHeapSort::PostOrder(PHNode m_tree)
{
if (nullptr != m_tree)
{
PostOrder(m_tree->left); //中序遍历左子树
PostOrder(m_tree->right); //中序遍历右子树
std::cout << m_tree->data << " "; //显示数据
}
}
层次遍历树
/************************************************************************/
/*
树的逐层遍历 双指针法
参数: m_tree 需要遍历的树
返回值: void
*/
/************************************************************************/
void CHeapSort::TravelBLevels(PHNode m_tree)
{
std::vector<PHNode> vec; //定义树层次遍历的树结构
vec.push_back(m_tree); //将树的头结点压入向量
unsigned int cur(0); //当前的结点数
unsigned int end(1); //向量的长度 也就是当前向量里面装的树结点的个数
while (cur < vec.size()) //二叉树层次遍历 最后cur的置将等于vec.size()的大小则推出while循环
{
end = vec.size(); //取当前层的节点个数
while (cur < vec.size()) //遍历每一层
{
//std::cout << vec[cur]->data << " " <<
// vec[cur]->pos << " " ; //显示数据
std::cout << vec[cur]->data << " " ; //显示数据
//计算下一层的结点数目 并将其压入向量 最后一层统计为0 则不满足while条件 退出
if (nullptr != vec[cur]->left) //若左孩子不为空将其放入向量中
{
vec.push_back(vec[cur]->left); //压入数据
}
if (nullptr != vec[cur]->right) //若右孩子不为空将其放入向量中
{
vec.push_back(vec[cur]->right); //压入数据
}
cur++; //统计每一层的结点数目 以便作为数组取用
}
//std::cout << "\n"; //每一层的分隔回车
}
}
堆排序算法
二叉树转换为顺序向量
/************************************************************************/
/*
双指针法 把树转换为vector顺序数组
参数: m_tree 需要转换的树
返回值: vector数组
*/
/************************************************************************/
std::vector<PHNode> CHeapSort::BitTree2Array(PHNode m_tree)
{
std::vector<PHNode> vec; //定义树层次遍历的树结构
vec.push_back(m_tree); //将树的头结点压入向量
unsigned int cur(0); //当前的结点数
unsigned int end(1); //向量的长度 也就是当前向量里面装的树结点的个数
while (cur < vec.size()) //二叉树层次遍历 最后cur的置将等于vec.size()的大小则推出while循环
{
end = vec.size(); //取当前层的节点个数
while (cur < vec.size()) //遍历每一层
{
if (nullptr != vec[cur]->left) //若左孩子不为空将其放入向量中
{
vec.push_back(vec[cur]->left); //压入数据
}
if (nullptr != vec[cur]->right) //若右孩子不为空将其放入向量中
{
vec.push_back(vec[cur]->right); //压入数据
}
cur++; //统计每一层的结点数目 以便作为数组取用
}
}
return vec;
}
堆最大化操作
/************************************************************************/
/*
堆最大化
参数: vec 顺序数组化之后的树
参数: i 当前的序号标记
返回值: void
*/
/************************************************************************/
void CHeapSort::Max_Heapify(std::vector<PHNode>& vec, const int i)
{
if ((nullptr!=vec[i]->left) && (nullptr!=vec[i]->right))
{
unsigned int l_pos = vec[i]->left->pos-1; //获取结点i左子树的序列标记
unsigned int r_pos = vec[i]->right->pos-1; //获取结点i右子树的序列标记
unsigned int large(0); //用于存储最大值的序列标记
//获取最大的值的结点序号
if ((l_pos<vec.size()) && vec[l_pos]->data>vec[i]->data)
{
large = l_pos;
}
else
{
large = i;
}
if ((r_pos<vec.size()) && vec[r_pos]->data>vec[large]->data)
{
large = r_pos;
}
//若当前序号为i的数据域值小于序号为large的数据域值 则交换
if (i != large)
{
double temp = vec[i]->data;
vec[i]->data = vec[large]->data;
vec[large]->data = temp;
Max_Heapify(vec, large);
}
}
else if((nullptr!=vec[i]->left) && (nullptr==vec[i]->right))
{
unsigned int l_pos = vec[i]->left->pos-1; //获取结点i左子树的序列标记
unsigned int large(0); //用于存储最大值的序列标记
//获取最大的值的结点序号
if ((l_pos<vec.size()) && vec[l_pos]->data>vec[i]->data)
{
large = l_pos;
}
else
{
large = i;
}
//若当前序号为i的数据域值小于序号为large的数据域值 则交换
if (i != large)
{
double temp = vec[i]->data;
vec[i]->data = vec[large]->data;
vec[large]->data = temp;
Max_Heapify(vec, large);
}
}
}
建立最大化堆
/************************************************************************/
/*
建立最大化堆
参数: m_tree 需要遍历的树
返回值: void
*/
/************************************************************************/
void CHeapSort::Bild_Max_Heapify(std::vector<PHNode>& vec)
{
int loop = static_cast<int>(vec.size()/2);
for (int i=loop; i>=1; i--)
{
Max_Heapify(vec, i-1);
}
}
堆排序算法
/************************************************************************/
/*
堆排序
参数: m_tree 需要堆排序的树
返回值: 排序好的向量
*/
/************************************************************************/
std::vector<datatype> CHeapSort::HEAPSORT(PHNode m_tree)
{
std::vector<PHNode> vec = BitTree2Array(m_tree); //二叉树序列顺序向量化
std::vector<datatype> dst_vec; //目标向量
Bild_Max_Heapify(vec);
for (int i=vec.size(); i>1; i--)
{
dst_vec.push_back(vec[0]->data);
datatype temp = vec[0]->data;
vec[0]->data = vec[i-1]->data;
vec[i-1]->data = temp;
vec.pop_back(); //删除向量最后一个元素 已经将它的值复制给了第一个
Max_Heapify(vec, 0);
}
dst_vec.push_back(vec[0]->data);
return dst_vec;
}