定义一个二叉排序树结构:
typedef int DataType;
typedef struct BST_Node {
DataType data;
struct BST_Node *lchild, *rchild;
}BST_T, *BST_P;
建立二叉排序树,用到Insert_BST方法,在后面:
void CreateBST(BST_P *T, int a[], int n)
{
int i;
for (i = 0; i < n; i++)
{
Insert_BST(T, a[i]);
}
}
二叉排序树查找
要在二叉树中找出查找最大最小元素是极简单的事情,从根节点一直往左走,直到无路可走就可得到最小值;从根节点一直往右走,直到无路可走,就可以得到最大值。
查找最小关键字:
BST_P SearchMin(BST_P root)
{
if (root == NULL)
return NULL;
if (root->lchild == NULL)
return root;
else //一直往左孩子找,直到没有左孩子的结点
return SearchMin(root->lchild);
}
查找最大关键字:
BST_P SearchMax(BST_P root)
{
if (root == NULL)
return NULL;
if (root->rchild == NULL)
return root;
else //一直往右孩子找,直到没有右孩子的结点
return SearchMax(root->rchild);
}
递归版查找(找到返回关键字的结点指针,没找到返回NULL):
BST_P Search_BST(BST_P root, DataType key)
{
if (root == NULL)
return NULL;
if (key > root->data) //查找右子树
return Search_BST(root->rchild, key);
else if (key < root->data) //查找左子树
return Search_BST(root->lchild, key);
else
return root;
}
非递归版查找:
BST_P Search_BST(BST_P root, DataType key)
{
BST_P p = root;
while (p)
{
if (p->data == key) return p;
p = (key < p->data) ? p->lchild : p->rchild;
}
return NULL;
}
二叉排序树插入
插入新元素时,可以从根节点开始,遇键值较大者就向左,遇键值较小者就向右,一直到末端,就是插入点。
void Insert_BST(BST_P *root, DataType data)
{
//初始化插入节点
BST_P p = (BST_P)malloc(sizeof(struct BST_Node));
if (!p) return;
p->data = data;
p->lchild = p->rchild = NULL;
//空树时,直接作为根节点
if (*root == NULL)
{
*root = p;
return;
}
//是否存在,已存在则返回,不插入
if (Search_BST(root, data) != NULL) return;
//进行插入,首先找到要插入的位置的父节点
BST_P tnode = NULL, troot = *root;
while (troot)
{
tnode = troot;
troot = (data < troot->data) ? troot->lchild : troot->rchild;
}
if (data < tnode->data)
tnode->lchild = p;
else
tnode->rchild = p;
}
# 递归插入
def insertTreeNode(root, val) -> TreeNode:
if root is None:
root = TreeNode()
root.val = val
return root
elif root.val == val:
return root
elif root.val < val:
root.right = insertTreeNode(root.right, val)
return root
else:
root.left = insertTreeNode(root.left, val)
return root
return root
if __name__ == '__main__':
root = None
root = insertTreeNode(root, 2)
root = insertTreeNode(root, 1)
root = insertTreeNode(root, 1)
root = insertTreeNode(root, 4)
root = insertTreeNode(root, 5)
root = insertTreeNode(root, 3)
二叉排序树删除
简单方法
二叉树的删除操作有一个技巧, 即在查找到需要删除的节点 X; 接着我们找到要么在它的左子树中的最大元素节点 M、要么在它的右子树中的最小元素节点 M, 并交换(M,X). 此时, M 节点必然至多只有一个孩子; 最后一个步骤就是用 M 的子节点代替 M 节点就完成了. 所以, 所有的删除操作最后都会归结为删除一个至多只有一个孩子的节点, 而我们删除这个节点后, 用它的孩子替换就好了
public Node deleteNode(Node root,int a){
if(root==null)
return null;
if(root.data==a){
if(root.left==null){
return root.right;
}else if(root.right==null){
return root.left;
}else{
Node t=root.right;
while (t.left!=null){
t=t.left;
}
int b=root.data;
root.data=t.data;
t.data=b;
root.right=deleteNode(root.right,a);
}
}else if(root.data<a){
root.right=deleteNode(root.right,a);
}else{
root.left=deleteNode(root.left,a);
}
return root;
}
def deleteTreeNode(root: TreeNode, val):
if root is None:
return
if root.val == val:
if root.left is None and root.right is None:
return None
elif root.left is None:
return root.right
elif root.right is None:
return root.left
else:
replaceNode = root.right
while replaceNode.left is not None:
replaceNode = replaceNode.left
root.val, replaceNode.val = replaceNode.val, root.val
root.right = deleteTreeNode(root.right, val)
elif root.val < val:
root.right = deleteTreeNode(root.right, val)
elif root.val > val:
root.left = deleteTreeNode(root.left, val)
return root
一般方法
对于二叉排序树中的节点A,对它的删除分为两种情况:
- 如果A只有一个子节点,就直接将A的子节点连至A的父节点上,并将A删除;
- 如果A有两个子节点,我们就以右子树内的最小节点取代A,怎么得最小节点,前有有说。这个最小节点肯定没有左孩子,将右孩子赋值给它的父母
- 如果是叶子节点,直接赋值为NULL就好了
void DeleteBSTNode(BST_P *root, DataType data)
{
BST_P p = *root, parent = NULL, s = NULL;
if (!p) return;
if (p->data == data) //找到要删除的节点了
{
/* It's a leaf node */
if (!p->rchild && !p->lchild)
*root = NULL;
// 只有一个左节点
else if (!p->rchild&&p->lchild)
*root = p->lchild;
// 只有一个右节点
else if (!p->lchild&&p->rchild)
*root = p->rchild;
//左右节点都不空
else
{
s = p->rchild;
/* the s without left child */
if (!s->lchild)
s->lchild = p->lchild;
/* the s have left child */
else
{
/* find the smallest node in the left subtree of s */
while (s->lchild)
{
/* record the parent node of s */
parent = s;
s = s->lchild;
}
parent->lchild = s->rchild;
s->lchild = p->lchild;
s->rchild = p->rchild;
}
*root = s;
}
free(p);
}
else if (data > p->data) //向右找
DeleteBSTNode(&(p->rchild), data);
else if (data < p->data) //向左找
DeleteBSTNode(&(p->lchild), data);
}
二叉树遍历
void MidOrderTraverse(BST_P T)
{
if (T)
{
MidOrderTraverse(T->lchild);
cout << T->data << " ";
MidOrderTraverse(T->rchild);
}
}
void PreOrderTraverse(BST_P T)
{
if (T)
{
cout << T->data << " ";
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
void PostOrderTraverse(BST_P T)
{
if (T)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout << T->data << " ";
}
}
测试
int main()
{
int arr[] = { 17,12,19,10,15,18,25,8,11,13,16,22};
BST_P root = NULL;
//创建二叉排序树
CreateBST(&root, arr, 12);
printf("\nCreate BST: ");
printf("\npre order traverse: ");
PreOrderTraverse(root);
printf("\npost order traverse: ");
PostOrderTraverse(root);
cout << endl;
//在二叉排序树中查找节点12.
BST_P result = Search_BST(root, 12);
printf("\nSearch Data: ");
cout << "查找结果:\n" << "指针:" << result << endl << "指针的值:" << result->data << endl;
//在二叉排序树中插入9
Insert_BST(&root, 9);
printf("\nInsert Data: ");
printf("\npre order traverse: ");
PreOrderTraverse(root);
printf("\npost order traverse: ");
PostOrderTraverse(root);
cout << endl;
//删除二叉排序树中的节点12
DeleteBSTNode(&root, 12);
printf("\nDelete Data: ");
printf("\npre order traverse: ");
PreOrderTraverse(root);
printf("\npost order traverse: ");
PostOrderTraverse(root);
printf("\n");
}
自己复习又写一遍的全部代码
#include<algorithm>
#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<queue>
using namespace std;
struct t
{
int data;
t *left, *right;
t():left(NULL),right(NULL){
}
t(int d) :data(d),left(NULL), right(NULL){
}
};
t* searchMin(t *root) {
if (root == NULL) {
return NULL;
}
if (root->left == NULL) {
return root;
}
else {
return searchMin(root->left);
}
}
t* searchMax(t *root) {
if (root == NULL) {
return NULL;
}
if (root->right == NULL) {
return root;
}
else {
return searchMax(root->right);
}
}
t* searchKey(t *root, int key) {
if (root == NULL) {
return NULL;
}
if (root->data == key) {
return root;
}
if (key>root->data) {
searchKey(root->right, key);
}
else {
searchKey(root->left, key);
}
}
t* searchKey1(t *root, int key) {
if (root == NULL) {
return NULL;
}
t *p = root;
while (p) {
if (p->data == key) {
return p;
}
if (key > p->data) {
p = p->right;
}
else {
p = p->left;
}
}
return NULL;
}
void insertNode(t *&root, int data);
t* createTree(vector<int> v) {
t *root =NULL;
for (int i = 0; i < v.size(); i++) {
insertNode(root, v[i]);
}
return root;
}
void insertNode(t *&root, int data) {
t *p = new t(data);
if (root == NULL) {
root = p;
return;
}
//找它的父节点
if (searchKey(root, data)) {
//里面有这个节点就别插了
return;
}
t *father = NULL;
t *t1 = root;
while (t1) {
father = t1;
t1 = data > t1->data ? t1->right : t1->left;
}
if (data > father->data)
father->right = p;
else
father->left = p;
//while
}
void deleteNode(t *&root, int data) {
if (root == NULL) {
return;
}
if (root->data == data) {
if (root->left == NULL && root->right == NULL) {
root = NULL;
}else if (root->left == NULL &&root->right!=NULL) {
root = root->right;
}else if (root->right == NULL && root->left != NULL) {
root = root->left;
}
else {
if (!root->right->left) {
t *p = root;
root->right->left = root->left;
root = root->right;
delete p;
}
else {
t *t2, *t3=NULL;
t2 = root->right;
while (t2->left) {
t3 = t2;
t2 = t2->left;
}
t3->left = t2->right;
t2->left = root->left;
t2->right = root->right;
t *p = root;
root = t2;
delete p;
}
}
}
else if (data > root->data) {
deleteNode(root->right, data);
}
else if (data < root->data) {
deleteNode(root->left, data);
}
}
void visitlvr(t *root) {
if (root != NULL) {
visitlvr(root->left);
cout << root->data << " ";
visitlvr(root->right);
}
}
void visitvlr(t *root) {
if (root != NULL) {
cout << root->data << " ";
visitvlr(root->left);
visitvlr(root->right);
}
}
void visitlrv(t *root) {
if (root != NULL) {
visitlrv(root->left);
visitlrv(root->right);
cout << root->data << " ";
}
}
void visitTree(t *tree) {
visitlvr(tree);
cout << endl;
visitvlr(tree);
cout << endl;
visitlrv(tree);
cout << endl;
}
int main() {
freopen("D:/in.txt", "r", stdin);
vector<int> v;
int n;
cin >> n;
for (int i = 0; i < n; i++) {
int a;
cin >> a;
v.push_back(a);
}
t* tree=createTree(v);
visitTree(tree);
deleteNode(tree, 7);
visitTree(tree);
return 0;
}
floor()
floor(key):小于等于键的最大键
如果键小于根节点的键,那么 floor(key) 一定在左子树中;
如果键大于根节点的键,需要先判断右子树中是否存在 floor(key),如果存在就找到,否则根节点就是 floor(key)。
public Key floor(Key key) {
Node x = floor(root, key);
if (x == null)
return null;
return x.key;
}
private Node floor(Node x, Key key) {
if (x == null)
return null;
int cmp = key.compareTo(x.key);
if (cmp == 0)
return x;
if (cmp < 0)
return floor(x.left, key);
Node t = floor(x.right, key);
return t != null ? t : x;
}
rank()
rank(key) 返回 key 的排名。
如果键和根节点的键相等,返回左子树的节点数;
如果小于,递归计算在左子树中的排名;
如果大于,递归计算在右子树中的排名,并加上左子树的节点数,再加上 1(根节点)。
@Override
public int rank(Key key) {
return rank(key, root);
}
private int rank(Key key, Node x) {
if (x == null)
return 0;
int cmp = key.compareTo(x.key);
if (cmp == 0)
return size(x.left);
else if (cmp < 0)
return rank(key, x.left);
else
return 1 + size(x.left) + rank(key, x.right);
}
deleteMin()
令指向最小节点的链接指向最小节点的右子树。
public void deleteMin() {
root = deleteMin(root);
}
public Node deleteMin(Node x) {
if (x.left == null)
return x.right;
x.left = deleteMin(x.left);
recalculateSize(x);
return x;
}