二叉搜索树

来源:互联网 发布:php linux 编辑:程序博客网 时间:2024/06/05 20:37

二叉搜索树可进行查询,插入,删除操作,不是平衡树,平均时间复杂度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;//6for (int i = 0; i < n; i++) {//7 6 11 8 12 13cin >> 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;}elsereturn 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;//6for (int i = 0; i < n; i++) {//7 6 11 8 12 13cin >> 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 100005class 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 100005int 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;}