已经定义了一个二叉树模板类BST,
template<typename T>
class BST
节点有2个数据,string id,T data;
BST<int> BSTbuck;
BST<double> BSTgpa;
BST<string> BSTmajor;
BST<string> BSTname;
BST的四个实现如上,意思是每个BST存储一个记录的id和其中一个数据(buck或gpa或major或name。
现要根据一个给定的a,将data值为a的记录从BST中删除,并将另外三个BST树中与该将删除的节点id值相同的点也删除。
求大神帮忙啊!!
一般都是遍历这四颗树,找到data为a的节点,记录节点的id,删除本树的这个节点,再在其它三颗树里查找id为刚才记录的节点id的节点,删掉。
你是想问大体的删除流程还是想问怎么查找还是想问怎么删除一个树的节点?
删除节点,BST是模板类,并且建立BST时是基于data的,所以id在树里面是无序状态,删除data为a的方法已经实现(BST的一个模板函数),问题是怎么删除另外三棵树的id与先前那个相同的节点
@SCUT_兴国老表: 首先data为a的节点的id已经知道的了,而id在树里是无序状态,那就遍历其它三颗树的每一个节点,判断id是否等于data为a的节点的id,如果相等就删除这个节点
@诶碧司: 能给下代码么?就是判断id是否等于data为a的节点的id的方法,该方法是BST的成员方法
@SCUT_兴国老表: if (node.id == id)
@诶碧司: 不是这个代码,现在我的问题是在一个二叉树中,每个节点存储2个数据,id,data,其中data是有序的,现在要根据id找到对应的data,
你看下我的这个代码,其中hasID是判断给定的ID是否存在的,运行的时候cout会执行多次,请告诉我这是为什么,还有需要怎么改进
1 template<typename T> 2 T finddata(Node<T> *root,const string id) 3 { 4 hasID=0; 5 while(root != NULL) 6 { 7 if(root->key()==id) 8 { 9 hasID=1; 10 return root->val(); 11 } 12 else 13 { 14 finddata(root->left(),id); 15 finddata(root->right(),id); 16 17 } 18 cout<<"the record doesn't exist!"<<endl; 19 break; 20 21 } 22 23 return 0; 24 }
@SCUT_兴国老表: 你这里使用了递归的方式来查找,会执行多次finddata,每次执行的时候几乎都会执行cout,所以才会执行多次,一般都是调用方法后根据返回值来判断是否存在,而不要在递归里执行
试试下面的代码:
template<typename T> T finddata(Node<T> *root,const string id) { // 这里不需要用while,只执行一次,用if就行 if(root != NULL) { if(root->key()==id) { // 找到就返回data return root->val(); } else { T value = finddata(root->left(),id); // 如果有值就表示找到了,直接返回这个值 if(value != null) { return value; } // 没有值就需要继续找右分支 else { value = finddata(root->right(),id); } // 同样如果有值就表示找到了,直接返回这个值 if(value != null) { return value; } } } // 返回null表示在这个root这个节点及下面的节点找不到 return null; }
调用finddata方法后看一下返回值就知道有没有找到了
@诶碧司: 好像是,但是遇到一个了,就是data可能是string或double,那个,判断是否相等要怎么实现呢?
(初学,还不是很会,见谅)
@SCUT_兴国老表: 如果类型T是double类型,就不能返回null了,这样可以把代码修改一下,直接返回节点,这样如果返回值不是null,再使用node->val()获得data值
template<typename T> Node<T> finddata(Node<T> *root,const string id) { // 这里不需要用while,只执行一次,用if就行 if(root != NULL) { if(root->key()==id) { // 找到就返回节点 return root; } else { Node<T> node = finddata(root->left(),id); // 如果有值就表示找到了,直接返回这个值 if(node != null) { return node; } // 没有值就需要继续找右分支 else { node = finddata(root->right(),id); } // 同样如果有值就表示找到了,直接返回这个值 if(node != null) { return node; } } } // 返回null表示在这个root这个节点及下面的节点找不到 return null; }
这样应该就可以应对double类型的了
@诶碧司: 太感谢了,这样问题解决了,还有个问题,就是所有BST树中id都是不同的,但是data可能会相同,查找和删除都要把所有data相同的节点查找出来(打印出来),删除掉。我只实现了data不同的方法,下面是我的代码,请问应该怎么修改呢
1 string findID(Node<T> *subroot,T& it) //查找方法 2 { 3 4 hasData=0; //判断该值是否存在 5 while(subroot!=NULL) //当结点不为空时继续比较 6 { 7 8 if(it<subroot->val()) 9 { 10 subroot=subroot->left(); 11 } 12 else if(it>subroot->val()) 13 { 14 subroot=subroot->right(); 15 } 16 else if(it==subroot->val()) 17 { 18 hasData=1; 19 //返回该关键值所在节点的id 20 return subroot->key(); 21 } 22 } 23 cout<<"the record does not exist!"<<endl; 24 return ""; 25 } 26 bool deleteNode1(T key) 27 { 28 29 if(findID<T>(root,key)=="") 30 { 31 32 return false; 33 } 34 Node<T> *preNode; 35 Node<T> *pNode=root; 36 while(pNode != NULL) //查找该节点 37 { 38 if(pNode->val() == key) 39 { 40 break; 41 } 42 else if (pNode->val() > key ) 43 { 44 preNode =pNode; 45 pNode = pNode->left(); 46 } 47 else 48 { 49 preNode = pNode; 50 pNode=pNode->right(); 51 } 52 53 } 54 if(pNode->right() == NULL&&pNode->left() !=NULL) 55 { 56 if(pNode ==root) 57 { 58 root=pNode->left(); 59 } 60 else if(preNode->left() == pNode) 61 { 62 preNode->setLeft(pNode->left()); 63 } 64 else 65 { 66 preNode->setRight(pNode->left()); 67 } 68 } 69 else if(pNode->left() == NULL&&pNode->right() != NULL) 70 71 { 72 if(pNode == root) 73 root = pNode->right(); 74 else if(preNode->left() == pNode) 75 preNode->setLeft(pNode->right()); 76 else 77 preNode->setRight(pNode->right()); 78 } 79 else if(pNode->left()==NULL&&pNode->right()==NULL) 80 { 81 if(pNode==preNode->left()) 82 preNode->setLeft(NULL); 83 else 84 preNode->setRight(NULL); 85 } 86 87 88 else //该节点有左右子树 89 { 90 Node<T> *pre=pNode; 91 Node<T> *pSearch = pNode->right(); 92 while (NULL != pSearch->left()) 93 { 94 pre = pSearch; 95 pSearch = pSearch->left(); 96 } 97 pNode->setData( pSearch->val()); 98 pNode->setID(pSearch->key()); 99 if(pre->left() == pSearch) 100 pre->setLeft(pSearch->right()); 101 else 102 pre->setRight(pSearch->right()); 103 } 104 return true; 105 }
@SCUT_兴国老表: 多次调用查找和删除的方法就可以了,直到查找的时候找不到指定data值的节点
@诶碧司: 知道了,谢谢啊
对于各类语言都有自己的常用库.
C++中的第三方标准库,用得最多的那个 ..,,,,
不允许用标准库
二叉树结点最少都要有3个字段吧.值,左子节点,右子节点,有的还会加个父节点
我的是有四个字段