数据结构(6) -- 构建二叉搜索树

//BinTree.h
#ifndef BINTREE_H_
#define BINTREE_H_
#define ElemType int
typedef struct _PNode
{
    ElemType data;
    _PNode *left;
    _PNode *right;
}PNode;

class BinTree
{
private:
    PNode *root;
public:
    BinTree();
    ~BinTree();
    PNode* GetRoot();    //获得根节点
    void SetRoot(PNode *p) { root = p; }    //设置根节点
    PNode* Find(ElemType x , PNode *p);        //查找元素x所在位置
    PNode* FindMin(PNode *p);    //查找二叉搜索树的最小值
    PNode* FindMax(PNode *p);    //查找二叉搜索树的最大值
    PNode* Insert(ElemType x, PNode *p);  //构建二叉搜索树,所插入的元素按二叉搜索树排列
    PNode* Delete(ElemType x, PNode *p);  //删除二叉搜索树的元素
    //遍历二叉树
    void PreOrder(PNode *p);  //先序遍历
    void CenOrder(PNode *p);  //中序遍历
    void Trave(PNode *p);     //层次遍历
};
#endif

/////////////////////////////////////////////////////////////////////
//BinTree.cpp
#include "BinTree.h"
#include <iostream>
#include <queue>

BinTree::BinTree()
{
    root = NULL;
}

BinTree::~BinTree(){}

PNode* BinTree::GetRoot()
{
    return root;
}
PNode* BinTree::Find(ElemType x, PNode *p)
{
    /*
    //尾递归实现
    if (p == NULL)
        return NULL;
    if (x > p->data)
        return Find(x, p->right);
    else if (x < p->data)
        return Find(x, p->left);
    else
        return p;*/
    while (p != NULL)
    {
        if (x > p->data)
            p = p->right;
        else if (x < p->data)
            p = p->left;
        else
            return p;
    }
    return NULL;
}

PNode* BinTree::FindMin(PNode *p)
{
    //递归查找
    if (p == NULL)
        return NULL;
    else if (p->left == NULL)
        return p;
    else
        return FindMin(p->left);
}

PNode* BinTree::FindMax(PNode *p)
{
    if (p != NULL)
        while (p->right != NULL)
            p = p->right;
    return p;
}

//遍历二叉树
void BinTree::PreOrder(PNode *p)
{
    if (p == NULL)
        return;
    std::cout << p->data << " ";
    PreOrder(p->left);
    PreOrder(p->right);
}

void BinTree::CenOrder(PNode *p)
{
    if (p == NULL)
        return;
    CenOrder(p->left);
    std::cout << p->data << " ";
    CenOrder(p->right);
}

PNode* BinTree::Insert(ElemType x, PNode *p)
{
    if (p == NULL)
    {
        p = new PNode();
        p->data = x;
        p->left = p->right = NULL;
    }
    else
    {
        if (x < p->data)
            p->left = Insert(x, p->left);
        else if (x > p->data)
            p->right = Insert(x, p->right);
    }
    return p;
}

PNode* BinTree::Delete(ElemType x, PNode *p)
{
    PNode *tmp;
    if (p == NULL)
        std::cout << "要删除的元素未找到" << std::endl;
    else if (x < p->data)  //查找要删除的节点
        p->left = Delete(x, p->left);
    else if (x > p->data)
        p->right = Delete(x, p->right);
    else
    {
        //删除的元素左右节点都在,删除右子树的最小节点
        if (p->left != NULL && p->right != NULL)
        {
            tmp = FindMin(p->right);  //查找右子树的最小节点
            p->data = tmp->data;          //将右字数的最小值与当前节点的值互换
            p->right = Delete(p->data, p->right);    //删除右字数最小节点
        }
        else
        {//删除的元素只有左节点,或只有右节点,或是叶子节点
            tmp = p;
            if (p->left == NULL)  //只有右节点,直接用右节点替换要删除节点
                p = p->right;
            else if(p->right == NULL) //只有左节点,直接用左节点替换要删除节点
                p = p->left;
            delete tmp;    //如果删除节点是叶子节点,直接删除当前节点
        }
    }
    return p;
}

void BinTree::Trave(PNode *p)    //层次遍历
{
    std::queue<PNode*> q;
    q.push(p);
    while (!q.empty())
    {
        PNode *s = q.front();
        std::cout << s->data << " ";
        if (s->left != NULL)
            q.push(s->left);
        if (s->right != NULL)
            q.push(s->right);
        q.pop();
    }
}

////////////////////////////////////////////////////////
//测试
#include <iostream>
#include "BinTree.h"
using namespace std;

int main()
{
    BinTree bt;
    //构造二分查找树
    bt.SetRoot(bt.Insert(4, bt.GetRoot())); //注意跟新根节点
    bt.SetRoot(bt.Insert(3, bt.GetRoot()));
    bt.SetRoot(bt.Insert(5, bt.GetRoot()));
    bt.SetRoot(bt.Insert(6, bt.GetRoot()));
    bt.SetRoot(bt.Insert(7, bt.GetRoot()));
    bt.SetRoot(bt.Insert(8, bt.GetRoot()));
    cout << "先序遍历: " << endl;
    bt.PreOrder(bt.GetRoot());
    cout << endl;
    cout << "中序遍历: " << endl;
    bt.CenOrder(bt.GetRoot());
    cout << endl;
    cout << "层次遍历:" << endl;
     bt.Trave(bt.GetRoot());
    cout << endl;
    cout << "最小值:" << bt.FindMin(bt.GetRoot())->data << endl;
    cout << "最大值:" << bt.FindMax(bt.GetRoot())->data << endl;
    ///////////////////////////////////////////////////////////////////
    cout << endl << "删除节点 5 " << endl;
    bt.Delete(4, bt.GetRoot());
    cout << "先序遍历: " << endl;
    bt.PreOrder(bt.GetRoot());
    cout << endl;
    cout << "中序遍历: " << endl;
    bt.CenOrder(bt.GetRoot());
    cout << endl;
    cout << "层次遍历:" << endl;
    bt.Trave(bt.GetRoot());
    cout << endl;
    cout << "最小值:" << bt.FindMin(bt.GetRoot())->data << endl;
    cout << "最大值:" << bt.FindMax(bt.GetRoot())->data << endl;
    system("pause");
    return 0;
}
时间: 2024-11-08 00:58:29

数据结构(6) -- 构建二叉搜索树的相关文章

[leetcode]108. Convert Sorted Array to Binary Search Tree构建二叉搜索树

构建二叉搜索树 /* 利用二叉搜索树的特点:根节点是中间的数 每次找到中间数,左右子树递归子数组 */ public TreeNode sortedArrayToBST(int[] nums) { return builder(nums,0,nums.length-1); } public TreeNode builder(int[] nums,int left,int right) { if (left>right) return null; int mid = (left+right)/2;

[数据结构]P2.1 二叉搜索树

二叉树就是每个节点最多有两个分叉的树.这里我们写一写一个典型的例子二叉搜索树,它存在的实际意义是什么呢? 在P1.1链表中,我们清楚了链表的优势是善于删除添加节点,但是其取值很慢:数组的优势是善于取值,但是不利于删除添加节点. 而二叉搜索树,正是两者的折中方案.首先,它是树状结构,因此它便于插入和删除节点,需要花费LogN级别的时间,其次,它 在每一个节点上都满足`左子树 <= 当前节点 <= 右子树`,因此便于使用二叉搜索,所以查找数据和取数据也是LogN级别的. 时间比较 链表 二叉搜索树

使用排序数组/链表构建二叉搜索树

2018-08-13 11:29:05 一.Convert Sorted Array to Binary Search Tree 问题描述: 问题求解: public TreeNode sortedArrayToBST2(int[] nums) { if (nums == null || nums.length == 0) { return null; } return helper(0, nums.length - 1, nums); } private TreeNode helper (in

数据结构|-二叉查找树(二叉搜索树)的链式存储结构的实现

二叉排序树,又称为二叉查找树. 它或者是一棵空树,或者是具有下列性质的二叉树. 若它的左子树不为空,则左子树上所有的结点的值均小于根结构的值: 若它的右子树不为空,则右字数上所有结点的值均大于它的根结点的值: 它的左右子树也分别为二叉排序树. 优点: 1,排序方便 2,方便查找 3,方便插入和删除 二叉排序树的插入数据: 因为二叉排序树中所有的数都符合排序树的特点,所以任意插入一个数时,都能在遍历树的过程中找到其应该放置的正确位置 二叉排序树的删除数据: 三种情况: 1,叶子结点:直接删除该叶子

数据结构-二叉搜索树(BST binary search tree)

本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/ 二叉搜索树简介 顾名思义,二叉搜索树是以一棵二叉树来组织的,这样的一棵树可以用一个链表数据结构来表示,每个节点除了key和卫星数据(除了二叉树节点的基本数据以外人为添加的数据,这些数据和树的基本结构无关),还有left.right.parent,分别指向节点的左孩子.右孩子和父节点,如果对应的节点不存在则指向NIL节点(因为最简单的二叉搜索树中的NIL节点里并没有有用的信息,所以在实现的时候简

数据结构(三):非线性逻辑结构-特殊的二叉树结构:堆、哈夫曼树、二叉搜索树、平衡二叉搜索树、红黑树、线索二叉树

在上一篇数据结构的博文<数据结构(三):非线性逻辑结构-二叉树>中已经对二叉树的概念.遍历等基本的概念和操作进行了介绍.本篇博文主要介绍几个特殊的二叉树,堆.哈夫曼树.二叉搜索树.平衡二叉搜索树.红黑树.线索二叉树,它们在解决实际问题中有着非常重要的应用.本文主要从概念和一些基本操作上进行分类和总结. 一.概念总揽 (1) 堆 堆(heap order)是一种特殊的表,如果将它看做是一颗完全二叉树的层次序列,那么它具有如下的性质:每个节点的值都不大于其孩子的值,或每个节点的值都不小于其孩子的值

Java数据结构——二叉搜索树

定义二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉排序树. 性质1,任意节点x,其左子树中的key不大于x.key,其右子树中的key不小于x.key.2,不同的二叉搜索树可以代表同一组值的集合.3,二叉搜索树的基本操作和树的高度成正比,所以如果是一棵完全二叉树

二叉搜索树&mdash;&mdash;算法导论(14)

1. 什么是二叉搜索树     顾名思义,二叉搜索树是以一棵二叉搜索树来组织的.如下图,这样的一棵树可以使用一个链表数据结构来表示,其中的每一个节点是一个对象.除了key和卫星数据之外,每个节点还包含属性left(左孩子).right(右孩子).和p(双亲)(若不存在,则值为NIL).     二叉搜索树中的关键字总是以满足二叉搜索树性质的方式存储: 设x是二叉搜索树的一个节点.如果y是x左子树中的一个节点,那么y.key≤x.key.如果y是x右子树中的一个节点,那么y.key≥x.key.

【算法导论】学习笔记——第12章 二叉搜索树

搜索树数据结构支持多种动态集合操作,包括SEARCH.MINIMUM.MAXIMUM.PREDECESSOR.SUCCESSOR.INSRT和DELETE操作等.基本的搜索树就是一棵二叉搜索树.12.1 什么是二叉搜索树1. 二叉搜索树的性质:设x是二叉搜索树中的一个结点.如果y是x左子树中的一个结点,那么y.key<=x.key.如果y是x右子树中的一个结点,那么y.key>=x.key.三种遍历时间复杂度是O(n),这是显然的. 12.1-3 1 void Inorder_Tree_Wal