二叉搜索树的建立

二叉搜索树最大特征是:左边子结点的值<当前结点的值,右边子结点的值>当前结点的值。

依照这个特征,可以使用递归和非递归两种方式建立一颗二叉搜索树。

下面是我的代码,分明列举了递归和非递归的建立方式。最初写的代码与正确版本大致相同,但程序总是运行不通过,debug后发现问题在于指针操作错误。自以为对c语言非常熟稔了,但还是犯下如此幼稚的错误,所以贴出这个错误,作为一个警示。

2014/5/24 ps:原来二叉搜索树最难的地方在于删除操作,所以补充一个删除操作。此外,还明白了书本介绍二叉搜索树的原因,因为很多更复杂的树结构,是以此为基础的,如b树,b+树,avl树等等。

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef struct NODE
{
    NODE * pleft;
    NODE * pright;
    int ivalue;
} node;

/*  错误示例,实际上这个函数并没有连接起新建的结点

void insert_bitree(node *pt, int value)
{

    if(pt == NULL)
    {
        pt = (node *) malloc ( sizeof(node) );
        pt->ivalue = value;
        pt->pleft = NULL;
        pt->pright = NULL;
        return ;
    }
    else if( value < pt->ivalue)
    {
        insert_bitree(pt->pleft, value);
    }
    else
    {
        insert_bitree(pt->pright, value);
    }

}

*/

void insert_bitree(node **ppt, int value) //递归方式1
{

    if(*ppt == NULL)
    {
        *ppt = (node *) malloc ( sizeof(node) );
        (*ppt)->ivalue = value;
        (*ppt)->pleft = NULL;
        (*ppt)->pright = NULL;
        return ;
    }
    else if( value < (*ppt)->ivalue)
    {
        insert_bitree(&((*ppt)->pleft), value); //将指向指针的指针重定位到当前结点的pleft
    }
    else
    {
        insert_bitree(&((*ppt)->pright), value); //将指向指针的指针重定位到当前结点的pright
    }

}

node* create_searchtree(node *t, int  temp)   //递归方式2
{
    if (t == NULL) {    // 若当前树为空
        t = (node *)malloc(sizeof(node) * 1);
        if (t == NULL) {
            printf("内存分配失败!\n");
            exit(EXIT_FAILURE);
        }
        t->ivalue = temp;
        t->pleft = NULL;
        t->pright = NULL;
    }else if (t->ivalue  > temp) {   // 如果比当前结点小,则插入左子树
        t->pleft = create_searchtree(t->pleft, temp);
    }else if (t->ivalue < temp){    // 如果比当前结点大,则插入右子树
        t->pright = create_searchtree(t->pright, temp);
    }  

    return t;
} 

node * creat_bitree(int value[], int len) //非递归方式
{
    int i, flag;

    node *before;
    node *tmp;
    node *pt = (node *)malloc( sizeof(node) );

    pt->ivalue = value[0];
    pt->pleft = pt->pright = NULL;

    flag = 0;
    for(i = 1; i < len; i++)
    {
        tmp = pt;
        while(tmp != NULL)
        {
            if ( value[i] < (tmp)->ivalue)
            {
                before = tmp; // 存储当前结点的位置
                flag = -1;  //标志位,表明向左子树探索
                tmp = (tmp)->pleft;

            }
            else
            {
                before = tmp;
                flag = 1;
                tmp = tmp->pright;
            }

        }

            if(flag == -1) //将输入值插入当前结点的左子树
            {
                before->pleft = (node *) malloc (sizeof(node) );
                before->pleft->ivalue = value[i];
                before->pleft->pleft = before->pleft->pright = NULL;
            }
            else if( flag == 1)
            {

                before->pright = (node *) malloc (sizeof(node) );
                before->pright->ivalue = value[i];
                before->pright->pleft = before->pright->pright = NULL;
            }

    }

    return pt;

}

void preorder(node *pt)  //先序访问二叉树
{
    if(pt != NULL)
    {
        printf("%d\n", pt->ivalue);
        preorder(pt->pleft);
        preorder(pt->pright);
    }
}

void postorder(node *pt)
{
    if(pt != NULL)
    {
        postorder(pt->pleft);
        postorder(pt->pright);
        printf("%d\n", pt->ivalue);
    }
}

int main()
{

    int a[8] = {1, 2, 7, 4, 5, 19, 9, 3};
    int len = sizeof(a) / sizeof(int);

#if 1
    int i;
    node *pt = (node *)malloc(sizeof(node));
    assert(pt != NULL);
    pt->ivalue = a[0];
    pt->pleft = pt->pright = NULL;
    for(i = 1; i < 8; i++)
    {

        //pt = create_searchtree(pt, a[i]);
        insert_bitree(&pt, a[i]);

    }
#else 

    node *pt = creat_bitree(a, len);

#endif

    preorder(pt);

    return 0;
}
node * find_elem(int x, node * t)
{
    if( t == NULL)
        return NULL;
    if( x < t->ivalue)
        return find_elem(x, t->pleft);
    else if ( x > t->ivalue)
        return find_elem(x, t->pright);
    else
        return t;
}

node * find_min(node *t)
{
    if( t == NULL)
        return NULL;
    else if( t->pleft == NULL)
        return t;
    else
        return find_min(t->pleft);
}

node * delete_elem(int x, node *t)
{
    node * tmp;

    if( t == NULL) // 已到树底,并且树中不存在该元素
    {
        printf("element: %d doesn't exist\n", x);
        exit(-1);
    }
    else if( x < t->ivalue ) // 进入左子树
        t->pleft = delete_elem(x, t->pleft );
    else  if( x > t->ivalue )
        t->pright = delete_elem(x, t->pright);
    else if( t->pleft && t->pright) // 找到该元素,但该元素还有两个子节点,从最右端节点找到最小点,进行替换该元素所在节点,替换后该树仍为二叉搜索树
    {
        tmp  = find_min(t->pright);
        t->ivalue = tmp->ivalue;
        t->pright = delete_elem(t->ivalue, t->pright);
    }
    else // 找到该元素,但该元素仅有一个子节点
    {
        tmp = t;
        if( t->pleft == NULL)
            t = t->pright;
        else if( t->pright == NULL)
            t = t->pleft;
        free(tmp);
    }
    return t;
}
 

 

时间: 2024-10-07 15:23:28

二叉搜索树的建立的相关文章

九度题目1009:二叉搜索树

题目1009:二叉搜索树 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4308 解决:1919 题目描述: 判断两序列是否为同一二叉搜索树序列 输入: 开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束. 接下去一行是一个序列,序列长度小于10,包含(0~9)的数字,没有重复数字,根据这个序列可以构造出一颗二叉搜索树. 接下去的n行有n个序列,每个序列格式跟第一个序列一样,请判断这两个序列是否能组成同一颗二叉搜索树. 输出: 如果序列相同则输出YES

二叉搜索树的非递归创建和搜索

#include "stdio.h" typedef struct node { int data ; node*lChild ; node*rChild ; }TreeNode ; void Insert(TreeNode**root,int data) //向二叉查找树中插入元素 采用非递归思想 { TreeNode * p=*root ;//获得根结点 TreeNode*q=new TreeNode ;//分配一个要插入的新节点 q->lChild=q->rChild

【算法学习】AVL平衡二叉搜索树原理及各项操作编程实现(C++)

AVLTree即(Adelson-Velskii-Landis Tree),是加了额外条件的二叉搜索树.其平衡条件的建立是为了确保整棵树的深度为O(nLogn).平衡条件是任何节点的左右子树的高度相差不超过1.   在下面的代码中,编程实现了AVL树的建立.查找.插入.删除.遍历等操作.采用C++类封装. AVL树中比较复杂的操作时插入和删除操作.在这里对插入和删除操作进行讲解.   AVL树的插入操作 向AVL树中插入元素可能会导致树失去平衡.但是,我们只需要调整插入点至根节点的路径上不满足平

c++-二叉搜索树的遍历问题

问题描述 二叉搜索树的遍历问题 #include<iostream> #include<string> using namespace std; class node{ public: string name; string keyword; node* left; node* right; node(string a = 0, string b = 0, node* c = 0, node* d = 0) : name(a), keyword(b), left(c), right

[华为机试练习题]33.二叉搜索树

题目 描述: 判断两序列是否为同一二叉搜索树序列 题目类别: 树 难度: 中级 运行时间限制: 10Sec 内存限制: 128MByte 阶段: 入职前练习 输入: 开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束. 接下去一行是一个序列,序列长度小于10,包含(0~9)的数字,没有重复数字,根据这个序列可以构造出一颗二叉搜索树. 接下去的n行有n个序列,每个序列格式跟第一个序列一样,请判断这两个序列是否能组成同一颗二叉搜索树. 输出: 如果序列相同则输出YES

纸上谈兵: 树, 二叉树, 二叉搜索树[转]

树的特征和定义 树(Tree)是元素的集合.我们先以比较直观的方式介绍树.下面的数据结构是一个树: 树有多个节点(node),用以储存元素.某些节点之间存在一定的关系,用连线表示,连线称为边(edge).边的上端节点称为父节点,下端称为子节点.树像是一个不断分叉的树根. 每个节点可以有多个子节点(children),而该节点是相应子节点的父节点(parent).比如说,3,5是6的子节点,6是3,5的父节点:1,8,7是3的子节点, 3是1,8,7的父节点.树有一个没有父节点的节点,称为根节点(

二叉搜索树与双向链表的C++实现

题目:输入一颗二叉搜索树, 将该二叉搜索树转换成一个排序的双向链表. 要求不能创建任何新的结点, 只能调整数中结点的指针的指向. 方法: 使用中序遍历每一个结点, 并进行连接, 即左子树指前, 右子树指后, 并保存前一个节点. 本程序包含算法原理, 测试程序, 及 输出. 代码: /* * main.cpp * * Created on: 2014.6.12 * Author: Spike */ /*eclipse cdt, gcc 4.8.1*/ #include <iostream> #i

二叉搜索树(Binary Search Tree)--C语言描述(转)

图解二叉搜索树概念 二叉树呢,其实就是链表的一个二维形式,而二叉搜索树,就是一种特殊的二叉树,这种二叉树有个特点:对任意节点而言,左孩子(当然了,存在的话)的值总是小于本身,而右孩子(存在的话)的值总是大于本身. 下面来介绍在此种二叉树结构上的查找,插入,删除算法思路. 查找:因为这种结构就是为了来方便查找的,所以查找其中的某个值很容易,从根开始,小的往左找,大的往右找,不大不小的就是这个节点了: 代码很简单,这里就不写了. 插入:插入一样的道理,从根开始,小的往左,大的往右,直到叶子,就插入.

剑指offer系列之二十五:二叉搜索树与双向链表

题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 由于二叉搜索树的中序遍历就是排序的,如果是构造单链表,只需要一次中序遍历就可以了,但现在需要构造双链表,也就是在中序遍历的过程中需要设置每个节点的left与right指针,现在问题是如何设置这两个指针?二叉搜索树有一个特点,就是根节点的左子树上所有节点都比根节点的值小,而右子树上的所有节点的值都比根节点的值大,利用这个性质,当遍历根节点的左孩子的时候,可以继续把其当做左子