数据结构与算法:利用数组实现完全二叉树(C++)

任务:使用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;
}

程序运行结果如下图:

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值