任务:使用C++语言,通过数组的形式来实现一颗平衡二叉树,包括树的创建,添加结点,查找结点,删除结点等功能。
main.cpp 代码如下:
#include "CompleteBinaryTree.h"
int main()
{
CompleteBinaryTree<char> tree;
for (int i = 0; i < 10; i++)
{
tree.Add('A' + i);
}
cout << "先序遍历:";
tree.PreTravel();
cout << endl;
cout << "A的父结点为:";
cout << tree.FindParent('A') << endl << endl;
cout << "E的父结点为:";
cout << tree.FindParent('E') << endl << endl;
cout << "B的右孩子为:";
cout << tree.FindRightChild('B') << endl << endl;
cout << "D的左孩子为:";
cout << tree.FindLeftChild('D') << endl << endl;
cout << "F的左孩子为:";
cout << tree.FindLeftChild('F') << endl << endl;
cout << "K的左孩子为:";
cout << tree.FindLeftChild('K') << endl << endl;
tree.Delete('D');
cout << "先序遍历:";
tree.PreTravel();
while (1);
return 0;
}
CompleteBinaryTree.h 代码如下:
#pragma once
#include <iostream>
using namespace std;
template<class T>
class CompleteBinaryTree
{
T* pRoot;
int num;
public:
//构造函数与析构函数
CompleteBinaryTree();
~CompleteBinaryTree();
//在二叉树尾部添加结点
void Add(const T& data);
//查找结点的父结点
T FindParent(const T& data);
//查找结点的左孩子积点
T FindLeftChild(const T& data);
//查找结点的右孩子结点
T FindRightChild(const T& data);
//删除结点
void Delete(const T& data);
public:
//先序遍历
void PreTravel();
private:
//先序遍历,递归用
void _pretravel(int index);
//获取结点编号
int _getindex(const T& data);
};
//构造函数和析构函数
template<class T>
CompleteBinaryTree<T>::CompleteBinaryTree()
{
pRoot = NULL;
num = 0;
}
template<class T>
CompleteBinaryTree<T>::~CompleteBinaryTree()
{
if (pRoot)
{
delete[] pRoot;
}
}
//在二叉树尾部添加结点
template<class T>
void CompleteBinaryTree<T>::Add(const T& data)
{
//新开内存
T* pTemp = new T[num + 1];
//如果当前树不为空,将当前树中的结点拷贝至新开内存中,并且释放当前pRoot内存段
if (pRoot)
{
memcpy(pTemp, pRoot, sizeof(T) * num);
delete[] pRoot;
}
//pRoot指向新内存段,且将新增结点数据赋值给内存段的末尾,完成添加
pRoot = pTemp;
pRoot[num++] = data;
}
//查找结点的父结点
template<class T>
T CompleteBinaryTree<T>::FindParent(const T& data)
{
int index = _getindex(data);
if (index < 0)
{
cout << "ERROR:没有找到该结点 ";
return NULL;
}
//如果结点为根结点,则没有父结点
if (index == 0)
{
cout << "该结点为根结点";
return NULL;
}
//根据完整二叉树的性质,如果将二叉树从上至下,从左至右依次保存入一个数组中
//已知结点的下标为index,则其父结点的下标为 (index - 1) / 2
return pRoot[(index - 1) / 2];
}
//查找结点的左孩子结点
template<class T>
T CompleteBinaryTree<T>::FindLeftChild(const T& data)
{
int index = _getindex(data);
if (index < 0)
{
cout << "ERROR:没有找到该结点 ";
return NULL;
}
//根据完整二叉树的性质,如果将二叉树从上至下,从左至右依次保存入一个数组中
//已知结点的下标为index,则其左孩子结点的下标为 index * 2 + 1
index = index * 2 + 1;
if (index < num)
{
return pRoot[index];
}
cout << "该结点没有左孩子";
return NULL;
}
//查找结点的右孩子结点
template<class T>
T CompleteBinaryTree<T>::FindRightChild(const T& data)
{
int index = _getindex(data);
if (index < 0)
{
cout << "ERROR:没有找到该结点 ";
return NULL;
}
//根据完整二叉树的性质,如果将二叉树从上至下,从左至右依次保存入一个数组中
//已知结点的下标为index,则其左孩子结点的下标为 index * 2 + 2
index = index * 2 + 2;
if (index < num)
{
return pRoot[index];
}
cout << "该结点没有右孩子";
return NULL;
}
//删除结点
template<class T>
void CompleteBinaryTree<T>::Delete(const T& data)
{
int index = _getindex(data);
if (index < 0)
{
cout << "ERROR:没有找到该结点 ";
return;
}
//开劈新内存
T* pNew = new T[num - 1];
//将原树中的数据(除被删除的结点外)拷贝至新内存中
memcpy(pNew, pRoot, sizeof(T) * index);
if (index < num)
{
memcpy(pNew + index, pRoot + index + 1, sizeof(T) * (num - index - 1));
}
//释放原内存,将pRoot指向新内存空间
delete[] pRoot;
pRoot = pNew;
num--;
cout << "删除成功:" << data << endl;
}
//先序遍历
template<class T>
void CompleteBinaryTree<T>::PreTravel()
{
if (num <= 0)
{
cout << "ERROR:当前树为空!" << endl;
}
_pretravel(0);
cout << endl;
}
//先序遍历,递归用
template<class T>
void CompleteBinaryTree<T>::_pretravel(int index)
{
if (index >= num) return;
//先遍历父结点,后依次遍历左右孩子结点
cout << pRoot[index] << " ";
//根据完整二叉树的性质,如果将二叉树从上至下,从左至右依次保存入一个数组中
//已知父结点的下标为index,则其左孩子结点下标为index*2+1,右孩子结点下标为index*2+2
_pretravel(index * 2 + 1);
_pretravel(index * 2 + 2);
}
//获取结点编号
template<class T>
int CompleteBinaryTree<T>::_getindex(const T& data)
{
if (pRoot == NULL)
return -1;
int index = 0;
while (index<num)
{
if (pRoot[index++] == data)
{
return (index - 1);
}
}
return -1;
}
程序运行结果如下图: