算法笔记之二叉查找树(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.练习
[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; }
相关文章推荐
- 二叉查找树 算法导论笔记
- 算法(第四版)学习笔记之java实现二叉查找树
- 算法复习笔记-BST
- 数据结构和算法分析学习笔记(三)--二叉查找树的懒惰删除(lazy deletion)
- 《算法》笔记-3.2二叉查找树(2)
- 算法练习笔记(九)——BST树的改正
- 算法系列笔记3(二叉查找树)
- 【C++研发面试笔记】9. 基本数据结构-二叉查找树BST
- 算法笔记:二叉搜索树BST
- 查找、检索 算法-总结2 二叉查找树 [BST]
- 数据结构&算法学习笔记 二叉查找树
- 算法笔记_053:最优二叉查找树(Java)
- 【算法】数据结构与算法分析学习笔记——各类二叉查找树的吐血整理
- 二叉查找树(binary search tree (BST))--算法导论示例
- 最优二叉查找树详解(算法导论学习笔记)
- 二叉查找树(binary search tree (BST))--算法导论示例
- java——二叉查找树(BST)算法
- 从一段简单算法题来谈二叉查找树(BST)的基础算法
- 算法练习笔记(七)——在BST树中的遍历
- 【算法笔记】数据结构(一)