完整的二叉树交换子级和父级错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了完整的二叉树交换子级和父级错误相关的知识,希望对你有一定的参考价值。

我正在为一个学校做项目,但有一个奇怪的错误。我正在实现一个完整的二叉树,并且在与他的父节点交换节点时遇到麻烦。

交换功能应该很好,我认为问题不存在。

在测试期间,我发现有1个案例无法正常工作。

此:Broken case

除这种情况外,所有其他交换都可以正常工作>>

我的树的结构就是这样

typedef struct TreeNode {
void * data;
struct TreeNode * left;
struct TreeNode * right;
struct TreeNode * parent;
} TNode;

typedef struct CompleteBinaryTree {
TNode * root;
TNode * last;
int numelm;
} CBTree;

这是我的交换函数:(就像我说的,我认为问题不在这里,但您永远不知道)

void CBTreeSwap(CBTree* tree, TNode* parent, TNode* child) {
 assert(parent != NULL && child != NULL && (child == parent->left || child == parent->right));

 if (child == tree->last) tree->last = parent;
 if(child == parent->left) {        
     if(child->left != NULL)
         child->left->parent = parent;
     parent->left = child->left;
     child->left = parent;
     if (child->right != NULL)
         child->right->parent = parent;
     if (parent->right != NULL)
         parent->right->parent = child;
     TNode * tmp = child->right;
     child->right = parent->right;
     parent->right = tmp;
     if (parent != tree->root) {
         parent->parent->left = child;
         child->parent = parent->parent;
         parent->parent = child;
     }
     else {
         child->parent = NULL;
         tree->root = child;
         parent->parent = child;
     }
 }
 else {
     if(child->right != NULL)
         child->right->parent = parent;
     parent->right = child->right;
     child->right = parent;
     if(child->left != NULL)
         child->left->parent = parent;
     if(parent->left != NULL)
         parent->left->parent = child;
     TNode * tmp = child->left;
     child->left = parent->left;
     parent->left = tmp;
     if(parent != tree->root)
     {
         parent->parent->right = child;
         child->parent = parent->parent;
         parent->parent = child;
     }
     else {
         child->parent = NULL;
         tree->root = child;
         parent->parent = child;
     }
 }
}

要在使用中的树中插入:

void CBTreeInsert(CBTree* tree, void* data) {
   TNode * tmp = newTNode(data);
   TNode * curr = tree->last;

   if(tree->root == NULL) { //empty
       tree->root = tmp;
   }
   else if(tree->last == tree->root) { //one node
       tree->last->left = tmp;
       tmp->parent = tree->root;
   }
   else if(tree->last->parent->right == NULL) { //general
       tree->last->parent->right = tmp;
       tmp->parent = tree->last->parent;
   }
   else if (tree->last == tree->last->parent->right) { //degenarated
       curr = tree->last->parent ;
   while (1) {
       if (curr == tree->root)
           break ;

       if (curr == curr->parent->left) {
           curr = curr->parent->right ;
           assert(curr != NULL) ;
           break ;
       }
       curr = curr->parent ;
   }

   while (curr->left != NULL) {
       assert(curr->right != NULL) ;
       curr = curr->left ;
   }
       assert(curr->right == NULL) ;
       tmp->parent = curr ;
       curr->left  = tree->last = tmp;
   }
   else {
       fprintf(stderr,"Error
");
   }
   tree->last = tmp;
   tree->numelm++;
}

所以我这样构建测试:

int *i1 = malloc(sizeof(int));
int *i2 = malloc(sizeof(int));
int *i3 = malloc(sizeof(int));
int *i4 = malloc(sizeof(int));
int *i5 = malloc(sizeof(int));
int *i6 = malloc(sizeof(int));
int *i7 = malloc(sizeof(int));
int *i8 = malloc(sizeof(int));
int *i9 = malloc(sizeof(int));
int *i10 = malloc(sizeof(int));
int *i11 = malloc(sizeof(int));
int *i12 = malloc(sizeof(int));
int *i13 = malloc(sizeof(int));
int *i14 = malloc(sizeof(int));
int *i15 = malloc(sizeof(int));
*i1 = 1;
*i2 = 2;
*i3 = 3;
*i4 = 4;
*i5 = 5;
*i6 = 6;
*i7 = 7;
*i8 = 8;
*i9 = 9;
*i10 = 10;
*i11 = 11;
*i12 = 12;
*i13 = 13;
*i14 = 14;
*i15 = 15;


CBTree * T  = newCBTree(); //create tree
CBTreeInsert(T, (int*) i1);
CBTreeInsert(T, (int*) i2);
CBTreeInsert(T, (int*) i3);
CBTreeInsert(T, (int*) i4);
CBTreeInsert(T, (int*) i5);
CBTreeInsert(T, (int*) i6);
CBTreeInsert(T, (int*) i7);
CBTreeInsert(T, (int*) i8);
CBTreeInsert(T, (int*) i9);
CBTreeInsert(T, (int*) i10);
CBTreeInsert(T, (int*) i11);
CBTreeInsert(T, (int*) i12);
CBTreeInsert(T, (int*) i13);
CBTreeInsert(T, (int*) i14);
CBTreeInsert(T, (int*) i15);

//All these work
CBTreeSwap(T, T->root->left, T->root->left->left);
CBTreeSwap(T, T->root, T->root->left);
CBTreeSwap(T, T->root->right, T->root->right->right);
CBTreeSwap(T, T->root, T->root->right);
CBTreeSwap(T, T->last->parent, T->last);

//This one is broken
CBTreeSwap(T, T->root->left, T->root->left->right);

[当我运行该损坏的测试并尝试查看我的树时,我得到了树的所有分支,然后出现段错误。

如果您需要更多我的代码,这只是更大项目的一部分,请随时提出

谢谢!

我正在为一个学校做项目,但有一个奇怪的错误。我正在实现一个完整的二叉树,并且在与他的父节点交换节点时遇到麻烦。交换函数应该很好,并且...

答案

[您的问题不仅在交换T->leftT->left->right(破坏所有剩余的T->left子树时,而且在交换T->rightT->right->left时,都会产生树损坏。

以上是关于完整的二叉树交换子级和父级错误的主要内容,如果未能解决你的问题,请参考以下文章

删除父级和所有子级

在一个查询中保存父级和子级(子级对父级有空值引用)

找到堆的父级和子级的方程式背后的直觉是啥?

在 Laravel 中为父级和子级创建活动类

php facetwp索引仅限父级和一级子级条款

php facetwp索引仅限父级和一级子级条款