二分搜索树

二分搜索树
1 添加元素

二分搜索树添加元素的思路:
1)判断,若树为空,则创建一个新的节点,直接使用添加的元素初始化;
2)不为空,则比较添加元素与节点元素的大小,然后使用递归左(右)子树;
3)递归终止条件:节点为空,创建新的节点并初始化返回。

	//向以node为根的二分搜索数中插入元素e,递归算法
    //返回插入新节点后二分搜索树的根
    TNode<T> *add(TNode<T> *node,T e) {
        if(node== nullptr) {
            size++;
            return new TNode<T>(e);
        }

        if(node->e>e){
            node->left=add(node->left,e);//递归
        }else if(node->e<e){
            node->right=add(node->right,e);
        }
        return node;
    }

二分搜索树

2 前序遍历

二分搜索树
二分搜索树前序遍历、中序遍历、后序遍历的概念就不在这里讲了,三者的区分就是注意根节点何时遍历。比如前序遍历,就是先遍历根节点,再遍历左右子节点。

这里注意使用递归调用,递归调用的终止条件:节点为空。
递归写法:

//前序遍历以node为根的二分搜索树,递归算法
    void preOrder(TNode<T> *node){
        if(node==nullptr)
            return ;

        std::cout<<node->e;
        preOrder(node->left);
        preOrder(node->right);
    }

非递归写法: 使用栈
1)先将根节点压入栈中,然后取出访问;
2)将左节点、右节点依次压入栈中,然后再将左节点作为根节点;
3)当栈为空时,访问结束。
e(e);
size++;二分搜索树

void preOrderNR(){
        std::stack<Node<T> *> stack;
        stack.push(root);
        while (!stack.empty()) {
            TNode<T> *cur = stack.top();
            std::cout << cur->e << " ";
            stack.pop();
            if (cur->right != nullptr)
                stack.push(cur->right);
            if (cur->left != nullptr)
                stack.push(cur->left);
        }
        std::cout<<std::endl;
    }
3 层序遍历

层序遍历又称为广度优先遍历。层序遍历通常使用非递归方式实现,需要借助队列实现。每次将待遍历的元素存入队列中,再将它的左右子节点排入队列。
二分搜索树

//层序遍历
void levelOrder(){
	std::queue<TNode<T> *> *q=new std::queue<TNode<T> *>();
    q->push(root);
    while (!q->empty()){//队列不为空
		TNode<T> *cur=q->front();
        q->pop();
        std::cout<<cur->e<<" ";
        if(cur->left!= nullptr){
        	q->push(cur->left);//左子节点排入队列中
        }
        if(cur->right!= nullptr){
            q->push(cur->right);//右子节点排入队列中
        }
        std::cout<<std::endl;
    }
}
4 删除元素

1)删除最大元素和最小元素
最小元素,只需要不断遍历树的左子节点,走到底就是最小元素。最大元素就是向右走。

TNode<T> *removeMin(TNode<T> *node){
	if(node->left==nullptr){//向左走,寻找最小元素
		//保存最小元素节点的右子节点
		TNode<T> *rightNode=node->right;
        delete node;//删除最小元素节点
        size--;
        return rightNode;//返回保存的节点
    }
    node->left=removeMin(node->left);
    return node;
}

二分搜索树2)删除仍意元素(Hibbard Deletion)
二分搜索树
二分搜索树
二分搜索树

分别判断节点的情况:
第一,删除只有左孩子的节点;
第二,删除只有右孩子的节点;
第三,删除左右都有孩子的节点。(选择该节点的右子树中最小的值代替该节点)

TNode<T> *remove(TNode<T> *node,T e){
        if(node==nullptr)
            return nullptr;
        if(node->e>e){
            node->left=remove(node->left,e);
            return node;
        }else if(node->e<e){
            node->right=remove(node->right,e);
            return node;
        }
        else{
            if(node->left== nullptr){//左子树为空
                TNode<T> *rightNode=node->right;
                delete node;
                size--;
                return rightNode;
            }
            if(node->right== nullptr){//右子树为空
                TNode<T> *leftNode=node->left;
                delete node;
                size--;
                return leftNode;
            }

            TNode<T> *successor=min(node->right);//获取该节点右子树的最小值
            successor->right=removeMin(node->right);
            successor->left=node->left;

            node->left=node->right= nullptr;
            return successor;
        }
    }
上一篇:二叉搜索树插入


下一篇:数据结构----数