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

二叉排序树,又称为二叉查找树。

它或者是一棵空树,或者是具有下列性质的二叉树。

  • 若它的左子树不为空,则左子树上所有的结点的值均小于根结构的值;
  • 若它的右子树不为空,则右字数上所有结点的值均大于它的根结点的值;
  • 它的左右子树也分别为二叉排序树。

优点:

  • 1,排序方便
  • 2,方便查找
  • 3,方便插入和删除



二叉排序树的插入数据:

因为二叉排序树中所有的数都符合排序树的特点,所以任意插入一个数时,都能在遍历树的过程中找到其应该放置的正确位置

二叉排序树的删除数据:

三种情况:

  • 1,叶子结点:直接删除该叶子(置空)
  • 2,仅有左子树或者右子数的结点:将其子树的值赋给结点,删除这个子树
  • 3,左右子树都有:找到结点的右子树中最小的结点(左子树的左的……的左子树)赋值给待删结点,然后删除那个最小的结点




代码部分:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestFun4
{
    class Program
    {
        static void Main(string[] args)
        {
            BSTree tree = new BSTree();
            int[] data = { 62, 58, 88, 47, 73, 99, 35, 51, 93, 37 };
            foreach (int item in data)
            {
                //将数组中的数装进树中去
                tree.Add(item);
            }
            Console.WriteLine("树的中序遍历:");
            tree.MiddleTravelsal();
            Console.WriteLine();
            Console.WriteLine("99是否存在树中:" + tree.Find(99));
            Console.WriteLine("11是否存在树中:" + tree.Find(11));
            tree.Delete(35);
            Console.WriteLine("删除35之后的中序遍历");
            tree.MiddleTravelsal();
            Console.WriteLine();
            tree.Delete(62);
            Console.WriteLine("删除62之后的中序遍历");
            tree.MiddleTravelsal();

            Console.ReadKey();
        }
    }

    /// <summary>
    /// 结点类、存储该结点的左子树、右子树、父亲
    /// </summary>
    class BSNode
    {
        public BSNode LeftChild { get; set; }
        public BSNode RightChild { get; set; }
        public BSNode Parent { get; set; }
        public int Data { get; set; }

        public BSNode() { }
        public BSNode(int item)
        {
            this.Data = item;
        }
    }

    class BSTree
    {
        BSNode root = null;

        //添加数据
        public void Add(int item)
        {
            //以该数据创建一个新结点
            BSNode newNode = new BSNode(item);
            //如果根节点为空,直接让插入的数据成为根节点
            if (root == null)
            {
                root = newNode;
            }
            else
            {
                BSNode temp = root;
                //遍历整棵树找到最适合插入数据的位置
                while (true)
                {
                    if (item >= temp.Data)//放在temp右边
                    {
                        if (temp.RightChild == null)//如果temp无右子树,就把newnode作为temp的右子树
                        {
                            temp.RightChild = newNode;
                            newNode.Parent = temp;
                            break;
                        }
                        else//否则继续往下遍历
                        {
                            temp = temp.RightChild;
                        }
                    }
                    else//放在temp左边
                    {
                        if (temp.LeftChild == null)
                        {
                            temp.LeftChild = newNode;
                            newNode.Parent = temp;
                            break;
                        }
                        else
                        {
                            temp = temp.LeftChild;
                        }
                    }
                }
            }
        }

        //中序遍历(中序遍历就是二叉排序树的从小到大排序)
        public void MiddleTravelsal()
        {
            MiddleTravelsal(root);
        }
        private void MiddleTravelsal(BSNode node)
        {
            if (node == null) return;
            MiddleTravelsal(node.LeftChild);
            Console.Write(node.Data + "  ");
            MiddleTravelsal(node.RightChild);
        }

        //判断树中是否已存在item这个值
        public bool Find(int item)
        {
            BSNode temp = root;
            while (true)
            {
                if (temp == null) return false;
                if (temp.Data == item) return true;
                if (item > temp.Data)
                    temp = temp.RightChild;
                else
                    temp = temp.LeftChild;
            }
        }

        //删除某个值所在的结点
        public bool Delete(int item)
        {
            BSNode temp = root;
            while (true)
            {
                //temp==null表示树中没有找到该值,返回false表示删除失败
                if (temp == null) return false;
                if (temp.Data == item)
                {
                    DeleteNode(temp);
                    return true;
                }
                if (item > temp.Data)
                    temp = temp.RightChild;
                else
                    temp = temp.LeftChild;
            }
        }
        //删除结点的具体操作
        private void DeleteNode(BSNode node)
        {
            //情况1:要删除的结点没有左右子树
            if (node.LeftChild == null && node.RightChild == null)
            {
                if (node.Parent == null)//删除根结点
                    root = null;
                else if (node.Parent.LeftChild == node)//要删除的结点是其父亲的左子树时候
                    node.Parent.LeftChild = null;//删除左子树就是删除该结点
                else if (node.Parent.RightChild == node)//右子树的情况
                    node.Parent.RightChild = null;
                return;
            }
            //情况2:要删除的结点有右子树没有左子树
            if (node.LeftChild == null && node.RightChild != null)
            {
                node.Data = node.RightChild.Data;//将其右子树作为被删除的这个结点
                node.RightChild = null;
                return;
            }
            //情况3:要删除的结点有左子树没有右子树
            if (node.LeftChild != null && node.RightChild == null)
            {
                node.Data = node.LeftChild.Data;
                node.LeftChild = null;
                return;
            }
            //情况4:要删除的结点有左右两个子树
            BSNode temp = node.RightChild;//找到右子树所包含的所有结点中最小的结点替换现在的结点
            while (true)
            {
                //左子树的左子树的左子树的…的左子树就是整个子树中最小的结点
                if (temp.LeftChild != null)
                    temp = temp.LeftChild;
                else
                    break;
            }
            node.Data = temp.Data;//数值替换
            DeleteNode(temp);//递归调用:把temp这个结点删除(因为temp无子树,所以会递归到情况1来删除这个结点)
        }

    }
}


结果:

原文地址:https://www.cnblogs.com/wq-KingStrong/p/10339608.html

时间: 2024-10-11 14:51:22

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

c数据结构 -- 线性表之 复杂的链式存储结构

复杂的链式存储结构 循环链表 定义:是一种头尾相接的链表(即表中最后一个结点的指针域指向头结点,整个链表形成一个环) 优点:从表中任一节点出发均可找到表中其他结点 注意:涉及遍历操作时,终止条件是判断 p->next == L? 双向链表 定义:在单链表的每个结点离再增加一个指向直接前驱的指针域 prior,这样链表中就形成了有 两个方向不用的链,故称为双向链表 双向循环链表 定义: 和单链的循环表类似,双向链表也可以有循环表 ·让头节点的前驱指针指向链表的最后一个结点 ·让最后一个结点的后继指

栈的链式存储结构和入栈出栈操作

参考<大话数据结构>P98~99——栈的链式存储结构. 进栈: 出栈: 举个简单的例子: 代码和解释如下(VS2012测试通过): 1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 typedef string status;//用书上推荐的status返回是否成功,C++中的模板类string比字符数组char[]更方便 6 7 //栈的结点 8 //包含data,和指向下一个结点

Java数据结构之二叉搜索树

Java数据结构之二叉搜索树 1.二叉搜索树组成 二叉搜索树又称为二叉排序树,它或者是一颗空树,或者是一颗具有如下特性的非空二叉树,需要满足一下三个条件: (1)若它的左子树非空,则左子树上所有结点的关键字均小于根结点的关键字: (2)若它的右子树非空,则右子树上所有结点的关键字均大于(可以等于)根结点的关键字. (3)左子树右子树本身又各是一颗二叉搜索树 在算法描述中,均以结点值的比较来代表其关键字的比较,因为若结点的值为类类型时,该类必须实现系统提供的java.lang.comparable

二叉树的链式存储结构----二叉链表

头文件:head.h #include<string.h> #include<ctype.h> #include<malloc.h> /* malloc()等 */ #include<limits.h> /* INT_MAX等 */ #include<stdio.h> /* EOF(=^Z或F6),NULL */ #include<stdlib.h> /* atoi() */ #include<io.h> /* eof()

二叉树的链式存储结构--二叉链表

1 二叉树的链式存储结构 //二叉链表的结点结构定义 typedef struct BiTNode { int data; struct BiTNode *lchild; struct BiTNode *rchild; }BiTNode; typedef struct BiTNode *BiTree; 结构示意图如下: 2 二叉树的遍历方法 (1)前序遍历:先访问根结,然后前序遍历左子树,再前序遍历右子树. (2)

03.线性表(二)链式存储结构.单链表1

链式存储结构.单链表1 1.基本概念 为了表示每个数据元素ai与其直接后继数据元素ai+1之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置) (1)数据域:存储线性表数据元素数据信息的域称为数据域: (2)指针域:把存储直接后继位置(下一个数据元素的地址)的域称为指针域,指针域中存储的信息为指针或链: (3)结点(Node):由数据域和指针域两部分信息组成数据元素ai的存储映像,称为结点. (4)头指针:把链表中第一个结点的存储

数据结构与算 5:C++ 顺序/链式存储,栈 模板类实现,编译模板类问题解决

[本文谢绝转载原文来自http://990487026.blog.51cto.com] 数据结构与算 5:C++ 顺序/链式存储,栈 模板类实现 C++ 顺序存储模板类的实现[面试重要] C++ 链式存储模板类的实现[面试重要] C++ 链式存储模板类,载入指针 c++ 栈的链式存储实现(模板类嵌套模板类),编译问题教训[重要] C++ 顺序存储模板类的实现[面试重要] 项目文件: [email protected]://990487026.blog.51cto.com~/c++$ tree .

数据结构(四)——基于链式存储结构的线性表

数据结构(四)--基于链式存储结构的线性表 一.基于链式存储结构的线性表 1.链式存储的定义 链式存储为了表示数据元素与其直接后继元素间的逻辑关系,数据元素除了存储本身的信息外,还需要存储直接后继的信息.相连的数据元素之间在存储空间中不要求连续.链式存储的逻辑结构基于链式存储结构的线性表中,每个结点都包含数据域和指针域.数据域用于存储数据元素本身,指针域用于存储相邻结点的地址. 2.链表的定义 链表是基于链式存储结构的线性表链表的基本元素:头结点:链表中的辅助结点,包含指向第一个数据元素的指针数

数据结构--线性表的链式存储结构

一 线性表的链式存储结构 A.链式存储的定义为了表示每个数据元素与直接后继元素之间的逻辑关系:数据元素除了存储本身的信息外,还需要存储其直接后继的信息图示B链式存储逻辑结构基于链式存储结构的线性表中,每个结点都包含数据域和指针域1.数据域:存储数据元素本身2.指针域:存储相邻结点的地址图示C链表中的基本概念1.头结点--链表中的辅助结点,包含指向第一个数据元素的指针(方便插入和删除)2.数据结点--链表中代表数据元素的结点,表现形式为:(数据元素,地址)3.尾节点--链表中的最后一个数据结点,包

数据结构之线性表(链式存储结构)

线性表的实现分顺序存储结构和链式存储结构 上一节我们主要介绍了顺序存储结构,在最后我们还分别总结了顺序存储结构的优缺点, 对于顺序结构的缺点,我们有没有什么好的解决方法呢? 我们今天要介绍的线性表的链式存储结构就可以很好的解决顺序结构的缺点,一起来看. 顺序结构最大的缺点就是在进行插入和删除操作的时候,如果插入位置不理想,那么我们需要移动大量的元素,那产生这一问题的原因是什么呢? 仔细分析后,我们可以发现在顺序存储结构中,他们相邻的元素的存储位置也是相邻的,我们在申请内存的的时候,是一次性申请一