您的位置:首页 > 其它

算法笔记之二叉查找树(BST)

2018-11-27 23:05 99 查看

1.基本操作

 

                                                       1.1查找与插入操作

[code]// 树的结构体
struct Node{
int number;
Node* Lchild;
Node* Rchild;
}node;

// 查询二叉树的一系列操作

// 查找
Node* findElement(Node * root, int x){
if(root == NULL) return NULL;
if(root->number == x){
return root;
}
else if(root->number > x){
findElement(root->Lchild, x);
}
else{
findElement(root->Rchild, x);
}
}

// 插入,注意形参里面的引用
bool insertElement(Node* &root, int x){
if(root == NULL){ // 结点不存在即插入位置, 用root来连接
root = new Node;
root->number = x;
root->Lchild = root->Rchild = NULL;
return true;
}
if(root->number == x){ // 值已存在
return false;
}
else if(root->number > x){
insertElement(root->Lchild, x);
}
else{
insertElement(root->Rchild, x);
}
}

 

                                            1.2 前序,中序,后序遍历树

对BST中序遍历可以得到一个有序数组,由BST的性值可以看出。

[code]//  分别为前序,中序,后序遍历
void preOrder(Node* root){
if(root == NULL) return;
else{
printf("%d ", root->number);
preOrder(root->Lchild);
preOrder(root->Rchild);
}
}

void inOrder(Node* root){
if(root == NULL) return;
else{
inOrder(root->Lchild);
printf("%d ", root->number);
inOrder(root->Rchild);
}
}

void postOrder(Node* root){
if(root == NULL) return;
else{
postOrder(root->Lchild);
postOrder(root->Rchild);
printf("%d ", root->number);
}
}

 

                                                     1.3 BST的删除操作

如果要删除根节点50 ,那么其替代节点必需合适,能满足BST的定义,可以用23号节点(左子树最大的节点),54号节点(右子树最小节点)。

 

[code]//寻找最大值
Node* findMax(Node* root){
while(root->Rchild != NULL){
root = root->Rchild;
}
return root;
}

//寻找最小值
Node* findMin(Node* root){
while(root->Lchild != NULL){
root = root->Lchild;
}
return root;
}

// 删除元素
void deleteElement(Node* &root, int x){
if(root == NULL) return;
if(root->number == x){ // 当节点值为删除值时
//节点为叶子节点,直接删除
if(root->Lchild == NULL && root->Rchild == NULL){
free(root);
root = NULL;
}
// 节点左子树存在,则找左子树的最大值来替代
else if(root->Lchild != NULL){
Node* pre = findMax(root->Lchild);
root->number = pre->number;
deleteElement(root->Lchild, pre->number); // 递归删除左子树
}
// 节点右子树存在,则找右子树的最小值来替代
else if(root->Rchild != NULL){
Node* next = findMin(root->Rchild);
root->number = next->number;
deleteElement(root->Rchild, next->number);
}
}
else if(root->number > x){ // 当节点值大于X,在左子树中寻找
deleteElement(root->Lchild, x);
}
else{ // 当节点值小于X,在右子树中寻找
deleteElement(root->Rchild, x);
}
}

 

                       

                                                                2.练习

 

                                                                                     问题 A: 二叉排序树

 

 

 

[code]#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
struct Node{
int number;
Node* Lchild;
Node* Rchild;
}node;

/* 查找二叉树的一系列基本操作 */

// 查找
Node* findElement(Node * root, int x){
if(root == NULL) return NULL;
if(root->number == x){
return root;
}
else if(root->number > x){
findElement(root->Lchild, x);
}
else{
findElement(root->Rchild, x);
}
}

// 插入,注意形参里面的引用
bool insertElement(Node* &root, int x){
if(root == NULL){ // 结点不存在即插入位置, 用root来连接
root = new Node;
root->number = x;
root->Lchild = root->Rchild = NULL;
return true;
}
if(root->number == x){
return false;
}
else if(root->number > x){
insertElement(root->Lchild, x);
}
else{
insertElement(root->Rchild, x);
}
}

// 前中后次序遍历
void preOrder(Node* root){
if(root == NULL) return;
else{
printf("%d ", root->number);
preOrder(root->Lchild);
preOrder(root->Rchild);
}
}

void inOrder(Node* root){
if(root == NULL) return;
else{
inOrder(root->Lchild);
printf("%d ", root->number);
inOrder(root->Rchild);
}
}

void postOrder(Node* root){
if(root == NULL) return;
else{
postOrder(root->Lchild);
postOrder(root->Rchild);
printf("%d ", root->number);
}
}

// 删除结点, 要先引入两个寻找结点前驱和后继
Node* findPre(Node* root){
Node* now = root->Lchild;
while(now->Rchild != NULL){
now = now->Rchild;
}
return now;
}

Node* findPost(Node* root){
Node* now = root->Rchild;
while(now->Lchild != NULL){
now = now->Lchild;
}
return now;
}

void deleteElement(Node* &root, int x){
if(root == NULL) return;
if(root->number == x){
if(root->Lchild == NULL && root->Rchild == NULL){ // 为叶子结点,直接删除
free(root);
root = NULL;
}
else if(root->Lchild != NULL){
Node* now = findPre(root);
root->number = now->number; // 将前驱结点的值赋给要删除结点
deleteElement(root->Lchild, now->number); // 递归删除
}
else{ // 同上
Node* now = findPost(root);
root->number = now->number;
deleteElement(root->Rchild, now->number);
}
}
else if(root->number > x){
deleteElement(root->Lchild, x);
}
else{
deleteElement(root->Rchild, x);
}
}

int main(){
int N, number;
while(scanf("%d", &N) != EOF){
scanf("%d", &number);
Node* root = new Node;
root->number = number;
root->Lchild = root->Rchild = NULL;
for(int i = 1; i < N; ++i){ // 依次插入
scanf("%d", &number);
insertElement(root, number);
}
preOrder(root); // 前序
printf("\n");
inOrder(root); // 中序
printf("\n");
postOrder(root); // 后序
printf("\n");
}
return 0;
}

 

 

                                                                      1043 Is It a Binary Search Tree (25 分)

 

注意:其中对MBST遍历的处理,如其中序遍历为依次遍历右子树,根节点,左子树。还有就是可以直接比较两个vector是否相等。

 

[code]#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<vector>
using namespace std;
//记录BST的前序,后序,镜像BST的前序,后序
vector<int> preOrder, preOrderM, origin, postOrder, postOrderM;
struct Node{
int number;
Node* Lchild;
Node* Rchild;
}node;

// 插入结点
bool insertElement(Node* &root, int x){
if(root == NULL){ // 结点不存在即插入位置, 用root来连接
root = new Node;
root->number = x;
root->Lchild = root->Rchild = NULL;
return true;
}
else if(root->number > x){
insertElement(root->Lchild, x);
}
else{
insertElement(root->Rchild, x);
}
}

//BST和镜像BST的前序,注意镜像BST要交换左右子树
void preOrderBST(Node* root){
if(root == NULL) return;
else{
preOrder.push_back(root->number);
preOrderBST(root->Lchild);
preOrderBST(root->Rchild);
}
}

void preOrderMBST(Node* root){
if(root == NULL) return;
else{
preOrderM.push_back(root->number);
preOrderMBST(root->Rchild);
preOrderMBST(root->Lchild);
}
}

//BST和镜像BST和后序遍历
void postOrderBST(Node* root){
if(root == NULL) return;
else{
postOrderBST(root->Lchild);
postOrderBST(root->Rchild);
postOrder.push_back(root->number);
}
};

void postOrderMBST(Node* root){
if(root == NULL) return;
else{
postOrderMBST(root->Rchild);
postOrderMBST(root->Lchild);
postOrderM.push_back(root->number);
}
}

int main(){
int N, data;
Node* root = NULL;
scanf("%d", &N);
for(int i = 0; i < N; ++i){
scanf("%d", &data);
origin.push_back(data);
insertElement(root, data);
}
//分别对BST和镜像BST进行前序,后序遍历
preOrderBST(root);
preOrderMBST(root);
postOrderBST(root);
postOrderMBST(root);
if(origin == preOrder){ // 与BST前序相同时
printf("YES\n");
for(int i = 0; i < postOrder.size(); ++i){
printf("%d", postOrder[i]);
if(i < postOrder.size() - 1) printf(" ");
}
}
else if(origin == preOrderM){ // 与镜像BST前序相同时
printf("YES\n");
for(int i = 0; i < postOrderM.size(); ++i){
printf("%d", postOrderM[i]);
if(i < postOrderM.size() - 1) printf(" ");
}
}
else{
printf("NO\n");
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: