二叉搜索树的基本功能实现

来源:互联网 发布:nosql数据库的优势 编辑:程序博客网 时间:2024/06/06 16:34

     

        二叉查找树(Binary Search Tree),又被称为二叉搜索树。设x为二叉查找树中的一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] <= key[x];如果y是x的右子树的一个结点,则key[y] >= key[x]。



在二叉查找树中:
(01) 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(02) 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(03) 任意节点的左、右子树也分别为二叉查找树。
(04) 没有键值相等的节点(no duplicate nodes)。

在实际应用中,二叉查找树的使用比较多。下面,用C语言实现二叉查找树。

我在网上查到的一位大神写的加上我自己总结的,一起分享给大家

*二叉搜索树中的节点类  *Node.h  */  # ifndef _NODE_  #define _NODE_  class Node  {  private:      int value;/*节点中存放的元素值*/      Node *parentNode;/*所指向的父节点指针*/      Node *leftChildNode;/*左孩子节点指针*/      Node *rightChildNode;/*右孩子节点指针*/  public:      Node(int v);/*初始化函数*/      Node* getParentNode();/*返回父节点指针*/      Node* getLeftChildNode();/*返回左孩子节点指针*/      Node* getRightChildNode();/*返回右孩子节点指针*/      int getValue();/*返回节点元素值*/      void setParentNode(Node *p);/*设定父节点指针*/      void setLeftChildNode(Node *left);/*设定左孩子节点*/      void setRightChildNode(Node *right);/*设定右孩子结点*/      void setValue(int v);/*设定节点元素值*/  };  #endif  


/*  *Node.cpp  */  #include "Node.h"  #include <cstdio> //NULL    /*初始化函数*/  Node::Node(int r)  {      setValue(r);      setParentNode(NULL);      setLeftChildNode(NULL);      setRightChildNode(NULL);  }  /*返回父节点指针*/  Node* Node::getParentNode()  {      return parentNode;  }  /*返回右孩子节点指针*/  Node* Node::getRightChildNode()  {      return rightChildNode;  }  /*返回左孩子节点指针*/  Node* Node::getLeftChildNode()  {      return leftChildNode;  }  /*返回节点元素值*/  int Node::getValue()  {      return value;  }  /*设定左孩子节点*/  void Node::setLeftChildNode(Node *left)  {      leftChildNode = left;  }  /*设定父节点指针*/  void Node::setParentNode(Node *parent)  {      parentNode = parent;  }  /*设定右孩子结点*/  void Node::setRightChildNode(Node *right)  {      rightChildNode = right;  }  /*设定节点元素值*/  void Node::setValue(int v)  {      value = v;  }  

/*二叉搜索树类:  *BinarySearchTree.h  */  #ifndef _BINARYSEARCHTREE_  #define _BINARYSEARCHTREE_  #define MAXLENGTH 100 //二叉搜索树的最大节点总数  #include "Node.h"  class BinarySearchTree  {  private:      Node *rootNode;/*根节点指针*/  public:      BinarySearchTree();/*构造函数初始化*/      void setRootNode(Node *root);/*设置根节点*/      void treeInsert(int v);/*向搜索数中添加节点*/      void levelTreeWalk(Node *start);/*层次遍历*/      void inorderTreeWalk(Node *start);/*中序遍历*/      void preorderTreeWalk(Node *start);/*先序遍历*/      void postorderTreeWalk(Node *start);/*后序遍历*/      void transplant(Node *u,Node *v);/*将节点v替换到u的位置,并且相应子树进行转换*/      bool deleteNode(Node *point);/*从搜索树中删除节点point*/      bool max(int x,int y);/*比较两个整型元素值大小,x<y返回false*/      int getNodeNumber(Node *start);/*得到以start为根的树的节点总数*/      int getTreeHeight();/*计算二叉搜索树的高度*/      int getNodeHeight(Node *start);/*计算节点start的高度*/      Node* getRootNode();/*得到根节点指针*/      Node* getMinimum(Node *start);/*得到以start节点为根的搜索数中的具有最小元素值的节点*/      Node* treeMax(Node *start);//递归版本的得到具有最大元素值的节点      Node* getMaximum(Node *start);/*得到以start为根节点的搜索数中的具有最大元素值的节点*/      Node* getTreeSuccessor(Node *start);/*得到节点start的后继节点*/      Node* getTreePredessor(Node *start);/*得到start的前驱节点*/      Node* treeSearch2(Node *start,int k);/*迭代版本*/      Node* treeSearch1(Node *start,int k);/*搜索数的查找,如果k存在于搜索树中,                                            (从树根开始查找,)则返回给节点,否则返回null*/  };  #endif  

/*  *BinarySearchTree.cpp  */  #include "BinarySearchTree.h"  #include <cstdio>  #include <iostream>  using namespace std;    /*构造函数初始化*/  BinarySearchTree::BinarySearchTree()  {      setRootNode(NULL);  }  /*得到根节点指针*/  Node* BinarySearchTree::getRootNode()  {      return rootNode;  }  /*设置根节点*/  void BinarySearchTree::setRootNode(Node *root)  {      rootNode = root;  }    /*向搜索数中添加节点,输入是新的节点元素值*/  void BinarySearchTree::treeInsert(int v)  {      /*新的插入的节点*/      Node *newInsertNode = new Node(v);      Node *y = NULL;      Node *x = getRootNode();//得到根节点      /*通过while循环中元素比较得到新的节点的合适位置*/      while(x!=NULL)      {          y = x;          if(v < x->getValue())    /*二叉搜索树的性质:x.left.value<x.value;*/              x = x->getLeftChildNode();          else                             /*x.right.value>=x.values*/              x = x->getRightChildNode();      }      //y = newInsertNode;      if(y == NULL)//二叉搜索树为空的情况          setRootNode(newInsertNode);      else if(v < y->getValue())      {          y->setLeftChildNode(newInsertNode);          newInsertNode->setParentNode(y);      }      else      {          y->setRightChildNode(newInsertNode);          newInsertNode->setParentNode(y);      }  }    /*从搜索树中删除节点point,如果删除成功,返回true,                                        如果是空子树,返回false*/  /*1、point没有左右子孩子,直接删除point  *2、point没有左孩子的情况,直接删除point并把右孩子放到原来point位置         上面两种情况可以归为一类情况:没有左孩子,将右孩子放到point位置    3、只有左孩子情况,把左孩子放到point位置,删除point    4、左右孩子都有的情况:查找point节点的后继节点successor          1、如果successor为point右孩子(既然为point右孩子,则successsor没有左孩子)             将point左孩子作为successor左孩子,successor替换point,删除point节点         2、如果successor不是point的右孩子(是以point右孩子为根节点的子树最小值所在节点             且没有左孩子)将successor右节点sright作为successor所在子树根节点,并将point             右孩子节点pright作为successor右节点,successor左孩子节点pleft作为successor             左孩子节点,删除point,,,  */  bool BinarySearchTree::deleteNode(Node *point)  {      /*搜索树为空或point为空时进行的操作*/      if(point == NULL || getRootNode() == NULL)          return false;      /*如果节点point不再搜索树中*/      if(treeSearch1(getRootNode(),point->getValue()) == NULL)          return false;      /*下面的就是讨论的三种情况:*************************/      /*1、point的左孩子节点为空*/      if(point->getLeftChildNode() == NULL)          transplant(point,point->getRightChildNode());      /*2、point的右孩子节点为空*/      else if(point->getRightChildNode() == NULL)          transplant(point,point->getLeftChildNode());      /*3、point的左右孩子节点均不为空*/      else      {          /*得到point的后继节点*/          Node *successor = getMinimum(point->getRightChildNode());          /*当successor不为point的右孩子节点时进行的操作*/          if(successor->getParentNode() != point)          {              transplant(successor,successor->getRightChildNode());              successor->setRightChildNode(point->getRightChildNode());              successor->getRightChildNode()->setParentNode(successor);          }          transplant(point,successor);          successor->setLeftChildNode(point->getLeftChildNode());          successor->getLeftChildNode()->setParentNode(successor);      }      delete point;      return true;  }  /*此时u节点右节点为空,v节点左孩子为空,将u的左孩子节点放到v的左孩子节点处    并把u的父节点作为v的父节点,即删除u节点    此函数的作用是将u的父节点作为v的父节点,v作为u的父节点的原u位置相应子节点  v可以为空节点,也可以不是,对于u的左孩子节点的处理,由这个函数的调用者进行  处理 */  void BinarySearchTree::transplant(Node *u,Node *v)  {      if(u->getParentNode() == NULL)          setRootNode(v);      else if(u == u->getParentNode()->getLeftChildNode())          u->getParentNode()->setLeftChildNode(v);      else          u->getParentNode()->setRightChildNode(v);      if(v != NULL)          v->setParentNode(u->getParentNode());  }    /*得到以start节点为根的搜索数中的具有最小元素值的节点*/  /*while迭代版本:*/  Node* BinarySearchTree::getMinimum(Node *start)  {      Node *minNode = start;      if(minNode == NULL)//空树的情况          return minNode;      while(minNode->getLeftChildNode() != NULL)      {          minNode = minNode->getLeftChildNode();      }      return minNode;  }  /*得到以start为根节点的搜索数中的具有最大元素值的节点*/  /*递归版本:*/  Node* BinarySearchTree::getMaximum(Node *start)  {      return treeMax(start);  }  Node* BinarySearchTree::treeMax(Node *start)  {      if(start == NULL)          return NULL;      else if(start->getRightChildNode() == NULL)          return start;      else          return treeMax(start->getRightChildNode());  }    /*得到以start为根的树的节点总数*/  int BinarySearchTree::getNodeNumber(Node *start)  {      if(start == NULL)          return 0;      if(start->getLeftChildNode() ==NULL)          return getNodeNumber(start->getRightChildNode()) + 1;      if(start->getRightChildNode() == NULL)          return getNodeNumber(start->getLeftChildNode()) + 1;      return getNodeNumber(start->getLeftChildNode()) +           getNodeNumber(start->getRightChildNode()) + 1;  }  /*层次遍历*/  void BinarySearchTree::levelTreeWalk(Node *start)  {      if(start == NULL)      {          cout << "这是一个空子树," << endl;          return;      }      /*定义一个数组来存放层次遍历过程中的节点指针,最大为MAXLENGTH*/      Node *B[MAXLENGTH + 1];      B[1] = start;/*根节点放到B[1]处*/      int nodeNumber = getNodeNumber(start);/*树中节点个数*/      int counter = 1;//已经放到数组B中的节点个数      int k = 1;/*在之后的每次循环中,counter之前有k个节点需要得到子节点放入数组B*/      int m,i;//寄存器值      while(counter < nodeNumber)      {          m = 0;          /*循环得到counter之前的k个节点它们的子节点*/          for(i = 1;i <= k;i ++)//k其实就是每一层中的节点个数          {              if(B[counter-k+i]->getLeftChildNode() != NULL)              {                  m ++;                  B[counter + m] = B[counter-k+i]->getLeftChildNode();              }              if(B[counter-k+i]->getRightChildNode() != NULL)              {                  m ++;                  B[counter + m] = B[counter-k+i]->getRightChildNode();              }          }          k = m;          counter = counter + k;      }      for(i = 1;i <= nodeNumber;i++)          cout << B[i]->getValue() << " ";  }  /*中序遍历:<<<<左根右>>>>*/  void BinarySearchTree::inorderTreeWalk(Node *start)  {      if(start != NULL)      {          inorderTreeWalk(start->getLeftChildNode());          cout << start->getValue() << " ";          inorderTreeWalk(start->getRightChildNode());      }  }  /*先序遍历:<<<<根左右>>>>*/  void BinarySearchTree::preorderTreeWalk(Node *start)  {      if(start != NULL)      {          cout << start->getValue() << " ";          preorderTreeWalk(start->getLeftChildNode());          preorderTreeWalk(start->getRightChildNode());      }  }  /*后序遍历:<<<<左右根>>>>*/  void BinarySearchTree::postorderTreeWalk(Node *start)  {      if(start != NULL)      {          preorderTreeWalk(start->getLeftChildNode());          preorderTreeWalk(start->getRightChildNode());          cout << start->getValue() << " ";      }  }    /*计算二叉搜索树的高度*/  int BinarySearchTree::getTreeHeight()  {      return getNodeHeight(getRootNode()) - 1;  }  /*计算节点start的高度*/  int BinarySearchTree::getNodeHeight(Node *start)  {      if(start == NULL)          return 0;      int leftChildLength = getNodeHeight(start->getLeftChildNode());      int rightChildLength = getNodeHeight(start->getRightChildNode());            /*这两个判断语句是把递归进行到二叉树的叶子节点进行判断并把        叶子节点的高度(本来为0)加一*/      if(max(leftChildLength,rightChildLength))          return leftChildLength + 1;      else          return rightChildLength + 1;  }  /*比较两个整型元素值大小,x<y返回false,x>=y返回true*/  bool BinarySearchTree::max(int x,int y)  {      if(x >= y)          return true;      else          return false;  }    /*得到节点start的后继节点,如果后继节点存在,则返回,    如果后继节点为自身,则返回null*/  Node* BinarySearchTree::getTreeSuccessor(Node *start)  {      if(start->getRightChildNode() != NULL)          return getMinimum(start->getRightChildNode());      Node *y = start->getParentNode();//叶子节点的情况      /*仍是二叉搜索树的性质决定*/      while(y != NULL && start == y->getRightChildNode ())      {          start = y;          y = y->getParentNode();      }      return y;  }  /*得到start的前驱节点如果前驱节点存在,则返回,如果前驱节点    为自身,则返回null*/  Node* BinarySearchTree::getTreePredessor(Node *start)  {      if(start->getLeftChildNode() != NULL)          return getMaximum(start->getLeftChildNode());      Node *y = start->getParentNode();      while(y != NULL && start == y->getRightChildNode())      {          start = y;          y = y->getParentNode();      }      return y;  }    /*搜索数的查找,如果k存在于搜索树中,则返回给节点,否则返回null*/  Node* BinarySearchTree::treeSearch1(Node *start,int k)  {      Node *temp = start;      if(temp == NULL || k == temp->getValue())          return temp;      if(k < start->getValue())          return treeSearch1(temp->getLeftChildNode(),k);      else          return treeSearch1(temp->getRightChildNode(),k);  }  /*搜索的while迭代版本*/  Node* BinarySearchTree::treeSearch2(Node *start,int k)  {      Node *temp = start;      while(temp != NULL && k != temp->getValue())      {          if(k < temp->getValue())              temp = temp->getLeftChildNode();          else               temp = temp->getRightChildNode();      }      return temp;  }            


0 0