二叉搜索树基本操作
2016-02-19 22:47
453 查看
#include <cstdio> #include <cstdlib> #include <queue> #include <stack> //查找值这类不修改原数据的行为,则用pnode,要插入,删除,建树,则用pnode* 指向指针的指针 typedef struct searchtree{ int key; struct searchtree *lchild; //左孩子指针 //注意这里指向该结构的指针还是要用原名字定义 struct searchtree *rchild; //右孩子指针 struct searchtree *parent; //指向父节点指针 }node, *pnode; //往二叉查找树中插入结点 //插入的话,可能要改变根结点的地址,所以传的是二级指针 void insert_node(pnode *root, int key) //指向指针的指针 { //初始化插入结点 pnode p = (pnode)malloc(sizeof(node)); p->key = key; p->lchild = p->rchild = p->parent = NULL; //空树时,直接作为根结点 if((*root) == NULL) { (*root) = p; return ; } //插入到当前结点(*root)的左孩子 if((*root)->lchild == NULL && (*root)->key > key) { p->parent = (*root); (*root)->lchild = p; return ; } //插入到当前结点(*root)的右孩子 if((*root)->rchild == NULL && (*root)->key < key) { p->parent = (*root); (*root)->rchild = p; return ; } if((*root)->key > key) insert_node(&(*root)->lchild, key); else if((*root)->key <key) insert_node(&(*root)->rchild, key); else //等于的话就不插入 return ; } //查找元素,找到返回关键字的结点指针,没找到返回NULL pnode searchnode(pnode root, int key) { if(root == NULL) return NULL; //没找到返回NULL if(key < root->key) return searchnode(root->lchild,key); else if(key > root->key) return searchnode(root->rchild,key); else return root; } //查找最小关键字,空树时返回NULL pnode searchmin(pnode root) { pnode p = root; if(p == NULL) return NULL; else { while(p->lchild) p = p->lchild; } return p; /* if(root == NULL) return NULL; if(root->lchild == NULL) return root; else //一直往左孩子找,直到没有左孩子的结点 return searchmin(root->lchild);*/ } //查找最大关键字,空树时返回NULL pnode searchmax(pnode root) { pnode p = root; if(p == NULL) return NULL; else { while(p->rchild != NULL) p = p->rchild; } return p; /* if(root == NULL) return NULL; if(root->rchild == NULL) return root; else //一直往右孩子找,直到没有右孩子的结点 return searchmax(root->rchild);*/ } //查找某个结点的前驱 pnode searchpredecessor(pnode p) { //空树 if(p == NULL) return NULL; //有左子树、左子树中最大的那个 if(p->lchild != NULL) return searchmax(p->lchild); //无左子树,查找某个结点的右子树遍历完了 else { if(p->parent == NULL) return NULL; //向上寻找前驱 while(p) { if(p->parent->rchild == p) break; p = p->parent; } return p->parent; } } //查找某个结点的后继 pnode searchsuccessor(pnode p) { if(p == NULL) return NULL; if(p->rchild) //有右子树、右子树中最小的那个 return searchmin(p->rchild); else //无右子树,查找某个结点的左子树遍历完了 { if(p->parent == NULL) retur c5e5 n NULL; //向上寻找后继 while(p) { if(p->parent->lchild == p) break; p = p->parent; } return p->parent; } } //根据关键字删除某个结点,删除成功返回1,否则返回0 //如果把根结点删掉,那么要改变根结点的地址,所以传二级指针 int deletenode(pnode *root, int key) //pnode *是指向指针的指针 { //查找到要删除的结点 pnode p = searchnode((*root),key); if(!p) return 0; //1.被删除点是叶子结点,直接删除 if(p->lchild == NULL && p->rchild == NULL) { //只有一个元素,删完之后变成一颗空树 if(p->parent == NULL) //本身就是根节点 { free(p); (*root) = NULL; } else { //删除的结点是父节点的左孩子 if(p->parent->lchild == p) p->parent->lchild = NULL; //删除的结点是父节点的右孩子 if(p->parent->rchild == p) p->parent->rchild = NULL; free(p); } } //2.被删结点只有左子树 else if(p->lchild && !(p->rchild)) { p->lchild->parent = p->parent; //先改左孩子的parent指针 if(p->parent == NULL) //如果删除是根结点 (*root) = p->lchild; //左孩子升级成为根节点 //删除的结点是父节点的左孩子 //再改父亲节点的parent指针 else if(p->parent->lchild == p) p->parent->lchild = p->lchild; //删除的结点是父节点的右孩子 else if(p->parent->rchild == p) p->parent->rchild = p->lchild; free(p); //以免类存泄露 } //3.被删结点只有右孩子 else if(p->rchild && !(p->lchild)) { p->rchild->parent = p->parent; if(p->parent == NULL) (*root) = p->rchild; //删除的结点是父节点的左孩子 else if(p->parent->lchild == p) p->parent->lchild = p->rchild; //删除的结点是父节点的右孩子 else if(p->parent->rchild == p) p->parent->rchild = p->rchild; free(p); } //4.被删除的结点既有左孩子,又有右孩子 //该结点的后继结点肯定无左子树(参考上面查找后继结点函数) //删掉后继结点,后继结点的值代替该结点 else {//找到要删除结点的后继 pnode q; int tmp; //存后继结点的值 q = searchsuccessor(p); tmp = q->key; //删除后继结点 deletenode(root, tmp); p->key = tmp; } return 1; } //创建二叉搜索树 void creatsearchtree(pnode *root, int *key, int length) { //逐个结点插入二叉树中 for(int i = 0; i < length; i++) insert_node(root, key[i]); //root本身就是二级指针了,直接传root } int main() { pnode root = NULL; //这里的root是一级指针 int key[11] = {15,6,18,3,7,17,20,2,4,13,9}; creatsearchtree(&root, key, 11); for(int i = 0; i < 2; i++) deletenode(&root, key[i]); printf("%d\n", searchpredecessor(root)->key); printf("%d\n", searchsuccessor(root)->key); printf("%d\n", searchmin(root)->key); printf("%d\n", searchmax(root)->key); printf("%d\n", searchnode(root, 13)->key); printf("\n//////////////////////////////////\n"); int n ; printf("Other search is same with searchnode, \nso I only display the search of searchnode \n"); while(scanf("%d", &n)!=EOF) searchnode(root, n) ? printf("yes, the searchtree has %d\n", n) : printf("sorry ! Do have this node !\n"); return 0; } /* 例子 of deletenode函数 一: O x / \ NULL NULL O / O x / \ NULL NULL O \ O x / \ NULL NULL 二: O x / O O / \ x O O / O / \ O O O / \ O O x / O / \ O O 三: O x \ O O / \ x O O \ O / \ O O O / \ O O x \ O / \ O O */
相关文章推荐
- 关于研究Java中GlassPane的心得
- Android Studio中的EditText控件使用详解
- 查看google chrome和firefox上的cookie
- 定制化Azure站点Java运行环境(4)
- Hotel(线段树合并)
- centos下面安装php开发环境
- 二叉树基本操作(完整版)
- 正则pattern和matcher
- 机器学习博士
- 最小生成树的两种方法
- poj2774 后缀数组
- Spark应用开发如何设定配置生效
- Unity3d热更新 从AssetBundle说起
- 算法竞赛入门经典(第二版)-刘汝佳-第四章 函数与递归 例题+习题(15/16)
- 矢量化的HTML5拓扑图形组件设计
- IDEA ant连接ftp报错NoClassDefFoundError
- 几种常用加密算法比较
- 程序员必备素质-团队
- 运算符重载之 []
- (18)[AppWidget]