树的实现

二叉排序树:

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

template <class T> class BinaryTree;

template <class T>
class Node {
public:
    Node() {};
    Node(T num) {
        data = num;
        lchild = NULL;
        rchild = NULL;
    }
    friend class BinaryTree<T>;
private:
    T data;
    Node<T>* lchild;
    Node<T>* rchild;
};

template <class T>
class BinaryTree {
public:
    BinaryTree() {
        root = NULL;
    }
    void Insert(T num);
    void PreOrder(Node<T>* r);//前序遍历
    void InOrder(Node<T>* r);//中序遍历
    void PostOrder(Node<T>* r);//后序遍历
    void LevelOrder();//层次遍历
//private:
    Node<T>* root;
};

template <class T>
void BinaryTree<T>::Insert(T num) {
    Node<T>* pnew = new Node<T>(num);
    Node<T>* p = root;
    if (!p) {
        root = pnew; 
    }
    else {
        while (p) {
            Node<T>* pre = p;
            if (num < p->data) {
                p = p->lchild;
                if (!p) {
                    pre->lchild = pnew;
                }
            }
            else if(num > p->data)
            {
                p = p->rchild;
                if (!p) {
                    pre->rchild = pnew;
                }
            }
        }
    }
}

template <class T>
void BinaryTree<T>::PreOrder(Node<T> *r) {

    if (r) {
        cout << r->data;
        PreOrder(r->lchild);
        PreOrder(r->rchild);
    }
}
template <class T>
void BinaryTree<T>::InOrder(Node<T>* r) {
    if (r) {
        InOrder(r->lchild);
        cout << r->data;
        InOrder(r->rchild);
    }
}
    
template <class T>
void BinaryTree<T>::PostOrder(Node<T>* r)
{
    if (r) {
        PostOrder(r->lchild);
        PostOrder(r->rchild);
        cout << r->data;
    }
}

template <class T>
void BinaryTree<T>::LevelOrder(){
    queue<Node<T>*> q;
    Node<T>* p = root;
    q.push(p);
    while (!q.empty()) {
        p = q.front();
        if (p->lchild) {
            q.push(p->lchild);
        }
        if (p->rchild) {
            q.push(p->rchild);
        }
        cout << q.front()->data ;
        q.pop();
    }
}

int main()
{
    BinaryTree<char> tree;
    char table[] = { 'E','C','B','A','D','J','H','G','F','I' };
    for (int i = 0; i < 10; i++) {
        tree.Insert(table[i]);
    }
    tree.PreOrder(tree.root); cout << endl;
    tree.InOrder(tree.root); cout << endl;
    tree.PostOrder(tree.root); cout << endl;
    tree.LevelOrder();
    return 0;
}

上面没有写删除函数,所以贴上以前写的删除函数。
删除节点要分好几种情况:


删除一个结点原理图.png

代码:

bool Tree::Delete(int num)
{
    Node *p = this->root;//指向要删除的结点
    Node *prev = this->root;//指向要删除结点的根结点
    
    while(p)//找到要删除的结点
    {
        if( num  > p->data )
        {
            prev = p;
            p = p->rchild;
        }else if( num < p->data )
        {
            prev = p;
            p = p->lchild;
        }else
        {
            break;
        }
    }
    if( p == NULL )//如果没找到要删除的结点,则返回错误
    {
        return false;
    }
    
    if( p->lchild == NULL && p->rchild == NULL )//如果p没有孩子
    {
        if( p == prev->lchild )//p在根的左边
        {
            prev->lchild = NULL;
            free(p);
            
        }else if( p == prev->rchild )//p在根的右边
        {
            prev->rchild = NULL;
            free(p);
        }else if( p == this->root  )//p是根结点
            this->root = NULL;
    }else if( p->lchild != NULL && p->rchild != NULL )//如果p有两个孩子
    {
        Node *p2 = p->lchild;//指向左子树最大的结点
        Node *prev2 = p;//指向p2的根结点
        while(p2)//找p左子树最大的结点
        {
            if( p2->rchild == NULL )
            {
                break;
            }else
            {
                prev2 = p2;
                p2 = p2->rchild;
            }
        }
        if( p2 == p->lchild )//如果左子树最大的结点是p的左孩子
        {
            int num = p2->data;
            p2->data = p->data;
            p->data = num;
            
            p->lchild = p2->lchild;
            p2->lchild = NULL;
            free(p2);
        }else//左子树最大的结点是p的左孩子的右子树最大结点
        {
            int num = p->data;
            p->data = p2->data;
            p2->data = num;
            
            prev2->rchild = p2->lchild;
            p2->lchild = NULL;
            free(p2);
        }
    }else//如果p只有一个孩子
    {
        if( p == this->root )//如果p是根结点
        {
            if( p->lchild != NULL )//p没有右孩子 只有左孩子
            {
                Node *psave = p->lchild;
                p->lchild = NULL;
                free(p);
                this->root = psave;
            }else if( p->rchild != NULL )//p没有左孩子 只有右孩子
            {
                Node *psave = p->rchild;
                p->rchild = NULL;
                free(p);
                this->root = psave;
            }
        }else if( p == prev->lchild )//如果p是某个根的左孩子
        {
            if( p->rchild == NULL )//p只有左孩子,没有右孩子
            {
                prev->lchild = p->lchild;
                p->lchild = NULL;
                free(p);
            }else//p只有右孩子,没有左孩子
            {
                prev->lchild = p->rchild;
                p->rchild = NULL;
                free(p);
            }
        }else if( p == prev->rchild )//如果p是某个根的右孩子
        {
            if( p->lchild == NULL )//p只有右孩子,没有左孩子
            {
                prev->rchild = p->rchild;
                p->rchild = NULL;
                free(p);
            }else//p只有左孩子,没有右孩子
            {
                prev->rchild = p->lchild;
                p->lchild = NULL;
                free(p);
            }
        }
    }
    return true;
}

非递归的先序遍历:
利用了栈,先存根结点,然后根结点出栈的同时,先存根结点的右子节点,再存左子节点;然后在出栈,再依次存出栈元素的右、左子节点。。。。。

void Tree::fpreorder()
{
    stack<Node *> b;
    Node *p = this->root;
    Node *num=NULL;
    b.push(p);
    while( !b.empty() )
    {
        p = b.top();
        num = b.top();
        b.pop();
        cout<<num->data<<" ";
        if( p->rchild )
        {
            b.push(p->rchild);    
        }
        if( p->lchild )
        {
            b.push(p->lchild);
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容