数据结构--‘搜索二叉树’

‘二叉树’是数据结构中比较重要的一部分,这里主要讨论一下‘搜索二叉树’,针对‘搜索二叉树的插入、删除和查找节点进行分情况讨论,希望能够帮助读者更加的理解搜索二叉树的原理。

◆搜索二叉树的性质:

1.每个节点都有一个一个作为搜索依据的关键码,所有节点的关键码都不相同。

2.左子树所有的关键码(key)都小于根节点的关键码(key)。

3.右子树所有的关键码(key)都大于根节点的关键码(key)。

4.左、右子树都是二叉搜索树。

实现‘搜索二叉树’的节点结构可以实现为K形式,和K、V形式,若实现K形式,则K表示节点的值,同时可以使用K来确定节点的位置,若实现K、V形式,则K表示节点的一个标记,用来判断节点在二叉树中具体的存储位置,V表示节点的具体存储的值。这里实现的是K、V形式,K形式读者可以下去自己进行尝试。


◆下面为实现‘搜索二叉树’的具体节点结构:

template <class K, class V>
struct BSTNode
{
     BSTNode<K, V>* _left;      //指向左节点的指针
     BSTNode<K, V>* _right;     //指向右节点的指针
     K _key;         //节点标记,确定节点位置
     V _value;       //节点的值
     
     BSTNode(const K& key, const V& value)    //构造节点
      :_key(key)
      , _value(value)
      , _left(NULL)
      , _right(NULL)
     { }
};


◆讨论相关操作情况

(1)节点插入

(2)节点删除

(3)节点查找

根据搜索二叉树的性质来进行查找,当key>root->key;向右孩子节点再次进行查找,当key<root->key,从左边的孩子节点进行查找,否则,就证明查找到了。

◆下面是详细的代码(实现的递归和非递归两种方式)

template <class K, class V>
class BSTree
{
     typedef BSTNode<K, V> Node;
     
public:
     BSTree()              //构造
          :_root(NULL)
     {}
     
     bool Insert(const K& key, const V& value)          //非递归插入
     {
          if (_root == NULL)    //根节点为空
          {
               _root = new Node(key, value);
               return true;
          }
          
          Node* cur = _root;
          if (cur->_left == NULL && cur->_right == NULL)    //父节点的左右节点为空
          {
               if (cur->_key < key)
               {
                    cur->_right = new Node(key, value);
               }
               else if (cur->_key > key)
               {
                    cur->_left = new Node(key, value);
               }
               else
               {
                    return false;
               }
          }
          else                                         
          {
               Node* parent = cur;
               while (cur)
               {
                    parent = cur;
                    if (cur->_key < key)   
                    {
                         if (parent->_right == NULL)          //右节点为空
                         {
                              parent->_right = new Node(key, value);
                         }
                         cur = cur->_right;
                    }
                    else if (cur->_key > key)
                    {
                         if (parent->_left == NULL)         //左节点为空
                         {
                              parent->_left = new Node(key, value);
                         }
                         cur = cur->_left;
                    }
                    else                              //数据在树中已经存在,防止数据冗余
                    {
                         return false;
                    }
               }
          }
          return true;
     }
     
     
     bool Remove(const K& key)                           //非递归删除
     {
          if (_root == NULL)          //根节点为空
          {
               return false;
          }
          
          if (_root->_left == NULL && _root->_right == NULL)       //根节点的左右节点为空
          {
               if (_root->_key == key)
               {
                    delete _root;
                    _root = NULL;
                    return true;
               }
               else
               {
                    return false;
               }
          }
          
          Node* parent = NULL;
          Node* cur = _root;
          while (cur)
          {
               if (cur->_key > key)     //寻找要删除的节点
               {
                    parent = cur;
                    cur = cur->_left;
               }
               else if (cur->_key < key)
               {
                    parent = cur;
                    cur = cur->_right;
               }
               else                 //找到要删除的节点
               {
                    Node* del = cur;
                    if (cur->_left == NULL)     //左为空
                    {
                         if (parent == NULL)      //cur节点没有父节点
                         {
                              _root = cur->_right;
                         }  
                         else                 //cur有父节点
                         {
                              if (parent->_left == cur)    
                              {
                                   parent->_left = cur->_right;
                              }
                              else
                              {
                                   parent->_right = cur->_right;
                              }
                         }
                    }
                    else if (cur->_right == NULL)     //右为空
                    {
                         if (parent == NULL)
                         {
                              _root = cur->_left;
                         }
                         else
                         {
                              if (parent->_left == cur)
                              {
                                   parent->_left = cur->_left;
                              }
                              else
                              {
                                   parent->_right = cur->_left;
                              }
                         }
                    }
                    else     //左、右为空
                    {
                         //找右树的最左节点
                         //找到的节点与cur交换再删除
                         parent = cur;
                         Node* firstLeft = cur->_right;
                         while (firstLeft->_left)
                         {
                              parent = firstLeft;
                              parent = firstLeft->_left;
                         }
                         swap(cur->_key, firstLeft->_key);
                         swap(cur->_value, firstLeft->_value);
                         del = firstLeft;
                         if (parent->_left == firstLeft)
                         {
                              parent->_left = firstLeft->_right;
                         }
                         else
                         {
                              parent->_right = firstLeft->_right;
                         }
                    }
                    delete del;
                    return true;
               }    
          }
          return false;
     }

     Node* Find(const K& key)                           //非递归查找
     {
          if (_root == NULL)
          {
           return NULL;
          }
          
          Node* cur = _root;
          while (cur)
          {
               if (cur->_key < key)
               {
                    cur = cur->_right;
               }
               else if (cur->_key > key)
               {
                    cur = cur->_left;
               }
               else
               {
                    return cur;
               }
          }
          return NULL;
     }
     
     bool Insert_R(const K& key, const V& value)    //递归实现插入
     {
          return _Insert_R(_root, key, value);
     }
     
     bool Remove_R(const K& key)                 //递归实现删除
     {
          return _Remove_R(_root, key);
     }
     
     Node* Find_R(const K& key)                //递归实现查找
     {
          return _Find_R(_root, key);
     }
     
     void Inorder()                       //递归实现中序遍历
     {
          _Inorder(_root);
     }
     
protected:
     bool _Insert_R(Node*& root, const K& key, const V& value)         //递归实现插入节点
     {
          if (root == NULL)
          {
               root = new Node(key, value);    //添加引用会更改_root
               return true;
          }
          
          if (root->_key < key)
          {
               return _Insert_R(root->_right, key, value);
          }
          else if (root->_key > key)
          {
               return _Insert_R(root->_left, key, value);
          }
          else
          {
               return false;
          }
     }
     
     Node* _Find_R(Node*& root, const K& key)                 //递归实现查找
     {
          if (root == NULL)
          {
               return NULL;
          }
          if (root->_key < key)
          {
               return _Find_R(root->_right, key);
          }
          else if (root->_key > key)
          {
               return _Find_R(root->_left, key);
          }
          else
          {
               return root;
          }
     }

     bool _Remove_R(Node*& root, const K& key)
     {
          if (root == NULL)
          {
               return false;
          }
          
          if (root->_key > key)
          {
               return _Remove_R(root->_left, key);
          }
          else if (root->_key < key)
          {
               return _Remove_R(root->_right, key);
          }
          else
          {
               Node* del = root;
               if (root->_left == NULL)
               {
                    root = root->_right;
                    delete del;
                    return true;
               }
               else if (root->_right == NULL)
               {
                    root = root->_left;
                    delete del;
                    return true;
               }
               else
               {
                    Node* firstLeft = root->_right;
                    while (firstLeft->_left)
                    {
                         firstLeft = firstLeft->_left;
                    }
                    swap(firstLeft->_key, root->_key);
                    swap(firstLeft->_value, root->_value);
                    _Remove_R(root->_right, key);
                    delete del;
                    return true;
               }
          }
          return false;
     }
     
 void _Inorder(Node* root)             //中序遍历
 {
      if (root == NULL)
      {
           return;
      }
      _Inorder(root->_left);
      cout << root->_key << " ";
      _Inorder(root->_right);
 }
 
protected:
 Node* _root;
};
时间: 2024-12-24 21:11:55

数据结构--‘搜索二叉树’的相关文章

【数据结构】搜索二叉树的(递归与非递归)实现,包括:增Insert,删Remove,查Find

搜索二叉树,是二叉树一种特殊的结构. 特点: (1)每个节点都有一个关键码,并且关键码不重复. (2)左子树上的每个节点的关键码都小于根节点的关键码. (3)右子树上的每个节点的关键码都大于根节点的关键码. (4)左右子树都是搜索二叉树. 下面,为方便大家理解,我举例画一个搜索二叉树,如下: 代码见下: #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> using namespace std; //搜索二叉树的节点结构 template&

搜索二叉树的操作

搜索二叉树的数据结构定义: /*二叉搜索树的结构定义*/ typedef struct TreeNode* SearchTree; typedef struct TreeNode* Position; struct TreeNode { int Element; SearchTree Left; SearchTree Right; } 搜索二叉树的插入操作: SearchTree Insert(int x, SearchTree T) { if(T == NULL)//空树 { T = mall

python环境下使用mysql数据及数据结构和二叉树算法(图)

python环境下使用mysql数据及数据结构和二叉树算法(图):1 python环境下使用mysql2使用的是 pymysql库3 开始-->创建connection-->获取cursor-->操作-->关闭cursor->关闭connection->结束45 代码框架6 import pymysql.cursors7 ###连接数据库8 connection = pymysql.connect(host='127.0.0.1',port=3306,user='roo

判断一个数列是不是搜索二叉树后续遍历输出的结果

剑平面阿里被问到这个,刚开始画了下看有什么性质,乱蒙了几个都被推翻了,初始感觉就是要O(n)的,因为印象中BST的构树都可以O(nlogn)搞定.然后剑平说最后一个数肯定是根节点,一下反应过来了,就是二分出间隔点然后两边递归判断,不过这好像还是构树的思路,可以把整棵树构造出来.然后剑平说不是二分,直接遍历.不科学啊,明显的二分,然后去网上搜一下,都是遍历的,O(n^2)的吧.想了想,二分是当做合法的情况来构树的,不合法怎么判断?构造出搜索二叉树后中序遍历一下不就行了么,妥妥的O(nlogn)吧.

数据结构:二叉树的链式存储

数据结构:二叉树的链式存储(C语言版) 1.写在前面 二叉树同样有两种存储方式,数组和链式存储,对于数组来说,我们利用二叉树的性质然后利用下标可以方便的找到一个节点的子节点和父节点. 二叉树的性质: 1.二叉树的第i层上至多有2i-1个节点 2.深度为K的二叉树至多有2k-1个节点 3.任何一个二叉树中度数为2的节点的个数必度数为0的节点数目少1. 说明:度数为0,为叶子节点. 4.具有n个节点的完全二叉树的深度为|_Log2N_|+1 5.若完全二叉树中的某节点编号为i,则若有左孩子编号为2i

搜索二叉树

二叉查找树(BinarySearch Tree,也叫二叉搜索树,或称二叉排序树Binary Sort Tree)或者是一棵空树,或具有如下性质: 每个节点都有一个作为搜索依据的关键码(key),所有节点的关键码互不相同. 左子树上所有节点的关键码(key)都小于根节点的关键码(key). 右子树上所有节点的关键码(key)都大于根节点的关键码(key). 左右子树都是二叉搜索树. 二叉搜索树相关操作: (1)插入:新节点 在二叉查找树中插入新结点,要保证插入新结点后仍能满足二叉查找树的性质.插入

java递归方法建立搜索二叉树,具备查找关键字,插入新节点功能

二叉排序树的定义: 二叉排序树满足以下三个性质(BST性质): <1>若它的左子树非空,则左子树上所有节点的值均小于根节点的值 <2>若它的右子树非空,则右子树上所有节点的值均大于根节点的值 <3>左,右子树本身又各是一棵二叉排序树 根据二叉排序树的BST性质,可以说二叉排序树每个节点上的值(或称关键字)都是唯一的,并且二叉排序树以中序遍历输出的结果必然是一个有序的递增序列. 如下图所示: 用递归方法建立二叉排序树,减少了繁复的比较程序,效率较高.只需要知道每个节点的值

数据结构之二叉树查找

数据结构之--二叉树查找 定义:它是一棵树,或者具有以下性质的树.  若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值: 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值:  它的左.右子树也分别为二叉排序树: 图解: ?        ?    ?    ?    ?    ?? #include<stdio.h> #include<stdlib.h> typedef int Status; #define TRUE 1 #define FALSE 0 t

数据结构之二叉树遍历

二叉树的 二叉树节点的描述 public class BiTNode { char data; BiTNode lc,rc; } 下面我们分别用递归和非递归实现前.中.后序遍历,以及使用了两种方法来进行层次遍历二叉树,一种方法就是使用STL中的queue,另外一种方法就是定义了一个数组队列,分别使用了front和rear两个数组的下标来表示入队与出队. 1.前序遍历 未完待续... 数据结构之二叉树遍历,布布扣,bubuko.com