二叉树的链接实现及基本操作(C++)

本文介绍了二叉树的概念,包括满二叉树和完全二叉树的定义,以及二叉树的常用性质。重点讲解了二叉树的C++实现,包括构建和遍历二叉树的代码,并提供了判断是否为完全二叉树的方法。

前言

学习了栈和队列后,我们接着在数据结构的海洋中遨游。这时的我已经被各种栈和队列折腾的快不行了,然而,当学习了树之后,才发现自己还是太年轻,跟树比起来,栈和队列是那么的和谐与友好。先来小试牛刀一把,看看最简单的二叉树是怎么实现的:

二叉树的实现

二叉树是节点的有限集合,他或者为空,或者有一个根节点及两颗互不相交的左右子树构成,而左右子树有都是二叉树。写到这里,是不是已经体会到了一点二叉树与递归的暧昧关系。

若一棵树的任意一层节点数都达到了最大值,则这棵二叉树称为满二叉树。

而如果将满二叉树自右向左依次删掉几个节点(注意不要跳过节点),那样的树就是完全二叉树。

FullBT CompleteBT.jpg

二叉树的常用性质

1. 一棵非空二叉树的第i层上最多有2^{i-1}个节点(i>=1)。

2. 一棵高度为k的二叉树,最多有2^{k} - 1个节点。

3. 对于一棵非空二叉树,如果叶子节点数为a,度为2的节点数为吧b,则a = b + 1。

4. 具有n个节点的完全二叉树的高度为k = [log2(n)] + 1。(其中[ ]指不比里面数大的最大整数)

说了这么多,下面就来看看具体的C++实现:

#include <iostream>

using namespace std;

//父类

template<class elemType>
class queue {
public:
    virtual bool isEmpty() = 0;
    virtual void enQueue(const elemType &x) = 0;
    virtual elemType deQueue() = 0;
    virtual elemType getHead() = 0;
    virtual ~queue(){};
};

template<class elemType>
class linkQueue: public queue<elemType>
{
private:
    struct node{
        elemType data;
        node *next;
        node(const elemType &x, node *N = NULL){
            data = x;
            next = N;
        }
        node():next(NULL){}
        ~node(){}
    };
    
    node *front , *rear;
    
public:
    linkQueue(){
        front = rear = NULL;
        
    }
    ~linkQueue(){
        node *tmp;
        while(front != NULL){
            tmp = front;
            front = front -> next;
            delete tmp;
        }
    }
    bool isEmpty(){
        return front == NULL;
    }
    
    void enQueue(const elemType &x){
        if(rear == NULL){
            front = rear = new node(x);
        }
        else{
            rear -> next = new node(x);
            rear = rear -> next;
        }
    }
    
    elemType deQueue(){
        node *tmp = front;
        elemType value = front -> data;
        front = front -> next;
        if(front == NULL){
            rear = NULL;
        }
        delete tmp;
        return value;
    }
    
    elemType getHead()
    {
        return front-> data;
    }
    
    
};




//子类
template<class T>

class bTree{
public:
    virtual void clear() = 0;
    virtual bool isEmpty()const = 0;
    virtual T Root(T flag)const = 0;
    virtual T parent(T x, T flag)const =0;
    virtual T lchild(T x, T flag)const = 0;
    virtual T rchild(T x, T flag)const = 0;
    virtual void delLeft(T x) = 0;
    virtual void delRight(T x) = 0;
    virtual void preOrder() const = 0;
    virtual void midOrder() const = 0;
    virtual void postOrder() const = 0;
    virtual void levelOrder() const = 0;
    
};

template<class T>
class binaryTree:public bTree<T>{
    friend void printTree(const binaryTree &t, T flag);
private:
    struct Node{
        Node *left, *right, *parent;
        T data;
        
        Node():left(NULL), right(NULL), parent(NULL){}
        Node(T item, Node *L = NULL, Node *R = NULL):data(item), left(L), right(R){}
        ~Node(){};
    };
    
    Node *root;
public:
    binaryTree():root(NULL){}
    
    binaryTree(T x){
        root = new Node(x);
    }
    
    ~binaryTree(){
        clear(root);
    }
    
    void clear(Node *t){
        if(t == NULL){
            return;
        }
        clear(t -> left);
        clear(t -> right);
        delete t;
        t = NULL;
    }
    
    void clear(){
        clear(root);
    }
    
    bool isEmpty()const{
        return root == NULL;
    }
    
    T Root(T flag)const{
        if(root == NULL){
            return flag;
        }
        else{
            return root->data;
        }
    }
    
    Node *find(T x, Node *t)const{
        Node *tmp;
        if(t == NULL){
            return t;
            
        }
        if(t -> data == x){
            return t;
        }
        if(tmp = find(x, t -> left)){
            return tmp;
        }
        else{
            return (find(x, t -> right));
        }
    }
    
    T lparent(T x, T flag)const{
        
    }
    
    T lchild(T x, T flag)const{
        Node *tmp = find(x,  root);
        if(tmp == NULL || tmp -> left == NULL){
            return flag;
        }
        return tmp -> left -> data;
        
    }
    
    T rchild(T x, T flag)const{
        Node *tmp = find(x, root);
        if(tmp == NULL || tmp -> right == NULL){
            return flag;
        }
        return tmp -> right -> data;
    }
    

    
    void delLeft(T x){
        Node *tmp = find(x, root);
        if(tmp == NULL){
            return;
        }
        clear(tmp -> left);
        
    }
    
    void delRight(T x){
        Node *tmp = find(x, root);
        if(tmp == NULL){
            return;
        }
        clear(tmp -> right);
    }
    
    //preorder traverse
    void preOrder(Node *t)const{
        if(t == NULL){
            return;
        }
        cout << t -> data << ' ';
        preOrder(t -> left);
        preOrder(t -> right);
    }
    void preOrder()const{
        preOrder(root);
    }
    
    //midorder traverse
    void midOrder(Node *t)const{
        if(t == NULL){
            return;
        }
        midOrder(t -> left);
        cout << t -> data << ' ';
        midOrder(t -> right);
    }
    void midOrder()const{
        midOrder(root);
    }
    
    //postorder traverse
    void postOrder(Node *t) const{
        if(t == NULL){
            return;
        }
        postOrder(t -> left);
        postOrder(t -> right);
        cout << t -> data << ' ';
    }
    
    void postOrder()const{
        postOrder(root);
    }
    
    //levelorder traverse
    void levelOrder()const{
        linkQueue<Node *>que;
        Node *tmp;
        
        que.enQueue(root);
        while(!que.isEmpty()){
            tmp = que.deQueue();
            cout << tmp -> data << ' ';
            if(tmp -> left){
                que.enQueue(tmp -> left);
            }
            if(tmp -> right){
                que.enQueue(tmp -> right);
            }
            
        }
        
    }
    
    //creat a binary tree
    void creatTree(T flag){
        linkQueue<Node *>que;
        Node *tmp;
        T x, ldata, rdata;
        cout << "Please input the root:";
        cin >> x;
        root = new Node(x);
        que.enQueue(root);
        
        while(!que.isEmpty()){
            tmp = que.deQueue();
            cout << "Input the left node and right node:";
            cin >> ldata >> rdata;
            if(!ldata != flag){
                que.enQueue(tmp -> left == new Node(ldata));
            }
            if(!rdata != flag){
                que.enQueue(tmp -> left == new Node(rdata));
            }
        }
        
    }
    
    T parent(T x, T flag)const{
        return flag;
    }
    
    //Judge if it is a complete binary tree
    void isCBT(){

        linkQueue<Node *> que;
        int lastId = 1, nodeCount = 1;
        root -> data = 1;
        Node *tmpNode, *son;
        if(root == NULL){
            cout << 'Y';
            return;
        }

        que.enQueue(root);
        while(!que.isEmpty()){
            tmpNode = que.deQueue();
            if(tmpNode -> left != NULL){
                nodeCount = nodeCount + 1;
                son = tmpNode -> left;
                son -> data = (tmpNode -> data) * 2;
                lastId = son -> data;
                que.enQueue(son);
                
            }
            if(tmpNode -> right != NULL){
                nodeCount = nodeCount + 1;
                son = tmpNode -> right;
                son -> data = (tmpNode -> data) * 2 + 1;
                lastId = son -> data;
                que.enQueue(son);
                
            }
        }
        if(nodeCount == lastId){
            cout << 'Y';
        }
        else{
            cout << 'N';
        }
        
    }

};

总结

本节内容主要是介绍了树的基本概念以及二叉树的定义、特性和实现代码,包括构建树,四种遍历树的操作,以及判断数是否为完全二叉树的方法,如果你已经觉得树如此复杂,那只能说“小朋友,这才是冰山一角中的一角”,想看看冰山的真面目,就鼓足干劲接着学习吧。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值