二叉搜索树可进行查询,插入,删除操作,不是平衡树,平均时间复杂度O(logN),还可到达O(N)
ACM竞赛也不大常用二叉搜索树,PAT还是常考
实现方法:指针和数组
指针:除了数据结构学习时,竞赛很少用到指针实现
法一:基于C++类封装实现
#include "stdafx.h"
#include <cstdio>
#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
class BST {
private:
int data;
BST *left,*right;
public:
BST(int te):data(te),left(NULL),right(NULL){}
static void insert(BST *&root,int te) {
if (root == NULL) {
root = new BST(te);
}
else if(te < root->data){
insert(root->left, te);
}
else {
insert(root->right, te);
}
}
BST *const &findMin() {
return this->left == NULL ? this : this->left->findMin();
}
void deletes(BST *&root,int te) {
if (root == NULL) {
return;
}
else if (te < root->data) {
deletes(root->left, te);
}
else if (te > root->data) {
deletes(root->right, te);
}
else if (root->left && root->right) {
BST * const t = root->right->findMin();
root->data = t->data;
deletes(root->right, t->data);
}
else {
BST *t = root;
if (root->left == NULL) {
root = root->right;
}
else {
root = root->left;
}
delete t;
}
}
void postOrder() {//后序遍历
if (this->left) {
this->left->postOrder();
}
if (this->right) {
this->right->postOrder();
}
cout << " " << this->data;
}
void dispose() {//递归释放内存
if (this->left) {
this->left->dispose();
}
if (this->right) {
this->right->dispose();
}
delete this;
}
};
int main() {
BST *root = NULL;
int n,te;
cin >> n;//6
for (int i = 0; i < n; i++) {//7 6 11 8 12 13
cin >> te;
BST::insert(root, te);
}
if (root != NULL) {
root->postOrder();
}
cout << endl;
if (root != NULL) {
root->deletes(root,11);
}
if (root != NULL) {
root->postOrder();
}
cout << endl;
if (root != NULL) {
root->dispose();
}
return 0;
}
感觉以上不符合C++的封装规则,又改了一下
#include "stdafx.h"
#include <cstdio>
#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
class treeNode {
private:
int data;
treeNode *left, *right;
public:
treeNode(int te):data(te),left(NULL),right(NULL){}
treeNode *&findMin(treeNode *&root, int te) {
if (root->left == NULL) {
return root;
}
else
return findMin(root->left, te);
}
treeNode *find(treeNode *root,int te) {
if (root == NULL || root->data == te) {
return root;
}
return te < root->data ? find(root->left, te) : find(root->right, te);
}
static void insert(treeNode *&root, int te) {
if (root == NULL) {
root = new treeNode(te);
return;
}
else if (te < root->data) {
insert(root->left, te);
}
else if(te > root->data){
insert(root->right, te);
}
else if (te == root->data) {
cerr << "ERROR" << endl;
}
}
void deletes(treeNode *&root, int te) {
if (root == NULL) {
cerr << "ERROR" << endl;
return;
}
else if (te < root->data) {
deletes(root->left, te);
}
else if (te > root->data) {
deletes(root->right, te);
}
else if(root->left && root->right){
treeNode *&p = findMin(root->right, te);
root->data = p->data;
deletes(root->right, root->data);
}
else {
treeNode *t = root;
root = root->left == NULL ? root->right : root->left;
delete t;
}
}
void postOrder(treeNode *&root) {
if (root == NULL) {
return;
}
postOrder(root->left);
postOrder(root->right);
cout << " " << root->data;
}
void disPosal(treeNode *&root) {
if (root->left) {
disPosal(root->left);
}
if (root->right) {
disPosal(root->right);
}
delete root;
}
};
class BST {
private:
treeNode *root;
public:
BST() :root(NULL) {}
void add(int te) {
treeNode::insert(root, te);
}
void remove(int te) {
if (root == NULL) {
cerr << "ERROR" << endl;
return;
}
root->deletes(root,te);
}
treeNode *query(int te) {
if (root == NULL) {
cerr << "ERROR" << endl;
return NULL;
}
return root->find(root, te);
}
void postOrder() {
if (root == NULL) {
cerr << "ERROR" << endl;
return;
}
root->postOrder(root);
}
void disPosal() {
if (root == NULL) {
return;
}
root->disPosal(root);
}
};
int main() {
int n, te;
BST bst;
cin >> n;//6
for (int i = 0; i < n; i++) {//7 6 11 8 12 13
cin >> te;
bst.add(te);
}
bst.postOrder();
cout << endl;
bst.remove(11);
bst.postOrder();
cout << endl;
bst.disPosal();
return 0;
}
法二:普通指针实现
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//插入和删除函数必须都得以返回指针的形式实现
//对于插入,看其最后的NULL时插入就能看出
//对于删除,本质删除的是只有一个儿子和没有儿子的节点,想其删除没有儿子的节点的情况
//若不返回指针,此节点的父亲就有个指针指向非法区了
struct TreeNode{
int Element;
struct TreeNode* Left;
struct TreeNode* Right;
};
struct TreeNode* Init(){//初始化
return NULL;
}
void PreTraversal(struct TreeNode* BinSearchTree)//前序遍历
{
if(BinSearchTree!=NULL){
printf("%d ",BinSearchTree->Element);
PreTraversal(BinSearchTree->Left);
PreTraversal(BinSearchTree->Right);
}
return;
}
struct TreeNode* Find(int data,struct TreeNode* BinSearchTree)//查找
{
if(BinSearchTree==NULL)
return NULL;
else if(BinSearchTree->Left!=NULL&&data<BinSearchTree->Element)
return BinSearchTree->Left;
else if(BinSearchTree->Right!=NULL&&data>BinSearchTree->Element)
return BinSearchTree->Right;
else
return BinSearchTree;
}
struct TreeNode* FindMax(struct TreeNode* BinSearchTree)//查找最大值所在的节点
{
if(BinSearchTree==NULL)
return NULL;
else if(BinSearchTree->Right!=NULL)
return FindMax(BinSearchTree->Right);
else
return BinSearchTree;
}
struct TreeNode* FindMin(struct TreeNode* BinSearchTree)//查找最小值所在的节点
{
if(BinSearchTree==NULL)
return NULL;
else if(BinSearchTree->Left!=NULL)
return FindMin(BinSearchTree->Left);
else
return BinSearchTree;
}
struct TreeNode* Insert(int data,struct TreeNode* BinSearchTree)//插入
{
if(BinSearchTree==NULL){
BinSearchTree=(struct TreeNode*)malloc(sizeof(struct TreeNode));
BinSearchTree->Element=data;
BinSearchTree->Left=NULL;
BinSearchTree->Right=NULL;
return BinSearchTree;
}
else if(data<BinSearchTree->Element)
BinSearchTree->Left=Insert(data,BinSearchTree->Left);
else if(data>BinSearchTree->Element)
BinSearchTree->Right=Insert(data,BinSearchTree->Right);
else
printf("ERROR\n");
return BinSearchTree;
}
struct TreeNode* Delete(int data,struct TreeNode* BinSearchTree)//删除
{
if(BinSearchTree==NULL)
return NULL;
else if(data>BinSearchTree->Element)
BinSearchTree->Right=Delete(data,BinSearchTree->Right);
else if(data<BinSearchTree->Element)
BinSearchTree->Left=Delete(data,BinSearchTree->Left);
else if(BinSearchTree->Left&&BinSearchTree->Right){//删除有两个孩子的节点,可找左树最大与右树最小代替其,本质删除没有儿子的节点
struct TreeNode* Temp=FindMin(BinSearchTree->Right);
BinSearchTree->Element=Temp->Element;
BinSearchTree->Right=Delete(Temp->Element,BinSearchTree->Right);
}
else{//删除有一个/零个孩子的节点
struct TreeNode* Temp;
Temp=BinSearchTree;
if(BinSearchTree->Left!=NULL)
BinSearchTree=BinSearchTree->Left;
else//此处包含了右儿子也为空的情况,即零个孩子
BinSearchTree=BinSearchTree->Right;
free(Temp);
}
return BinSearchTree;
}
int main(){
struct TreeNode* BinSearchTree;
//初始化
BinSearchTree=Init();
//插入
BinSearchTree=Insert(4,BinSearchTree);
BinSearchTree=Insert(3,BinSearchTree);
BinSearchTree=Insert(6,BinSearchTree);
BinSearchTree=Insert(5,BinSearchTree);
BinSearchTree=Insert(7,BinSearchTree);
BinSearchTree=Insert(2,BinSearchTree);
//遍历一遍,便于检验代码
PreTraversal(BinSearchTree);
putchar('\n');
//删除有零个孩子的2节点
BinSearchTree=Delete(2,BinSearchTree);
PreTraversal(BinSearchTree);
putchar('\n');
//重新插入2
BinSearchTree=Insert(2,BinSearchTree);
//删除有一个孩子的3节点
Delete(3,BinSearchTree);
PreTraversal(BinSearchTree);
putchar('\n');
//删除有两个孩子的6节点
Delete(6,BinSearchTree);
PreTraversal(BinSearchTree);
putchar('\n');
}
数组实现:
法一:基于C++类封装实现
#include "stdafx.h"
#include <cstdio>
#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
#include <queue>
using namespace std;
#define MAXN 100005
class BST {
private:
int len,root;
int data[MAXN], left[MAXN], right[MAXN], book[MAXN];
public:
BST(int te) :len(te),root(-1){
memset(left, -1, sizeof(left));
memset(right, -1,sizeof(right));
memset(book, 0, sizeof(book));
}
void insert(int &root, int i) {//执行插入操作
if (root == -1) {
root = i;
return;
}
if (data[i] < data[root]) {
insert(left[root], i);
}
else {
insert(right[root], i);
}
}
void buildTree() {//建树
for (int i = 0; i < len; i++) {
cin >> data[i];
book[i] = 1;
insert(root, i);
}
}
int query(int te) {//查询当前值的下标
for (int i = 0; i < len; i++) {
if (book[i] && data[i] == te) {
return i;
}
}
return -1;
}
void add(int te) {//增添数据
if (query(te) != -1) {
return;
}
data[len++] = te;
insert(root, len-1);
}
int findMin(int i) {//查找当前节点以及其子树的最小值的下标
if (left[i] == -1) {
return i;
}
return findMin(left[i]);
}
void deletes(int &root, int te) {//执行删除操作
if (root == -1) {
return;
}
else if (te < data[root]) {
deletes(left[root], te);
}
else if (te > data[root]) {
deletes(right[root], te);
}
else if(left[root] != -1 && right[root] != -1){
int index = findMin(right[root]);
data[root] = data[index];
deletes(right[root], data[root]);
}
else {
root = left[root] == -1?right[root]:left[root];
book[root] = 0;
}
}
void remove(int te) {//删除数据
deletes(root, te);
}
void levelOrder() {//层序遍历
queue<int> q;
q.push(root);
while (!q.empty()) {
int t = q.front();
cout << " " << data[t];
q.pop();
if (left[t] != -1) {
q.push(left[t]);
}
if (right[t] != -1) {
q.push(right[t]);
}
}
cout << endl;
}
};
int main() {
int te,n;
BST *tree;
while (scanf("%d", &n) != EOF) {
tree = new BST(n);
tree->buildTree();
tree->add(3);
tree->remove(3);
tree->levelOrder();
delete tree;
}
return 0;
}
法二:普通实现
#include "stdafx.h"
#include <cstdio>
#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
#include <queue>
using namespace std;
#define MAXN 100005
int data[MAXN], left[MAXN], right[MAXN],book[MAXN];
int root, len;
void insert(int &root, int i) {
if (root == -1) {
root = i;
return;
}
if (::data[i] < ::data[root]) {
insert(::left[root], i);
}
else {
insert(::right[root], i);
}
}
int findMin(int root) {
if (::book[root] && ::left[root] == -1) {
return root;
}
return findMin(::left[root]);
}
void deletes(int &root, int te) {
if (root == -1) {
return;
}
else if (te < ::data[root]) {
deletes(::left[root], te);
}
else if (te > ::data[root]) {
deletes(::right[root], te);
}
else if (::left[root] != -1 && ::right[root] != -1) {
int index = findMin(::right[root]);
::data[root] = ::data[index];
deletes(::right[root], ::data[root]);
}
else {
root = ::left[root] == -1 ? ::right[root]: ::left[root];
::book[root] = 0;
}
}
void levelOrder() {
queue<int> q;
q.push(root);
while (!q.empty()) {
int t = q.front();
q.pop();
cout << " " << ::data[t];
if (::left[t] != -1) {
q.push(::left[t]);
}
if (::right[t] != -1) {
q.push(::right[t]);
}
}
cout << endl;
}
int main() {
int te;
while (scanf("%d", &len) != EOF) {
root = -1;
memset(::left, -1, sizeof(::left));
memset(::right, -1, sizeof(::right));
memset(::book, 0, sizeof(::book));
for (int i = 0; i < len; i++) {
cin >> ::data[i];
::book[i] = 1;
insert(root, i);
}
::data[len++] = 4;
insert(root, len - 1);
deletes(root, 4);
levelOrder();
}
return 0;
}