STL源码—二叉树查找树

来源:互联网 发布:老男孩 linux 编辑:程序博客网 时间:2024/06/05 13:28

为了进一步了解RB树,先了解一下二叉查找树

定义:

二叉查找树是一棵二叉树,因此可以用链式结构来存储数据。若二叉查找树不为空,则应具有以下性质:

  1. 关键字的值唯一
  2. 若左子树不为空,则子树任何节点关键字值一定小于其根节点的关键字值
  3. 若右子树不为空,则子树任何节点关键字值一定大于其根节点的关键字值
  4. 左、右子树任然是二叉查找树
结构示意图

查找节点:

  1. 若二叉查找树为空,则查找失败
  2. 若该树非空且查找数据x等于根节点的值,则查找成功,返回根节点
  3. 若该树非空且查找数据x小于根节点的值,则查找左子树,直到值相等,并返回节点
  4. 若该树非空且查找数据x大于根节点的值,则查找右子树,直到值相等,并返回节点

插入节点:

  1. 若二叉查找树为空,则将结点作为根节点插入
  2. 若所插入节点关键字值等于根节点的值,则插入失败,并返回
  3. 若所插入节点关键字值小于根节点的值,则把节点插入到左子树中
  4. 若所插入节点关键字值大于根节点的值,则把节点插入到右子树中

删除节点:

  1. 若p结点为叶子结点,则删去该叶子结点,修改其双亲结点的指针即可。
  2. 若p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点的左子树(当p是左子树)或右子树(当p是右子树)。
  3. 若p结点的左子树和右子树均不空。找出节点p的后继节点y(一定在节点p的右子树中),以右子树中的最小数作为后继节点。

下面是实现这些功能的程序

#include<stdio.h>#include<stdlib.h>#include<malloc.h>#define LENGTH 11struct BinSearNode{int key;struct BinSearNode *left_child;struct BinSearNode *right_child;struct BinSearNode *parent;}Node;typedef struct BinSearNode *PNode;/*Search the node of the tree*/PNode Search_Tree(PNode root,int key){PNode x=root;//the tree is not empty and the key is not equalwhile(NULL!=x && x->key!=key){if(x->key<key)x=x->right_child;//along the right child of tree,until it is emptyelsex=x->left_child;//along the left child of tree,until it is empty}return x;//return the node}/*the minimum key of node in the tree*/PNode Minimum_Tree(PNode root){PNode x=root;while(NULL!=x->left_child){x=x->left_child;}return x;}/*the maxmum key of node in the tree*/PNode Maxmum_Tree(PNode root){PNode x=root;while(NULL!=x->right_child){x=x->right_child;}return x;}/*the successor node of the x,后继节点可以这么理解,将查找树从小到大排序,比他大的值如果有右孩子,那么应该是右子树当中的最小值如果没有右孩子,那么应该向上追溯,直至一个分支节点是其父节点的左孩子,返回父节点可以用于operate++*/PNode Successor_Tree(PNode x){PNode y=NULL;//case 1:the right subtree of node x is not emptyif(NULL!=x->right_child){y=Minimum_Tree(x->right_child);}//case 2:the right subtree of node x is empty//and the node of x has a successor node yelse{y=x->parent;while(NULL!=y && x==y->right_child) {x=y;y=y->parent;}}return y;}/*the predecessor node of the x,前任节点如果节点有左孩子,那么找到左孩子的最大值如果没有左孩子,那么向上追溯直至一个分支当前节点是对应父节点的右孩子,返回父节点的值*/PNode Predecessor_Tree(PNode x){PNode y=NULL;//case 1:the left subtree of node x is not emptyif(NULL!=x->left_child){y=Maxmum_Tree(x->left_child);}//case 2:the left subtree of node x is empty//and the node of x has a predecessor node yelse{y=x->parent;while(NULL!=y && x==y->left_child){x=y;y=y->parent;}}return y;}/*insert a new node into the BST*/void Insert_Tree(PNode *root,int key){PNode x=*root;PNode y=NULL;PNode z=(PNode)malloc(sizeof(Node));//<开辟一个节点的空间if(NULL==z){printf("malloc the z is failed.");exit(1);}//initial the node of zz->key=key;z->left_child=z->right_child=z->parent=NULL;//Find the location node of y to insert the node of zwhile(NULL!=x){y=x; //<找到当前树满足条件的叶子节点了,表示为y,之后在y节点后面进行插入操作if(z->key<x->key)x=x->left_child;elsex=x->right_child;}//insert the node of zz->parent=y;if(NULL==y)*root=z;//tree was emptyelse{if(z->key<y->key)y->left_child=z;elsey->right_child=z;}}void Transplant(PNode *root,PNode u,PNode v){if(NULL==u->parent)*root=v;else{if(u==u->parent->left_child)u->parent->left_child=v;elseu->parent->right_child=v;}if(NULL!=v)v->parent=u->parent;}/*delete a node in the binary search tree*/void Delete_Tree(PNode *root,int key) //<删除节点{//Find the node you want to deletePNode p=Search_Tree(*root,key);if(NULL==p->left_child)Transplant(root,p,p->right_child);else{if(NULL==p->right_child)Transplant(root,p,p->left_child);else{PNode y=Successor_Tree(*root);if(y->parent!=p){Transplant(root,y,y->right_child);y->right_child=p->right_child;y->right_child->parent=y;}Transplant(root,p,y);y->left_child=p->left_child;y->left_child->parent=y;}}}/*print the key of binary search tree*/void ioder_Tree(PNode root){if(NULL!=root){ioder_Tree(root->left_child);printf("  %d",root->key);ioder_Tree(root->right_child);}}int main()  {  int i;  int Arr[LENGTH]={16,6,20,2,7,19,22,1,4,11,8};  PNode root=NULL;  PNode p=NULL;  for(i=0;i<LENGTH;i++)  {  Insert_Tree(&root,Arr[i]);  }  ioder_Tree(root);  printf("\n");  //printf("Hello world!\n");  Delete_Tree(&root,11);  ioder_Tree(root);  printf("\n");  p=Maxmum_Tree(root);  printf("The Maxmum of node is:%d\n",p->key);  p=Minimum_Tree(root);  printf("The Minimum of node is:%d\n",p->key);  return 0;  }  

结果图:



在STL中除了要求是搜索二叉树之外,还需要是平衡搜索二叉树:

因为关联容器很重要的一个是搜索效率


平衡树有很多种比如AVL_tree,RB-tree,AA-tree

平衡二叉树插入节点和删除节点的平均时间都是比较长,但是他们可以很好的避免难以应付的最坏情况


AVL-tree要求任何节点的左右子树的高度相差最多为1

如果插入或者删除操作打破了这些平衡条件,那么这样的树应该需要做相应的旋转操作来达到平衡


RB-tree的节点有红色和黑色的区分,并有一些限制条件,之后会专门进行介绍



0 0
原创粉丝点击