数据结构与算法之二叉搜索树

  与链表不同,树是一种非线性的数据结构。树中最常用的是二叉树,二叉树限制了子树的数量,也就是每个结点的子树至多2个,并且这两个子树是有顺序的。而二叉搜索树(二叉查找树,二叉排序树)是指根节点的关键字大于左子树的,而小于右子树,并且,左右子树也是一颗二叉搜索树。也就是说中序遍历一颗二叉搜索树,它的输出是从小到大排序好的。

  除了普通的二叉搜索树之外,还有很多关于它的变形。

  二叉平衡搜索树,即即是一颗二叉平衡树,也是一颗搜索树,平衡树即任意一个结点的左子树的高度与右子树的高度之差的绝对值不大于1。

  红黑树,也是一种特殊的二叉查找树,除了具备查找树的特点,它的每个结点上还有一个记录红黑颜色的元素。

  这里我们主要讨论一般的二叉搜索树。

  二叉搜索树,其实就是一颗特殊的树,任何适用于树的算法都适用于二叉搜索树。当然它也是图,任何适用于图的算法也适用于二叉搜索树。图中的深度优先搜索(DFS)其实就是树中的前序遍历,广度优先搜索(BFS)就是树中的层序遍历。当然图中还有很多其他算法也都适用于树。

1、二叉树的数据结构

typedef struct binSrcTreeNode{
    int element;
    struct binSrcTreeNode *pLeft;
    struct binSrcTreeNode *pRight;
}BSTNode;

2、动态分配一个二叉树的结点

BSTNode* allocNode(int element){
    BATNode *pNode = (BSTNode*)malloc(sizeof(BSTNode));
    if(NULL != pNode){
        pNode->element = element;
        pNode->pLeft = NULL;
        pNode->pRight = NULL;
    }
    return pNode;
}

3、二叉搜索树的查找

由于二叉搜索树是已经排序了的二叉树,所以可以通过二分查找来搜索。先判断是否等于根节点,如果大于根节点的关键字,搜索右子树,小于根节点的关键字,搜索左子树。

bool searchInBSTree(const BSTNode *pRoot,int element,BSTNode **pNode){
    if(NULL == pRoot)
        return false;
    *pNode = pRoot;
    if(pRoot->element == element){
        return true;
    }
    else if(pRoot->element > element)
        return searchInBSTree(pRoot->pLeft,element,pNode);
    else
        return searchInBSTree(pRoot->pRight,element,pNode);
}

4、二叉搜索树的插入

首先查找二叉树是是否已经存在该元素,如果已经存在返回false;如果不存在,插入该结点,插入元素大于根节点,则插入右子树,否则,插入左子树中。

bool insertIntoBSTree(BSTNode **pRoot,int element){
    if(NULL == pRoot)
        return false;
    if(NULL == *pRoot){
        *pRoot = allocNode(element);
        return NULL==*pRoot?false:true;
    }
    BSTNode **pSrc = NULL;
    if(searchInBSTree(pRoot,element,pSrc))
        return false;
    BSTNode *pNode = allocNode(element);
    if(element < *pSrc->element)
        *pSrc->pLeft = pNode;
    else
        *pSrc->pRight = pNode;
    return true;
}

5、二叉搜索树的删除

二叉搜索树的删除分为三种情况:

(1) 删除结点为叶子结点,直接删除该结点,再修改其父结点的指针(注意分是根结点和不是根节点)。

(2) 删除结点为单支结点(即只有左子树或右子树)。

(3) 删除结点的左子树和右子树均不空。

bool deleteFromBSTree(BSTNode **pRoot,int element){
    if(NULL == pRoot || NULL == *pRoot)
        return false;
    BSTNode **pSrc = NULL;
    BSTNode **pParent = NULL;
    if(searchInBSTree(*pRoot,element,pParent,pSrc)){
        if(NULL == *pSrc->pLeft && NULL == *pSrc->pRight){
            free(*pSrc);
            *pSrc = NULL;
            return true;
        }
        else if(NULL == *pSrc->pLeft){
            if(*pSrc == *pParent->pLeft)
                *pParent->pLeft = *pSrc->pRight;
            else if(*pSrc == *pParent->pRight)
                *pParent->pRight = *pSrc->pRight;
            free(*pSrc);
            return true;
        }
        else if(NULL == *pSrc->pRight){
            if(*pSrc == *pParent->pLeft)
                *pParent->pLeft = *pSrc->pLeft;
            else if(*pSrc == *pParent->pRight)
                *pParent->pRight = *pSrc->pLeft;
            free(*pSrc);
            return true;
        }
        else{
            BSTNode *pNode = *pSrc;
            BSTNode *pChild = *pSrc->pLeft;
            while(pChild->pRight){
                pNode = pChild;
                pChild = pChild->pRight;
            }
            if(pNode == *pSrc) pNode->pLeft = pChild->pLeft;
            else pNode->pRight = pChild->pLeft;

            if(*pSrc == *pParent->pLeft) *pParent->pLeft = pChild;
            else *pParent->pRight = pChild;

            pChild->pLeft = *pSrc->pLeft;
            pChild->pRight = *pSrc->pRight;

            return true;
        }
    }

    return false;
}

6、二叉搜索树的前序中序后序遍历

/* preOrder to traverse the binarySearchTree.*/
void preOrderBinarySearchTree(const BSTNode *pRoot){
    if(NULL == pRoot)
        return ;
    printf("%d ",pRoot->element);
    preOrderBinarySearchTree(pRoot->pLeft);
    preOrderBinarySearchTree(pRoot->pRight);
}

/* inOrder to traverse the binarySearchTree.*/
void inOrderBinarySearchTree(const BSTNode *pRoot){
    if(NULL == pRoot)
        return ;
    inOrderBinarySearchTree(pRoot->pLeft);
    printf("%d ",pRoot->element);
    inOrderBinarySearchTree(pRoot->pRight);
}

/* posOrder to traverse the binarySearchTree.*/
void posOrderBinarySearchTree(const BSTNode *pRoot){
    if(NULL == pRoot)
        return ;
    posOrderBinarySearchTree(pRoot->pLeft);
    posOrderBinarySearchTree(pRoot->pRight);
    printf("%d ",pRoot->element);
}

7、释放结点

void freeBinarySearchTree(BSTNode *pRoot){
    if(NULL == pRoot)
        return ;
    freeBinarySearchTree(pRoot->pLeft);
    freeBinarySearchTree(pRoot->pRight);
    free(pRoot);
}

完整代码详见:https://github.com/whc2uestc/DataStructure-Algorithm/tree/master/tree

typedef struct binSrcTreeNode{    int element;    struct binSrcTreeNode *pLeft;    struct binSrcTreeNode *pRight;}BSTNode;

时间: 2024-10-11 15:44:13

数据结构与算法之二叉搜索树的相关文章

数据结构与算法问题 二叉搜索树

1.序 具体实现了二叉查找树的各种操作:插入结点.构造二叉树.删除结点.查找.  查找最大值.查找最小值.查找指定结点的前驱和后继 2.二叉查找树简单介绍 它或者是一棵空树:或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上全部结点的值均小于它的根结点的值. (2)若右子树不空.则右子树上全部结点的值均大于它的根结点的值: (3)左.右子树也分别为二叉排序树 3.二叉查找树的各种操作 此处给出代码.凝视很具体.具体操作请參考代码: #include <iostream> using

70 数组的Kmin算法和二叉搜索树的Kmin算法对比

[本文链接] http://www.cnblogs.com/hellogiser/p/kmin-of-array-vs-kmin-of-bst.html [分析] 数组的Kmin算法和二叉搜索树的Kmin算法非常类似,其本质是找序列中的第K大或者第K小的元素,可以借鉴QuickSort的思想加以实现. [Kmin_of_Array] C++ Code 1234567891011121314151617181920212223242526272829303132333435363738394041

C++算法之 二叉搜索树转换为双向链表

题目: 输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的节点,只能调整树中节点指针的方向: 分析: 1:由于要求链表是有序的,可以借助二叉树中序遍历,因为中序遍历算法的特点就是从小到大访问结点.当遍历访问到根结点时,假设根结点的左侧已经处理好,只需将根结点与上次访问的最近结点(左子树中最大值结点)的指针连接好即可.进而更新当前链表的最后一个结点指针. 2:由于中序遍历过程正好是转换成链表的过程,即可采用递归处理 代码: // BT.cpp : 定义控制台应用程序的

《数据结构复习笔记》--二叉搜索树

二叉搜索树:维基百科:click here 二叉查找树(Binary Search Tree),也称二叉搜索树.有序二叉树(ordered binary tree),排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值: 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 任意节点的左.右子树也分别为二叉查找树. 没有键值相等的节点(no duplicate nodes

算法导论—二叉搜索树(BST)

华电北风吹 天津大学认知计算与应用重点实验室 日期:2015/9/9 与散列表一样,搜索树数据结构也支持动态集合操作,包含插入,查询,删除,最小值,最大值,前驱,后继等. 一.二叉搜索树: 二叉搜索树节点:关键字key,卫星数据,左孩子指针,右孩子指针,父节点指针,其他特殊类型(红黑树的节点颜色,AVL树的树高等). 二叉搜索树性质:x是二叉搜索树中的任意一个节点.若y是x左子树中任意一个节点有x.key>=y.key.若y是x右子树中任意一个节点有x.key<=y.key. 二.二叉搜索树的

一步两步学算法之二叉搜索树

Binary Search Tree  又叫二叉查找树,二叉排序树 这是种什么样的树呢? 其实就是根节点的左子树比根节点小  右子树比根节点大  同时 左子树和右子树也是二叉搜索树 代码比较简单 基本用递归实现 比较好理解  只有删除带有左右子树的节点时比较难理解 方法就是 直接在右子树找一个最小的节点 取代要被删除的节点 再继续删除右子树里的节点 详细看代码 1 #include "stdio.h" 2 #include "stdlib.h" 3 typedef

基础数据结构——是否同一棵二叉搜索树

给定一个插入序列就可以唯一确定一棵二叉搜索树.然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到.例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果.于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树. #include<iostream> #include<vector> using namespace std; #define Max_Node 11 #define END -1 typedef struct

【数据结构】5.2 二叉搜索树的创建查找以及插入操作

TAG 此代码遇到一个bug,在Insert函数中,注释部分,思考一下为什么用这个方法来添加会失效 #include<iostream> using namespace std; struct BTNode { int data; BTNode *lchild,*rchild; }; void selectsort(int a[], int n) { for (int i = 1; i < n; i++) { for (int j = i + 1; j < n; j++) { if

算法导论-----------二叉搜索树

先上二叉树查找树的删除的代码,因为删除是二叉查找树最复杂的操作: int BinarySearchTree<T>::tree_remove(const T& elem) { BinarySearchTreeNode<T> *z = tree_search(elem);//根据元素查找到要删除的节点 BinarySearchTreeNode<T> *x, *y; if (z != NULL) { //用y来表示实际要删除的节点 if (z->left ==