用C++实现一个二叉树类

我以为自己复习得差不多了,但是从昨天的笔试看来,基础真的很不扎实. 一个二叉树类也写不出来,即使是今天,也要调试半天.

/*
* 昨天参加宜搜的笔试,要求用C++写一二叉树类,实现插入,删除,定位功能,辗转再三,
* 却无从下手,甚急,终基础不好,今天再想,通过层次遍历二叉树,再进行实现相关功能
* 实也不难. 以下代码
*/

/*
* FileName:BTree.cpp
* Description:binary tree with insert, delete, find
* Date:2007-11-4
*/


#include
< iostream >
#include
< deque >
using   namespace  std;

// binary node with parent node
template < typename T >
class  node
{
public:
    node(
const T &v, node<T> *L=NULL, node<T> *R=NULL, node<T> *P=NULL):left(L),right(R),par(P)
    
{
        value 
= v;
    }


public:
    T value;
    node
<T> *left, *right, *par;
}
;

//  binary tree
template < typename T >
class  BTree
{
public:
    BTree(node
<T> *R=NULL):root(R)
    
{ }
    
~BTree()
    

        
if(root)
            delall();
    }


    node
<T> *findby(const T &v);    // 层次遍历,返回找到第一个结点值为v的结点指针
    void Insert(const T &v);        // 层次遍历二叉树,将值插在遇到的第一个叶子或者子树不全的结点上
    bool delby(const T &v);            // 层次遍历二叉树,删除遇到的第一个结点值为v的结点
    
    node
<T> *findleave(node<T> *cur); // 层次遍历二叉树,返回cur下遇到的第一个叶子结点
    void delall();
    
void display(node<T> *r);        // 先序遍历,打印二叉树各结点的值

public:
    node
<T> *root;
}
;

template
< typename T >
node
< T >   * BTree < T > ::findby( const  T  & v)
{
    deque
< node<T>* > Q;
    
bool isfind; // find v ==> isfind = true; not find ==> isfind = false
    node<T> *tmp;

    
if(root)
        Q.push_back(root);
    
else
    
{
        
return NULL;
    }


    isfind 
= false;
    tmp 
= NULL;
    
while(!Q.empty() && !isfind)
    
{
        tmp 
= Q.front();
        Q.pop_front();

        
if(tmp->value == v)
            isfind 
= true;
        
else
        
{
            
if(tmp->left)
                Q.push_back(tmp
->left);
            
if(tmp->right)
                Q.push_back(tmp
->right);
        }

    }

    
    
if(!isfind)
        tmp 
= NULL;

    
return tmp;
}


template
< typename T >
void  BTree < T > ::Insert( const  T  & v)
{
    deque
< node<T>* > Q;
    node
<T> *cur;

    
if(root)
        Q.push_back(root);
    
else
    
{
        root 
= new node<T>(v, NULL, NULL, NULL);
        
return;
    }


    
while(!Q.empty()) // 原来是这里出错了.第一次是写了Q.empty(),应该是!Q.empty()
    {
        cur 
= Q.front();
        Q.pop_front();

        
if(cur->left)
            Q.push_back(cur
->left);
        
else
        
{
            cur
->left = new node<T>(v, NULL, NULL, cur);
            
return;
        }

        
        
if(cur->right)
            Q.push_back(cur
->right);
        
else
        
{
            cur
->right = new node<T>(v, NULL, NULL, cur);
            
return;
        }

    }

}


template
< typename T >
bool  BTree < T > ::delby( const  T  & v)
{
    node
<T> *cur, *tmp;
    
bool isleave; // 判断是不是叶子结点
    
    isleave 
= false;
    cur 
= NULL;
    cur 
= findby(v);
    
if(!cur) // 说明不存在结点值为v的结点
        return false;
    
else
    
{
        
if(cur->left && cur->right) // 左右子树不为空
        {
            tmp 
= findleave(cur); // 通过层次遍历,找出cur下第一个叶子结点
            tmp->left = cur->left;
            tmp
->right = cur->right;
            
            
// 改变左右子树的父结点,不过要判断cur是否为根结点
            if(cur->left)
                cur
->left->par = tmp;
            
if(cur->right)
                cur
->right->par = tmp;
        }

        
else if(cur->left) // 右子树为空
            tmp = cur->left;
        
else if(cur->right) // 左子树为空
            tmp = cur->right;
        
else // 左右子树皆为空,说明要删除的是叶子结点
        {
            (cur 
== cur->par->left) ? (cur->par->left = NULL) :(cur->par->right = NULL);
            isleave 
= true;
        }


        
if(!isleave)
        
{
            tmp
->par = cur->par;

            
if(cur->par)
                (cur 
== cur->par->left) ? (cur->par->left = tmp) :(cur->par->right = tmp);
            
            
if(root == cur)
            
{
                root 
= tmp;
                root
->par = NULL;
            }

        }

    }


    delete cur;

    
return true;
}


//  层次遍历二叉树,返回遇到的第一个叶子.二叉树的叶子特征:左右子树为NULL
template < typename T >
node
< T >   * BTree < T > ::findleave(node < T >   * cur)
{
    deque
< node<T>* > Q;    // 用于层次遍历的双端队列
    node<T> *tmp;            // 返回的叶子指针
    bool isfind;            // 用来跳出while循环的flag

    
if(!cur)                // 假如cur为空,则返回NULL
        return NULL;
    
else
        Q.push_back(cur);    
// 推进Q中

    isfind 
= false;            
    
while(!Q.empty() && !isfind)    // 当队列为空或者找到叶子时终止循环
    {
        tmp 
= Q.front();
        Q.pop_front();

        
if(!tmp->left && !tmp->right)
            isfind 
= true;
        
else if(tmp->left)
            Q.push_back(tmp
->left);
        
else
            Q.push_back(tmp
->right);
    }


    
// 处理该叶子的父结点
    if(tmp->par)
        (tmp 
== tmp->par->left) ? (tmp->par->left = NULL) : (tmp->par->right = NULL);

    
return tmp;
}


//  通过层次遍历删除二叉树所有结点
template < typename T >
void  BTree < T > ::delall()
{
    deque
< node<T>* > Q;

    
// 假如root为空,则直接返回,不为空,则推进Q中
    if(root)
        Q.push_back(root);
    
else
        
return ;

    
while(!Q.empty())
    
{
        root 
= Q.front();
        Q.pop_front();

        
if(root->left)
            Q.push_back(root
->left);
        
if(root->right)
            Q.push_back(root
->right);

        delete root;
        root 
= NULL;
    }

}


//  通过前序遍历打印二叉树各结点的值
template < typename T >
void  BTree < T > ::display(node < T >   * r)
{
    
if(r)
    
{
        cout 
<< r->value << ' ';
        display(r
->left);
        display(r
->right);
    }

}


int  main( void )
{
    BTree
<int> BT;
    
int a[] = 123456789 };

    
for(int it = 0; it < sizeof(a) / sizeof(a[0]); it++)
        BT.Insert(a[it]); 
// 第一次测试,Insert不成功,Insert 已修正

    BT.display(BT.root);
    cout 
<< endl;

    BT.delby(
1);
    BT.delby(
3);
    BT.delby(
6);
    BT.delby(
2);
    BT.delby(
8);
    
    BT.display(BT.root);
    cout 
<< endl;

    BT.delall();
    BT.display(BT.root);

    
return 0;
}

//  第二次测试 ,测试delby(),
//  A,定义delby时忘记写类名了
//  B,删除不成功,是findby,findleave的whie循环条件判断那里出错了
//  C,出了很问题,没处理好这种情况,删除的结点如果是根结点
首先,需要定义一个二叉树的节点结构体,包括左子树、右子树和节点数据。例如: ``` typedef struct TreeNode { int data; struct TreeNode *left; struct TreeNode *right; }TreeNode; ``` 然后,需要实现以下几个函数: 1. 创建新节点 ``` TreeNode* createTreeNode(int data) { TreeNode *newNode = (TreeNode*)malloc(sizeof(TreeNode)); newNode->data = data; newNode->left = NULL; newNode->right = NULL; return newNode; } ``` 2. 插入节点 ``` TreeNode* insertTreeNode(TreeNode* root, int data) { if(root == NULL) { return createTreeNode(data); } if(data < root->data) { root->left = insertTreeNode(root->left, data); } else { root->right = insertTreeNode(root->right, data); } return root; } ``` 3. 查找节点 ``` TreeNode* findTreeNode(TreeNode* root, int data) { if(root == NULL) { return NULL; } if(data == root->data) { return root; } else if(data < root->data) { return findTreeNode(root->left, data); } else { return findTreeNode(root->right, data); } } ``` 4. 删除节点 ``` TreeNode* deleteTreeNode(TreeNode* root, int data) { if(root == NULL) { return NULL; } if(data < root->data) { root->left = deleteTreeNode(root->left, data); return root; } if(data > root->data) { root->right = deleteTreeNode(root->right, data); return root; } if(root->left == NULL && root->right == NULL) { free(root); return NULL; } if(root->left == NULL) { TreeNode* rightChild = root->right; free(root); return rightChild; } if(root->right == NULL) { TreeNode* leftChild = root->left; free(root); return leftChild; } TreeNode* successor = root->right; while(successor->left != NULL) { successor = successor->left; } root->data = successor->data; root->right = deleteTreeNode(root->right, successor->data); return root; } ``` 5. 遍历节点 ``` void inorderTraversal(TreeNode* root) { if(root != NULL) { inorderTraversal(root->left); printf("%d ", root->data); inorderTraversal(root->right); } } void preorderTraversal(TreeNode* root) { if(root != NULL) { printf("%d ", root->data); preorderTraversal(root->left); preorderTraversal(root->right); } } void postorderTraversal(TreeNode* root) { if(root != NULL) { postorderTraversal(root->left); postorderTraversal(root->right); printf("%d ", root->data); } } ``` 以上是实现一个二叉树的基本步骤,在实际使用中可能还需要增删改查等操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值