二叉排序树的构造及其基本操作
二叉排序树的定义
对于一棵空的二叉树或者具有如下性质的二叉树:
1.若其左子树不为空,则左子树所有结点的值均小于根结点的值。
2.若其右子树不为空,则右子树所有结点的值均大于根结点的值。
3.其左右子树也是二叉排序树。
如:
相关图片来源《数据结构——从概念到C++实现(第三版)》
二叉排序树中对值的查找
给定一个值p,当前结点为bt,若bt->data==p,查找成功。
若pdata,则在pt左子树查找。
若p>bt->data,则在pt右子树查找。
BiNode* BiSortTree::SearchBST(BiNode* bt, datatype x)
{if (bt == NULL) return NULL;if (bt->data == x)return bt;else if (bt->data > x)return SearchBST(bt->lchild, x);else return SearchBST(bt->rchild, x);
}
插入
当root为空时直接插入。
若root不为空,模拟查找的过程找到其该插入的位置,然后插入。
BiNode* BiSortTree::InsertBST(BiNode* bt, datatype x)
{if (bt == NULL){BiNode* s = new BiNode;s->data = x;s->lchild = s->rchild = NULL;bt = s;return bt;}else if (bt->data > x){if (bt->lchild == NULL)bt->lchild = InsertBST(bt->lchild, x);else InsertBST(bt->lchild, x);}else{if (bt->rchild == NULL)bt->rchild = InsertBST(bt->rchild, x);else InsertBST(bt->rchild, x);}
}
二叉排序树的创建
其实就是一个不断插入的过程。
BiSortTree::BiSortTree(int a[], int n)
{root = NULL;for (int i = 0;i < n;i++){if (i == 0) root = InsertBST(root, a[i]);//在插入操作时,当root节点为空时分配根节点空间,并且root的地址不会改变。else InsertBST(root, a[i]);}
}
删除
1.当删除的结点是叶子结点,直接删除即可。
下图中需要删除的结点为p所指,f为其双亲结点。
2.被删除的结点只有左子树或右子树,让当前结点的左孩子或右孩子(不为空的那个)指向其左孩子或右孩子的儿子。
3.被删除的结点既有左子树又有右子树,找到左子树的最大值,与当前要删除的结点替换值,并删除之前找到的左子树的最大值。
有一个特殊情况,当左子树中的最大值结点是被删除结点的孩子。
但我们还需要解决一个问题,如果想要实现上述过程我们需要找到需要删除的结点以及需要删除结点的父亲。
在此我用一个find函数找到所要删除结点的父亲。
BiNode* BiSortTree::find(BiNode* root,const datatype key)
{fa = NULL;BiNode* cur = root;while (cur != NULL && cur->data != key){fa = cur;if (key > cur->data)cur = cur->rchild;else cur = cur->lchild;}if (cur == NULL)return NULL;return cur;
}
并且对于所删除的结点是不是根结点的情况(此时father为NULL)需要特判一下,具体见代码。
void BiSortTree::DeleteBST(datatype x)
{BiNode* p = find(x);if ((p->lchild == NULL) && (p->rchild == NULL)){if (fa == NULL);else if (fa->lchild == p)fa->lchild = NULL;else if (fa->rchild == p)fa->rchild = NULL;delete p;return;}if (p->rchild == NULL){if (fa == NULL){root = p->lchild;delete p;return; }else{if (fa->lchild == p)fa->lchild = p->lchild;else if (fa->rchild == p)fa->rchild = p->lchild;delete p;return;}}if (p->lchild == NULL){if (fa == NULL){root = p->rchild;delete p;return;}else{if (fa->lchild == p)fa->lchild = p->rchild;else if (fa->rchild == p)fa->rchild = p->rchild;delete p;return;}}BiNode* par = p, * s = p->lchild;while (s->rchild != NULL){par = s;s = s->rchild;}if (par->lchild == s)par->lchild = NULL;if (par->rchild == s)par->rchild = NULL;p->data = s->data;if (par == p)par->lchild = s->lchild;else par->rchild = s->lchild;delete s;
}
以下的操作对于二叉树同样适用
二叉排序树的前中后序的递归遍历
其实就是输出根结点的位置为前中后。
void BiSortTree::PreOrder(BiNode* bt)
{if (bt == NULL)return;else{cout << bt->data << endl;PreOrder(bt->lchild);PreOrder(bt->rchild);}
}void BiSortTree::InOrder(BiNode* bt)
{if (bt == NULL)return;else{PreOrder(bt->lchild);cout << bt->data << endl;PreOrder(bt->rchild);}
}void BiSortTree::PostOrder(BiNode* bt)
{if (bt == NULL)return;else{PreOrder(bt->lchild);PreOrder(bt->rchild);cout << bt->data << endl;}
}
二叉排序树的非递归前序遍历
首先我们需要一个栈,先将root入栈,然后出栈(此时出的就是root)输出,如果有右结点则入右结点,有左节点则入左节点,注意顺序,因为是前序遍历所以让右结点先入左结点后入,这样会保证左结点先出栈,循环直到栈空。
void BiSortTree::IterativePreorder()
{BiNode* stack[Max];int top = -1;if (root == NULL)return;stack[++top] = root;while (top!=-1){BiNode* p = stack[top];cout << p->data << endl;top--;if (p->rchild != NULL)stack[++top] = p->rchild;if (p->lchild != NULL)stack[++top] = p->lchild;}
}
二叉排序树的层序遍历
需要用到一个队列,先将根结点入队。然后将队列中的队首元素(这时就是根结点)出队、输出,再把当前出队结点的左右子节点压入队列(如果左右结点不为空的话),循环直到队列为空。
void BiSortTree::LevelOrder()
{BiNode* Q[Max], * q = NULL;int front = -1, rear = -1;if (root == NULL) return;Q[++rear] = root;while (front != rear){q = Q[++front];cout << q->data << endl;if (q->lchild != NULL)Q[++rear] = q->lchild;if (q->rchild != NULL)Q[++rear] = q->rchild;}
}
求二叉排序树的高度
DFS,先一直往左走直到尽头,再跳回往右,把所有路径遍历一遍比较得出最大的高度。
int h=0,ht=0;
void BiSortTree::get_high(BiNode* bt)
{ht++;if (bt == NULL)return;if (bt->lchild == NULL && bt->rchild == NULL){h = max(h, ht);return;}get_high(bt->lchild);ht--;get_high(bt->rchild);ht--;
}
求二叉排序树度为0、度为1、度为2的结点的个数
DFS将二叉树遍历一遍,看其左右结点是否为空逐一记录各度的结点数。
void BiSortTree::get_node(BiNode* bt)
{if (bt->lchild != NULL && bt->rchild != NULL){d2++;get_node(bt->lchild);get_node(bt->rchild);}else if (bt->lchild!=NULL){d1++;get_node(bt->lchild);}else if (bt->rchild != NULL){d1++;get_node(bt->rchild);}else{d0++;return;}
}
Code
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
#include<memory.h>
#include<cmath>
#include<queue>
#define pii pair<int,int>
#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
typedef char datatype;
const int Max = 1e3 + 5;
int h=0,ht=0, d1=0, d2=0, d0=0;class BiSortTree
{public:BiSortTree(int a[], int n);//~BiSortTree() { Release(root); }BiNode* InsertBST(datatype x) { return InsertBST(root, x); }void DeleteBST(datatype x);BiNode* SearchBST(datatype x) { return SearchBST(root, x); }BiNode* find(const datatype key) { return find(root, key); }void PreOrder() { PreOrder(root); }void InOrder() { InOrder(root); }void PostOrder() { PostOrder(root); }void LevelOrder();void get_high() { h = 0;get_high(root); }void get_node() { d0 = d1 = d2 = 0;get_node(root); }void get_width();
private:BiNode* InsertBST(BiNode* bt, datatype x);BiNode* SearchBST(BiNode* bt, datatype x);BiNode* find(BiNode* root, const datatype key);void get_high(BiNode* bt);void get_node(BiNode* bt);void Release(BiNode* bt);void PreOrder(BiNode* bt);void InOrder(BiNode* bt);void PostOrder(BiNode* bt);BiNode* root;
};BiNode* BiSortTree::SearchBST(BiNode* bt, datatype x)
{if (bt == NULL) return NULL;if (bt->data == x)return bt;else if (bt->data > x)return SearchBST(bt->lchild, x);else return SearchBST(bt->rchild, x);
}BiNode* BiSortTree::InsertBST(BiNode* bt, datatype x)
{if (bt == NULL){BiNode* s = new BiNode;s->data = x;s->lchild = s->rchild = NULL;bt = s;return bt;}else if (bt->data > x){if (bt->lchild == NULL)bt->lchild = InsertBST(bt->lchild, x);else InsertBST(bt->lchild, x);}else{if (bt->rchild == NULL)bt->rchild = InsertBST(bt->rchild, x);else InsertBST(bt->rchild, x);}
}BiSortTree::BiSortTree(int a[], int n)
{root = NULL;for (int i = 0;i < n;i++){if (i == 0) root = InsertBST(root, a[i]);//在插入操作时,当root节点为空时分配根节点空间,并且root的地址不会改变。else InsertBST(root, a[i]);}
}BiNode* BiSortTree::find(BiNode* root,const datatype key)
{fa = NULL;BiNode* cur = root;while (cur != NULL && cur->data != key){fa = cur;if (key > cur->data)cur = cur->rchild;else cur = cur->lchild;}if (cur == NULL)return NULL;return cur;
}void BiSortTree::DeleteBST(datatype x)
{BiNode* p = find(x);if ((p->lchild == NULL) && (p->rchild == NULL)){if (fa == NULL);else if (fa->lchild == p)fa->lchild = NULL;else if (fa->rchild == p)fa->rchild = NULL;delete p;return;}if (p->rchild == NULL){if (fa == NULL){root = p->lchild;delete p;return; }else{if (fa->lchild == p)fa->lchild = p->lchild;else if (fa->rchild == p)fa->rchild = p->lchild;delete p;return;}}if (p->lchild == NULL){if (fa == NULL){root = p->rchild;delete p;return;}else{if (fa->lchild == p)fa->lchild = p->rchild;else if (fa->rchild == p)fa->rchild = p->rchild;delete p;return;}}BiNode* par = p, * s = p->lchild;while (s->rchild != NULL){par = s;s = s->rchild;}if (par->lchild == s)par->lchild = NULL;if (par->rchild == s)par->rchild = NULL;p->data = s->data;if (par == p)par->lchild = s->lchild;else par->rchild = s->lchild;delete s;
}void BiSortTree::get_node(BiNode* bt)
{if (bt->lchild != NULL && bt->rchild != NULL){d2++;get_node(bt->lchild);get_node(bt->rchild);}else if (bt->lchild != NULL){d1++;get_node(bt->lchild);}else if (bt->rchild != NULL){d1++;get_node(bt->rchild);}else{d0++;return;}
}void BiSortTree::get_high(BiNode* bt)
{ht++;if (bt == NULL)return;if (bt->lchild == NULL && bt->rchild == NULL){h = max(h, ht);return;}get_high(bt->lchild);ht--;get_high(bt->rchild);ht--;
}void BiSortTree::PreOrder(BiNode* bt)
{if (bt == NULL)return;else{cout << bt->data << endl;PreOrder(bt->lchild);PreOrder(bt->rchild);}
}void BiSortTree::InOrder(BiNode* bt)
{if (bt == NULL)return;else{PreOrder(bt->lchild);cout << bt->data << endl;PreOrder(bt->rchild);}
}void BiSortTree::PostOrder(BiNode* bt)
{if (bt == NULL)return;else{PreOrder(bt->lchild);PreOrder(bt->rchild);cout << bt->data << endl;}
}void BiSortTree::LevelOrder()
{BiNode* Q[Max], * q = NULL;int front = -1, rear = -1;if (root == NULL) return;Q[++rear] = root;while (front != rear){q = Q[++front];cout << q->data << endl;if (q->lchild != NULL)Q[++rear] = q->lchild;if (q->rchild != NULL)Q[++rear] = q->rchild;}
}
码字不易给个赞吧QAQ~
二叉排序树的构造及其基本操作相关推荐
- 二叉排序树的定义及基本操作(构造、查找、插入、删除)递归及非递归算法
文章目录 二叉排序树的定义 二叉排序树的查找 二叉排序树的插入 二叉排序树的构造 二叉排序树的删除 完整代码及实例 二叉排序树的查找效率 二叉排序树的定义 二叉排序树(Binary Sort Tree ...
- 二叉排序树(BST)构造与应用
二叉排序树(BST)构造与应用 本文取自<数据结构与算法>(C语言版)(第三版).出版社是清华大学出版社. 本博文作为学习资料整理. 源码是VC+ ...
- 二叉树的构造以及基本操作
*二叉树的构造以及基本操作: 二叉树的构造基本思想:循环遍历一段字符串,遇到"(" 就将父结点入指针栈(数组指针),并将变量k置为1,表示接下来构建的是左子树,遇到",& ...
- 二叉排序树、平衡二叉树、红黑树、B树、B+树
全民制作人们,大家好.我是练习时长两天半的个人练习册,喜欢B树 ,B+树, BST树, AVL树,来 red black ~ 目录 一.二叉排序树(BST树) 1.1二叉排序树的定义 1.2二叉排序 ...
- 【swjtu】数据结构实验8_平衡二叉排序树
实验内容及要求: 从键盘输入若干两两互不相同的非0整数,直到输入0时停止.将输入的所有非0整数按输入次序插入二叉排序树来构造平衡的二叉排序树.输出平衡的二叉排序树的先序和中序递归遍历次序:按中序递归遍 ...
- 【数据结构-树】3.详解二叉排序树(理论+代码)
二叉排序树 二叉排序树的定义 二叉排序树也称为二叉查找树.二叉排序树或者是一棵空树,或者是一棵具有如下特性的非空为茶树 若左子树非空,则左子树所有结点关键字值均小于根结点的关键字值 若右子树非空,则右 ...
- 数据结构之树和二叉树的应用:二叉排序树(BST)
树和二叉树的应用:二叉排序树 思维导图: 二叉排序树的定义: 二叉排序树节点结构: 二叉排序树的查找: 二叉排序树的插入: 二叉排序树的构造: 二叉排序树的删除: 二叉排序树先删除再插入某个相同值的节 ...
- 二叉排序树和平衡二叉树
二叉排序树 定义 二叉排序树或者是空树,或者是满足以下性质的二叉树: 1)左子树不为空,则左子树上所有关键字的值均小于根关键字的值. 2)右子树不为空,则右子树上所有关键字的值均大于根关键字的值. 3 ...
- C语言实现二叉排序树
1.二叉排序树的定义 二叉排序树,又称二叉查找数树,一颗二叉树或者是空二叉树,或者是具有如下性质的二叉树: a.左子树上所有结点的关键字均小于根结点的关键字: b.右子树上所有结点的关键字竣大雨根结点 ...
最新文章
- 福利 | Python、深度学习、机器学习、TensorFlow 好书推荐
- SolidWorks学习笔记4特征
- python数据库连接池工具类_Python数据库连接池DBUtils
- View结合组策略进行应用程序下发
- Flink SQL Client注册Python UDF完整流程
- [转]软件测试的完整分类
- 通过Rancher安装K8s
- sql 数据检索后的替换格式化
- OpenCL+minGW64+windows8.1 enviroment
- python 函数中参数的传递方式(三分钟读懂)
- linux系统各种日志存储路径和详细介绍
- 解决wordpress后台管理访问速度慢的问题
- matlab三角波发生器精度改为定点型,关于matlab simulink中三角波模块的问题!
- VS Code 的插件位置更改
- 还在用 Random?试试 ThreadLocalRandom,好用!
- 华为eSight网管平台折腾
- oracle没有卸载,oracle卸载没有正确卸载怎么办??
- MTR和WinMTR的下载和使用
- vue3使用useMouseInElement实现图片局部放大预览效果
- Intraweb之EasyUI篇
热门文章
- 拼多多商品详情API调用示例
- Fortran学习5:数组2
- 【Hash函数与生日攻击】
- SmartFlow测试LAN-LAN/WAN throughput
- Disruptor以及@Contended注解
- [春秋云镜wp]CVE-2022-28060 CVE-2022-26201 Victor CMS v1.0存在sql注入漏洞复现拿flag
- 【论文代码阅读】LORA: LOW-RANK ADAPTATION OF LARGE LAN- GUAGE MODELS
- 易语言专治反截图程序源码
- win7系统安装过程,usb鼠标键盘不能使用,无法点击下一步
- 怎么选最快dns服务器,如何可以选择适合自己的最快的DNS服务器?