标签:
源代码:
ttree.h源代码:
/* * ttree.h: header file * * T树的结构 * */ #ifndef TTREE #define TTREE #include <QString> #include <QMap> /* * 为了保持空间的利用率,每一个内部节点都需要包含一个最小数目的键值 */ enum { ttPageSize = 10, ttminSize = ttPageSize - 2 }; typedef QString ElementKey; typedef QMap<QString, QString>* ElementData; typedef struct TTREENODE //树节点的结构 { TTREENODE *left; //节点的左子树指针 TTREENODE *right; //节点的右子树指针 unsigned short int nItems; //节点中键值的数目 ElementKey key[ttPageSize]; //key值数组 ElementData data[ttPageSize]; //对应数据行的指针 因为需要保证每个内部节点的 //最小数目键值,所以用数组,不用map之类的容器 int balance; //balance(平衡因子),其绝对值不大于1,balance =右子树高度-左子树高度; } TTREENODE; class TTree //T树的结构 { public: TTree(); virtual ~TTree(); public: //向T树中插入一条数据 void insertRecord(ElementKey key, ElementData data); //删除T树中对应的key的数据 void deleteRecord(ElementKey key); //查找对应key值得数据指针 ElementData findRecord(ElementKey key); //返回T树中的节点数 int getNodeSize(); //返回T树的深度 int depth(TTREENODE *pNode) const; //比较两个key值得大小,1 : key1 > key2, 0 : key1 = key2, -1 : key1 < key2 virtual int keyCompare(ElementKey key1, ElementKey key2); //清除树节点 void clear(); //如果树为空返回TRUE, 不为空返回FALSE bool isEmpty() const; //T树的前序遍历 void PreOrderTraverse(TTREENODE *pNode) const; private: //从内存中为node分配空间 TTREENODE *mallocNode(); //释放节点占用的内存 void freeNode(TTREENODE *pNode); //递归清除每个节点 void _earse(TTREENODE *pNode); //插入的时候需要递归遍历整棵树,为了方便,额外增加一个方法 *& 表示一个指针的引用 bool _insert(TTREENODE *&pNode, ElementKey key, ElementData data); //内部删除数据的方法 int _delete(TTREENODE *&pNode, ElementKey key); private: //获取该节点的平衡因子 int getBalance(TTREENODE *pNode) const; //LL类型旋转 右旋 TTREENODE *singleRotateLeft(TTREENODE *pNode); //RR类型旋转 左旋 TTREENODE *singleRotateRight(TTREENODE *pNode); //LR类型旋转,节点的左子树先左旋,然后节点右旋 TTREENODE *doubleRotateLeftRight(TTREENODE *pNode); //RL类型旋转,节点的右子树先右旋,然后节点左旋 TTREENODE *doubleRotateRightLeft(TTREENODE *pNode); //平衡右子树分支 int balanceRightBranch(TTREENODE *&pNode); //平衡左子树分支 int balanceLeftBranch(TTREENODE *&pNode); //平衡右子树分支:节点隔层调用底层的节点的数据,需要另外一种平衡 int balanceRightBranchInterlayer(TTREENODE *&pNode); //平衡左子树分支:节点隔层调用底层的节点的数据,需要另外一种平衡 int balanceLeftBranchInterlayer(TTREENODE *&pNode); public: TTREENODE* root; //T树的根节点 int nodeSize; //T树中的节点数 }; #endif // TTREE
/* * ttree.cpp: source file */ #include "ttree.h" #include <math.h> #include <QString> #include <QDebug> TTree::TTree() { root = NULL; nodeSize = 0; // qDebug() << "in TTree()"; } TTree::~TTree() { clear(); root = NULL; nodeSize = 0; } TTREENODE *TTree::mallocNode() { TTREENODE *pNode = new TTREENODE; /* * void *memset(void *s, int ch, size_t n); * 函数解释:将s中前n个字节替换为ch并返回s; * memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。 */ // memset(pNode, 0, sizeof(TTREENODE)); //如果不注释,会导致程序异常 pNode->nItems = 0; pNode->balance = 0; pNode->balance = 0; pNode->left = pNode->right = NULL; nodeSize ++; return(pNode); } void TTree::freeNode(TTREENODE *pNode) { if(pNode) { delete pNode; pNode = NULL; nodeSize --; } } void TTree::_earse(TTREENODE *pNode) { if(pNode == NULL) { return; } _earse(pNode->left); _earse(pNode->right); freeNode(pNode); } void TTree::clear() { _earse(root); } int TTree::getNodeSize() { return nodeSize; } ElementData TTree::findRecord(ElementKey key) { TTREENODE *pNode = root; while(pNode != NULL) { int n = pNode->nItems; ElementKey minKey = pNode->key[0]; ElementKey maxKey = pNode->key[n > 0 ? n - 1 : 0]; int nDiff1 = keyCompare(key, minKey); int nDiff2 = keyCompare(key, maxKey); if(nDiff1 >= 0 && nDiff2 <= 0) { int l = 0, r = n - 1; //二分查找算法 while(l <= r) { int i = (r - l) / 2 + l; ElementKey itemKey = pNode->key[i]; int nDiff = keyCompare(key, itemKey); if(nDiff == 0) { return pNode->data[i]; } else if(nDiff > 0) { l = i + 1; } else { r = i - 1; } } break; } else if(nDiff1 < 0) { pNode = pNode->left; } else if(nDiff2 > 0) { pNode = pNode->right; } } return NULL; } /*int TTree::getBalance(TTREENODE *pNode) const //第三次修改BUG,此处需要递归,你个辣鸡!!! { int l, r; TTREENODE *p1, *p2; l = r = 0; p1 = p2 = pNode; if(p1 != NULL) { while(p1->left != NULL) { p1 = p1->left; l++; } } if(p2 != NULL) { while(p2->right != NULL) { p2 = p2->right; r++; } } qDebug() << "key: " << pNode->key[0] << " l : " << l << " r : " <<r; return (r - l); } */ int TTree::getBalance(TTREENODE *pNode) const { return depth(pNode->right) - depth(pNode->left); } int TTree::depth(TTREENODE *pNode) const { if(pNode == NULL) { return 0; } return depth(pNode->left) > depth(pNode->right) ? depth(pNode->left) + 1 : depth(pNode->right) + 1; } //LL类型的旋转需要右旋一次,然后返回新的根节点 TTREENODE *TTree::singleRotateLeft(TTREENODE *pNode) { TTREENODE *k = pNode->left; pNode->left = k->right; k->right = pNode; pNode->balance = getBalance(pNode); k->balance = getBalance(k); // qDebug() << "右旋完毕:pNode: " << pNode->key[0] << " pNode->bf: " << pNode->balance; // qDebug() << "右旋完毕:k: " << k->key[0] << " k->bf: " << k->balance; return k; } //RR类型的旋转需要左旋一次,然后返回新的根节点 TTREENODE *TTree::singleRotateRight(TTREENODE *pNode) { TTREENODE *k = pNode->right; pNode->right = k->left; k->left = pNode; pNode->balance = getBalance(pNode); k->balance = getBalance(k); return k; } //LR类型的旋转需要根节点的左子树先左旋一次,变成LL类型,然后根节点再右旋一次,然后返回新的根节点 TTREENODE *TTree::doubleRotateLeftRight(TTREENODE *pNode) { pNode->left = singleRotateRight(pNode->left); pNode->balance = getBalance(pNode); return singleRotateLeft(pNode); } //RL类型的旋转需要根节点的右子树先右旋一次,变成RR类型,然后根节点再左旋一次,返回根节点 TTREENODE *TTree::doubleRotateRightLeft(TTREENODE *pNode) { pNode->right = singleRotateLeft(pNode->right); pNode->balance = getBalance(pNode); // leverlOrderTraverse(root); return singleRotateRight(pNode); } //插入一条数据记录的时候需要先判断树中是否有节点,没有节点需要创建节点插入,如果有 //节点,需要遍历T树查找相应的位置插入 void TTree::insertRecord(ElementKey key, ElementData data) { // qDebug() << "in insertRecord(), key = " << key << " data = " << data; if(root == NULL) { root = mallocNode(); root->balance = 0; root->key[0] = key; root->data[0] = data; // qDebug()<< "i got here "; // qDebug() << "ROOT " << root->key[0] << root->data[0]; root->nItems = 1; root->left = NULL; root->right = NULL; } else { // qDebug() << "ROOT is not NULL"; TTREENODE *pNode = root; bool bRet = _insert(pNode, key, data); /* * 插入数据可能导致插入节点,导致T树不平衡开始旋转,导致root改变 */ if(pNode != root) { root = pNode; } } } /* * 在一个节点中插入数据的时候: * (1)比最小的key值小 * (2)比最大的key值大 * (3)处于这个节点的key值范围内 */ bool TTree::_insert(TTREENODE *&pNode, ElementKey key, ElementData data) { int n = pNode->nItems; ElementKey minKey = pNode->key[0]; ElementKey maxKey = pNode->key[n > 0 ? n-1 : 0]; int nDiff = keyCompare(key, minKey); /* * 如果key值小于这个节点中最小的key值 * (1)如果这个节点中存储的值个数小于pageSize(节点存储的最大个数)&&(没有左子树||key等于节点中的最小值) * 把节点中的数组向后移一位,把当前key插入到最前面 * (2)如果不满足(1),也就是当前节点存储满了,并且没有左子树,需要添加新的节点 * (3)如果(1)(2)都不满足,说明需要向子节点中插入,需要递归,一直到插入为止 * 当插入新的节点的时候,需要重新计算平衡因子,看是否需要旋转 */ if(nDiff == 0) //因为每次只返回一条数据,所以如果key值相同,说明是同一条数据,就不能再次插入 { return false; } if(nDiff < 0) { TTREENODE *pLeftId = pNode->left; /* * 疑惑!!!!!!!! * 如果key值相同怎么还插入了,虽然返回false * 查找的时候findRecord只返回一条数据的地址 */ //if(pLeftId == NULL && pNode->nItems < pageSize) if(pNode->nItems < ttPageSize) //第三次修改BUG { TTREENODE * pleftId = pNode->left; if(pleftId != NULL) { while(pleftId->right) { pleftId = pleftId->right; } } if(pNode->left == NULL || keyCompare(key, pleftId->key[pleftId->nItems-1]) > 0) { for(int i = n; i > 0; i--) { pNode->key[i] = pNode->key[i-1]; pNode->data[i] = pNode->data[i-1]; } pNode->key[0] = key; pNode->data[0] = data; pNode->nItems += 1; return false; } } if(pLeftId == NULL) { // qDebug() << "开辟新的左子节点"; pLeftId = mallocNode(); pLeftId->key[0] = key; pLeftId->data[0] = data; pLeftId->nItems += 1; pNode->left = pLeftId; } else { TTREENODE *pChildId = pLeftId; bool issuccess = _insert(pChildId, key, data); if(pChildId != pLeftId) { pNode->left = pLeftId = pChildId; } if(!issuccess) { return false; } } /* * 由于某些插入导致递归查找插入,下层节点旋转平衡节点后, * 再重新递归上层看是否旋转,一直到root,完成整棵树的旋转 */ if(pNode->balance > 0) { pNode->balance = 0; return false; } else if(pNode->balance == 0) { pNode->balance = -1; return true; //true或false用来控制是否需要递归旋转,当多出一层节点的时候才会导致树失衡 } //当旋转完毕,多出的那一层就会剪掉,整棵树已经平衡,没必要继续递归检测 else { if(pLeftId->balance < 0) { pNode = singleRotateLeft(pNode); } else { pNode = doubleRotateLeftRight(pNode); } return false; } } /* * 第二种情况,大于最大的key值,与上面类似 */ nDiff = keyCompare(key, maxKey); // qDebug() << "keyCompare(key, maxKey) : " << key << maxKey << nDiff; if(nDiff == 0) { return false; } if(nDiff > 0) { // qDebug()<<"新插入数据>节点最大key值"; TTREENODE *pRightId = pNode->right; // if(pRightId == NULL && pNode->nItems < pageSize) //当节点中的数据只有一个并且引起旋转导致节点上升,导师pRightId!=NULL if(pNode->nItems < ttPageSize) { //然而再次插入的时候,随然当前节点数据量<PageSize,但是也不能插入当前结点 // qDebug() << "当前结点未满,插入当前节点"; //T树效率影响点之一,可以动手修改点 TTREENODE * prightId = pNode->right; //第三次修改BUG:成功避免节点因旋转导致空间利用率低下问题 if(prightId != NULL) { while(prightId->left) { prightId = prightId->left; } } if(pNode->right == NULL || keyCompare(key, prightId->key[0]) < 0) { pNode->key[n] = key; pNode->data[n] = data; pNode->nItems ++; return false; } } if(pRightId == NULL) { // qDebug() << "需要开辟新节点"; pRightId = mallocNode(); pRightId->key[0] = key; pRightId->data[0] = data; pRightId->nItems = 1; pNode->right = pRightId; } else { // qDebug() << "进入下一级节点"; TTREENODE *pChildId = pRightId; bool bGrow = _insert(pChildId, key, data); if(pChildId != pRightId) { pNode->right = pRightId = pChildId; } if(!bGrow) { return false; } } // qDebug() << "pNode->balance : " << pNode->balance; if(pNode->balance < 0) { pNode->balance = 0; return false; } else if(pNode->balance == 0) { pNode->balance = 1; return true; //增加一个新节点,返回true,进入现在代码,进行重置节点中的平衡点 } else { // qDebug() << "in rotate"; if(pRightId->balance > 0) { // qDebug() << "in RR: pNode->bf: " << pNode->balance << " pRightId->bf : " << pRightId->balance; pNode = singleRotateRight(pNode); //RR类型, 左旋 // qDebug() << "after RR : " <<pNode->balance; } else if(pRightId->balance < 0) { // PreOrderTraverse(root); // qDebug() << "int RL: pNode->bf: " << pNode->balance << " pRightId->bf : " << pRightId->balance; pNode = doubleRotateRightLeft(pNode); //RL类型,先右旋,再左旋 // qDebug() << "out RL"; } // qDebug() << "out rotate"; return false; } } /* * 第三种情况,key值在节点的key值范围内 * (1)如果该节点中的数据还没有满,只需找到合适的位置插入即可 * (2)如果节点中数据已满,只需要考虑把节点往前挤掉一个,还是往后挤掉一个 * ((1))如果节点的平衡点>0,为了避免插入可能带来的增加节点导致旋转引起 * 效率下降,需要往前挤掉,把最前面的节点重新往左子树插 * ((2))如果节点的balance<0,同理往后挤 */ // qDebug() << "确定位置为节点中间位置"; int l = 0, r = n -1; while(l < r) //利用二分查找找到需要插入位置r { int i = (r - l) / 2 + l; ElementKey itemKey = pNode->key[i]; nDiff = keyCompare(key, itemKey); if(nDiff > 0) { l = i + 1; } else { r = i; if(nDiff == 0) { return false; } } } if(n < ttPageSize) { // qDebug() << "节点中数据未满,直接插入中间合适的位置 r: " << r; for(int i = r; i < n; i++) { pNode->key[i+1] = pNode->key[i]; pNode->data[i+1] = pNode->data[i]; } pNode->key[r] = key; pNode->data[r] = data; pNode->nItems ++; // qDebug() << "插入完毕 nItems: " << pNode->nItems; return false; } else { ElementKey reInsertKey; ElementData reInsertData; if(pNode->balance >= 0) { reInsertKey = pNode->key[0]; reInsertData = pNode->data[0]; for(int i = 0; i < r - 1; i++) { pNode->key[i] = pNode->key[i+1]; pNode->data[i] = pNode->data[i+1]; } pNode->key[r-1] = key; pNode->data[r-1] = data; return _insert(pNode, reInsertKey, reInsertData); } else { reInsertKey = pNode->key[n-1]; reInsertData = pNode->data[n-1]; for(int i = n -1 ; i > r; i--) { pNode->key[i] = pNode->key[i-1]; pNode->data[i] = pNode->data[i-1]; } pNode->key[r] = key; pNode->data[r] = data; return _insert(pNode, reInsertKey, reInsertData); } } } /* * deleteRecord * 对外公开的delete方法 */ void TTree::deleteRecord(ElementKey key) { if(root != NULL) //删除BUG地方之一,已修改 { TTREENODE *pNode = root; int h = _delete(pNode, key); //assert(h >= 0); if(pNode != root) { root = pNode; } } } /* * 内部删除的方法 * * 如果key值不再当前结点的key值范围内,则递归调用本方法在子节点中删除key值对应的数据 * 如果key值在范围内: * (1)如果当前结点的nItems>minSize,则只需要删除节点中的数据,nItems-1即可 * (2)如果当前结点的nItems=minSize,需要调用一个子节点中的数据添加到本节点中。 * 至于调用子节点中小于当前结点最小值的最大值,还是大于当前结点的最大值的最小值 * 需要看当前结点的balance,尽可能避免删除带来的旋转 * (3)因为子节点的数据需要向上补充,所以有的子节点中的数据可能小于minSize,当节点中 * 的数据=1,并且需要删除的时候,本节点也需要删除,因此可能导致T树不平衡,导致旋转 * * T树与AVL树删除的不同的是,由于再删除中间节点的时候,子节点中的数据需要向上补充,所以 * 删除的一直是子节点。 * * return -1:没有删除成功 1:删除一个节点 0:没有删除节点,但删除数据成功 */ int TTree::_delete(TTREENODE *&pNode, ElementKey key) { int n = pNode->nItems; ElementKey minKey = pNode->key[0]; ElementKey maxKey = pNode->key[n > 0 ? n - 1 : 0]; int nDiff = keyCompare(key, minKey); // qDebug() << "keyCompare(key, minKey); key:" << key << " minKey:" << minKey << " nDiff:" << nDiff; if(nDiff < 0) { TTREENODE *pLeftId = pNode->left; if(pLeftId != 0) { TTREENODE *pChildId = pLeftId; // qDebug() << "!!!!!!!!!!!!!!!!!!!!!!!!!!!! pChildId: " << pChildId << " pLeftId: " << pLeftId; int h = _delete(pChildId, key); //h表示删除的节点数,不是数据数 // qDebug() << "pChildId: " << pChildId; if(pChildId != pLeftId) { pNode->left = pChildId; } if(h > 0) { return balanceLeftBranch(pNode); //h>0 表示有删除的节点,需要平衡 } else if(h == 0) { return 0; } } return -1; } nDiff = keyCompare(key, maxKey); if(nDiff > 0) { TTREENODE *pRightId = pNode->right; if(pRightId != 0) { TTREENODE *pChildId = pRightId; int h = _delete(pChildId, key); if(pChildId != pRightId) { pNode->right = pChildId; } if(h > 0) { return balanceRightBranch(pNode); } else if(h == 0) { return 0; } } return -1; } for(int i = 0; i < n; i++) { if(keyCompare(pNode->key[i],key) == 0) { if(n == 1 && pNode->left == NULL && pNode->right == NULL) //删除的一直是子节点 { freeNode(pNode); pNode = NULL; return 1; } TTREENODE *pLeftId = pNode->left, *pRightId = pNode->right; TTREENODE *pre = pNode; if(n <= ttminSize) { if(pLeftId != NULL && pNode->balance <= 0) //在调入子树节点数据的时候,尽量避免失衡,所以判断是从左子树调用还是从右子树 { bool isInterlayer = false; while(pLeftId->right != NULL) { isInterlayer = true; pre = pLeftId; pLeftId = pLeftId->right; } while(--i >= 0) //删除数据,从左子树中调入最大数据 { pNode->key[i+1] = pNode->key[i]; pNode->data[i+1] = pNode->data[i]; } pNode->key[0] = pLeftId->key[pLeftId->nItems - 1]; pNode->data[0] = pLeftId->data[pLeftId->nItems - 1]; TTREENODE *pChildId = pLeftId; int h = _delete(pChildId, pNode->key[0]); // qDebug() << "pChildId : " << pChildId; if(pChildId != pLeftId) { if(pre == pNode) { pre->left = pLeftId = pChildId; } else { pre->right = pLeftId = pChildId; //警告,数据能报错点 } } if(h > 0) { if(isInterlayer) { h = balanceRightBranchInterlayer(pNode->left); if(h > 0) { h = balanceLeftBranch(pNode); } } else { h = balanceLeftBranch(pNode); } } // qDebug() << "h: " << h; return h; } else if(pNode->right != NULL) { // qDebug() << "in pNode->right"; bool isInterlayer = false; while(pRightId->left != NULL) { isInterlayer = true; pre = pRightId; pRightId = pRightId->left; } while(++i < n) { pNode->key[i-1] = pNode->key[i]; pNode->data[i-1] = pNode->data[i]; } pNode->key[n-1] = pRightId->key[0]; pNode->data[n-1] = pRightId->data[0]; TTREENODE *pChildId = pRightId; int h = _delete(pChildId, pNode->key[n-1]); // qDebug() << "pChildId : " << pChildId << " pRightId:" <<pRightId ; if(pChildId != pRightId) { if(pre == pNode) { pre->right = pLeftId = pChildId; } else { pre->left = pLeftId = pChildId; } } // qDebug() << "pChildId : " << pChildId << " pRightId:" <<pRightId << pNode->right->left ; if(h > 0) { // qDebug() << "是时候起飞旋转了"; if(isInterlayer) { // qDebug() << "开始in balanceLBI"; h = balanceLeftBranchInterlayer(pNode->right); // qDebug() << "h: " << h; if(h > 0) { h = balanceRightBranch(pNode); } } else { h = balanceRightBranch(pNode); //没有隔层调用子节点中的数据 } } // qDebug() << "h: " << h; return h; } } while(++i < n) { pNode->key[i-1] = pNode->key[i]; pNode->data[i-1] = pNode->data[i]; } pNode->nItems -= 1; return 0; } } return -1; } /* * 平衡左子树 * 由于调用直接子节点数据,导致子节点删除的情况 * */ int TTree::balanceLeftBranch(TTREENODE *&pNode) { if(pNode->balance < 0) { pNode->balance = 0; //至于返不返回1,还需要看是不是(祖祖)祖父节点调用最下层节点的情况,(决定重新写一个这种情况下的平衡方法) return 1; //h>=1,证明子节点一层全部删除,pNode左子树少一层,可能导致旋转,返回1 } else if(pNode->balance == 0) { pNode->balance = 1; return 0; //删除了pNode的左子树,但是还有右子树支撑平衡 } else { TTREENODE *pRightId = pNode->right; int prightbf = pRightId->balance; if(prightbf >= 0) // { pNode = singleRotateRight(pNode); if(prightbf == 0) //第二次寻BUG:用prightbf代替pRightId->balance,因为是指针,在旋转后,balance变化,导致前后不一致 { pNode->balance = -1; pNode->left->balance = 1; return 0; } else { pNode->balance = 0; pNode->left->balance = 0; return 1; //旋转平衡导致pNode的深度-1,可能对上层造成影响 } } else { pNode = doubleRotateRightLeft(pNode); return 1; } } return 0; } /* * 平衡右子树 * 由于调用直接子节点数据,导致子节点删除的情况 * 由于删除可能导致旋转,所以需要判断,删除之前树肯定是平衡的 */ int TTree::balanceRightBranch(TTREENODE *&pNode) { if(pNode->balance > 0) { pNode->balance = 0; return 1; } else if(pNode->balance == 0) { pNode->balance = -1; return 0; } else { TTREENODE *pLeftId = pNode->left; int pleftbf = pLeftId->balance; if(pleftbf <= 0) { pNode = singleRotateLeft(pNode); if(pleftbf == 0) { pNode->balance = 1; pNode->right->balance = -1; return 0; } else { pNode->balance = 0; pNode->right->balance = 0; return 1; } } else { pNode = doubleRotateLeftRight(pNode); return 1; } } return 0; } /* * 平衡右子树分支 * 由于删除的另一种情况,节点跨层调用底层节点的数据,导致节点删除,可能需要平衡旋转 */ int TTree::balanceRightBranchInterlayer(TTREENODE *&pNode) { int h; if(pNode->right == NULL) { if(pNode->left == NULL) //第二次BUG:两种情况,这种是虽然隔代调入删除节点,但是还有一层直接调入删除。见乱画本 { return 1; } h = balanceRightBranch(pNode); return h; } TTREENODE *tempNode = pNode->right; if((h = balanceRightBranchInterlayer(tempNode)) > 0) { h = balanceRightBranch(pNode); } else { return 0; } return h; } /* * 平衡左子树分支 * 由于删除的另一种情况,节点跨层调用底层节点的数据,导致节点删除,可能需要平衡旋转 * 需要递归从最底层开始查看是否需要旋转,如果最底层高度不变,则对整棵树的平衡不会造成影响 */ int TTree::balanceLeftBranchInterlayer(TTREENODE *&pNode) { int h; //qDebug() << "pNode->left: " << pNode->left; if(pNode->left == NULL) { // qDebug() << "最底层,开始balanceLeftBranch"; if(pNode->right == NULL) //第二次修改:两种情况,这种是虽然隔代删除节点,但是还有一层删除。见本 { return 1; } h = balanceLeftBranch(pNode); return h; } TTREENODE *tempNode = pNode->left; if((h = balanceLeftBranchInterlayer(tempNode)) > 0) { h = balanceLeftBranch(pNode); //第二次修改 } else { return 0; } return h; } bool TTree::isEmpty() const { return root == NULL; } int TTree::keyCompare(ElementKey key1, ElementKey key2) { if(key1.size() < key2.size()) { return -1; } else if(key1.size() > key2.size()) { return 1; } else{ return QString::compare(key1, key2, Qt::CaseSensitive); } } void TTree::PreOrderTraverse(TTREENODE *pNode) const { if (pNode != NULL) { int nSize = pNode->nItems; qDebug()<<"bf: " << pNode->balance << " nItems: " << pNode->nItems; for (int i = 0; i < nSize; i++) { //printf("%02d ", pNode->item[i]); qDebug() << pNode->key[i] << " "; } qDebug()<<"||"; PreOrderTraverse(pNode->left); PreOrderTraverse(pNode->right); } }
标签:
原文地址:http://blog.csdn.net/u013815649/article/details/51941563