KBinsTree.h
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:8k
源码类别:

模拟服务器

开发平台:

C/C++

  1. /* 二叉搜索树
  2. */
  3. #ifndef BINARY_SEARCH_TREE_CLASS
  4. #define BINARY_SEARCH_TREE_CLASS
  5. #include <stdlib.h>
  6. #include "KBinTreeNode.h"
  7. template <class T>
  8. class BinSTree
  9. {
  10.     private:
  11.         // 指向树根及当前结点的指针
  12.         TreeNode<T> *root;
  13.         TreeNode<T> *current;
  14.         
  15.         // 树中数据项个数
  16.         int size;
  17.       
  18.         // 用于复制构造函数及赋值运算符
  19.         TreeNode<T> *CopyTree(TreeNode<T> *t);
  20.         
  21.         // 用于析构函数,赋值运算符及 ClearList 方法
  22.         void DeleteTree(TreeNode<T> *t);
  23.         // 在函数 Find 和 Delete 中用来定位结点及其双亲在树中的位置
  24.         TreeNode<T> *FindNode(const T& item, TreeNode<T>* & parent) const;
  25.     public:
  26.         // 构造函数,析构函数
  27.         BinSTree(void);
  28.         BinSTree(const BinSTree<T>& tree);
  29.         ~BinSTree(void);
  30.         
  31.         // 赋值运算符
  32.         BinSTree<T>& operator= (const BinSTree<T>& rhs);
  33.         
  34.         // 标准的表处理方法
  35.         bool Find(T& item);
  36.         void Insert(const T& item);
  37.         void Delete(const T& item);
  38.         void ClearList(void);
  39.         bool ListEmpty(void) const;
  40.         int ListSize(void) const;
  41.         
  42.         // 树的特殊方法
  43.         void Update(const T& item);
  44.         TreeNode<T> *GetRoot(void) const;
  45. };
  46. // 复制树 t 并使其存储在当前对象中
  47. template <class T>
  48. TreeNode<T> *BinSTree<T>::CopyTree(TreeNode<T> *t)
  49. {
  50.     TreeNode<T> *newlptr, *newrptr, *newNode;
  51.    
  52.     // 如果树分支为空,返回 NULL
  53.     if (t == NULL)
  54.         return NULL;
  55.         
  56.     // 复制树 t 的左子树并将其根分配给 newlptr
  57.     if (t->left != NULL) 
  58.         newlptr = CopyTree(t->left);
  59.     else
  60.         newlptr = NULL;
  61.  
  62.     // 复制树 t 的右子树并将其根分配给 newrptr
  63.     if (t->right != NULL) 
  64.         newrptr = CopyTree(t->right);
  65.     else
  66.         newrptr = NULL;
  67.  
  68.     // 为当前根结点分配存储器并将其数据值和指针分配给它的子树,返回其指针
  69.     newNode = new TreeNode<T>(t->data, newlptr, newrptr);
  70.     return newNode;
  71. }
  72. // 删除当前对象存储的树
  73. template <class T>
  74. void BinSTree<T>::DeleteTree(TreeNode<T> *t)
  75. {
  76.     if (t != NULL)
  77.     {
  78.         DeleteTree(t->left);
  79.         DeleteTree(t->right);
  80.         delete t;
  81.     }
  82. }
  83. // 在树中搜索数据项,若找到,则返回结点地址及指向其双亲的指针;否则,返回 NULL
  84. template <class T>
  85. TreeNode<T> *BinSTree<T>::FindNode(const T& item, TreeNode<T>* & parent) const
  86. {   
  87.     // 用指针 t 从根开始遍历树
  88.     TreeNode<T> *t = root;
  89.     
  90.     // 根的双亲为 NULL
  91.     parent = NULL;
  92.     
  93.     // 若子树为空,则循环结束
  94.     while(t != NULL)
  95.     {
  96.         // 若找到键值,则退出
  97.         if (item == t->data)
  98.             break;
  99.         else 
  100.         {
  101.             // 修改双亲指针,并移到左子树或右子树
  102.             parent = t;
  103.             if (item < t->data)
  104.                 t = t->left;
  105.             else 
  106.                 t = t->right;
  107.         }
  108.     }
  109.     
  110.     // 返回指向结点的指针;若没找到,则返回 NULL
  111.     return t;
  112. }
  113. // 构造函数,初始化 root,current 为空,size 为 0
  114. template <class T>
  115. BinSTree<T>::BinSTree(void):root(NULL), current(NULL), size(0)
  116. {}
  117. // 复制构造函数
  118. template <class T>
  119. BinSTree<T>::BinSTree(const BinSTree<T>& tree)
  120. {
  121.     // 将 tree 复制到当前对象,分配 current 和 size
  122.     root = CopyTree(tree.root);
  123.     current = root;
  124.     size = tree.size;
  125. }
  126. // 析构函数
  127. template <class T>
  128. BinSTree<T>::~BinSTree(void)
  129. {
  130.     ClearList();
  131. }
  132. // 删除树中的所有结点
  133. template <class T>
  134. void BinSTree<T>::ClearList(void)
  135. {
  136.     DeleteTree(root);
  137.     root = current = NULL;
  138.     size = 0;
  139. }
  140. // 赋值运算符
  141. template <class T>
  142. BinSTree<T>& BinSTree<T>::operator= (const BinSTree<T>& rhs)
  143. {
  144.     // 不能将树复制到自身
  145.     if (this == &rhs)
  146.         return *this;
  147.         
  148.     // 清除当前树,将新树复制到当前对象
  149.     ClearList();
  150.     root = CopyTree(rhs.root);
  151.     
  152.     // 将 current 指针指向 root 并设置树的 size 值
  153.     current = root;
  154.     size = rhs.size;
  155.     
  156.     // 返回当前对象的指针
  157.     return *this;
  158. }
  159. // 在树中搜索 item,若找到,则将结点数据赋给 item
  160. template <class T>
  161. bool BinSTree<T>::Find(T& item)
  162. {
  163.     // 使用 FindNode,它需要 parent 参数
  164.     TreeNode<T> *parent;
  165.     // 在树中搜索 item,将匹配的结点赋给 current
  166.     current = FindNode(item, parent);
  167.     
  168.     // 若找到,则将数据赋给 item 并返回 True
  169.     if (current != NULL)
  170.     {
  171.         item = current->data;
  172.         return true;
  173.     }
  174.     else
  175.      // 在树中没找到 item,返回 False
  176.         return false;
  177. }
  178. // 指示树是否为空
  179. template <class T>
  180. bool BinSTree<T>::ListEmpty(void) const
  181. {
  182.     return (size == 0);
  183. }
  184. // 返回树中的数据项个数
  185. template <class T>
  186. int BinSTree<T>::ListSize(void) const
  187. {
  188.     return size;
  189. }
  190. // 往查找树中插入数据项,若元素重复,则更新现有元素
  191. template <class T>
  192. void BinSTree<T>::Insert(const T& item)
  193. {
  194.     // t 为遍历过程中的当前结点,parent 为前一结点
  195.     TreeNode<T> *parent = NULL;
  196. current = FindNode(item, parent);
  197.     
  198. if (current != NULL)
  199. current->data = item;
  200. else
  201. {
  202. // 创建新的叶子结点
  203. TreeNode<T> *newNode = new TreeNode<T>(item,NULL,NULL);
  204. // 若 parent 为 NULL,则将其作为根结点插入
  205. if (parent == NULL)
  206. root = newNode;
  207.         
  208. // 若 item < parent->data,则将其作为左孩子插入        
  209. else if (item < parent->data)                   
  210. parent->left = newNode;
  211.         
  212. else
  213. // 若 item >= parent->data,作为右孩子插入     
  214. parent->right = newNode;
  215.         
  216. // current 赋值为新结点的地址并将 size 加 1
  217. current = newNode;
  218. size++;
  219. }
  220. }
  221. // 如果 item 在树中,将其删除
  222. template <class T>
  223. void BinSTree<T>::Delete(const T& item)
  224. {
  225.     // DNodePtr = 指向被删除结点 D 的指针
  226.     // PNodePtr = 指定结点 D 的双亲节点 P 的指针
  227.     // RNodePtr = 指向替换 D 的结点 R 的指针
  228.     TreeNode<T> *DNodePtr, *PNodePtr, *RNodePtr;
  229.     
  230.     // 搜索数据值为 item 的结点,并保存该结点的双亲结点的指针
  231.     if ((DNodePtr = FindNode (item, PNodePtr)) == NULL)
  232.         return;
  233.     
  234.     // 如果 D 有一个指针为 NULL,则替换结点为其另一枝的某一结点
  235.     if (DNodePtr->right == NULL)
  236.         RNodePtr = DNodePtr->left;
  237.     else if (DNodePtr->left == NULL)
  238.         RNodePtr = DNodePtr->right;
  239.         
  240.     // DNodePtr 的两个指针均不为 NULL
  241.     else
  242.     {
  243.         // 寻找并卸下 D 的替换结点。从结点 D 的左子树开始,找数据值小于 D 的数据值的
  244.         // 最大值,将该结点从树中断开
  245.         
  246.         // PofRNodePtr = 指向替换结点双亲的指针
  247.         TreeNode<T> *PofRNodePtr = DNodePtr;
  248.         
  249.         // 第一种可能的替换为 D 的左孩子
  250.         RNodePtr = DNodePtr->left;
  251.     
  252.         // 从 D 的左孩子的右子树继续往下搜索最大值,并记录当前结点及其双亲结点的
  253.         // 指针,最后,我们将找到替换结点
  254.         while(RNodePtr->right != NULL)
  255.         {
  256.             PofRNodePtr = RNodePtr;
  257.             RNodePtr = RNodePtr->right;
  258.         }
  259.         
  260.         if (PofRNodePtr == DNodePtr)
  261.             // 被删除结点的左孩子为替换结点,将 D 的右子树赋给 R
  262.             RNodePtr->right = DNodePtr->right;
  263.         else
  264.         {
  265.             // 至少往右子树移动了一个结点,从树中删除替换结点,将其左子树赋给其双亲
  266.             PofRNodePtr->right = RNodePtr->left;
  267.             
  268.             // 用替换结点代替 DNodePtr
  269.             RNodePtr->left = DNodePtr->left;
  270.             RNodePtr->right = DNodePtr->right;
  271.         }
  272.     }
  273.     // 完成到双亲结点的连接。删除根结点,并给新更赋值
  274.     if (PNodePtr == NULL)
  275.         root = RNodePtr;
  276.         
  277.     // 将 R 连到 P 的正确一枝上
  278.     else if (DNodePtr->data < PNodePtr->data)
  279.         PNodePtr->left = RNodePtr;
  280.     else
  281.         PNodePtr->right = RNodePtr;
  282.         
  283.     // 释放被删结点内存并将树的大小减 1
  284.     delete DNodePtr;
  285.     size--;
  286. }
  287. // 若当前结点已定义且数据值与给定数据值相等,则将结点值赋给 item;否则,将 item 插入到树中
  288. template <class T>
  289. void BinSTree<T>::Update(const T& item)
  290. {   
  291.     if (current != NULL && current->data == item)
  292.             current->data = item;
  293.     else
  294.         Insert(item);
  295. }
  296. // 返回根结点的地址
  297. template <class T>
  298. TreeNode<T> *BinSTree<T>::GetRoot(void) const
  299. {
  300.     return root;
  301. }
  302. #endif  // BINARY_SEARCH_TREE_CLASS