调用leftRotate后AVL树打印函数输出异常,求错误定位
AVL树左旋转后print2D输出异常问题排查
我实现了一个打印二叉搜索树(BST)结构的print2D函数,不调用leftRotate时输出正常,但调用该函数后,输出的树结构错误且丢失部分节点。以下是完整的C语言程序:
// C program to insert a node in AVL tree #include<stdio.h> #include<stdlib.h> #define COUNT 10 // An AVL tree node struct Node { int key; struct Node *left; struct Node *right; int height; }; // A utility function to get maximum of two integers int max(int a, int b); // A utility function to get the height of the tree int height(struct Node *N) { if (N == NULL) return 0; return 1+max(height(N->left), height(N->right)); } // A utility function to get maximum of two integers int max(int a, int b) { return (a > b)? a : b; } /* Helper function that allocates a new node with the given key and NULL left and right pointers. */ struct Node* newNode(int key) { struct Node* node = (struct Node*) malloc(sizeof(struct Node)); node->key = key; node->left = NULL; node->right = NULL; node->height = 0; // new node is initially added at leaf return(node); } // A utility function to right rotate subtree rooted with y // See the diagram given above. struct Node *rightRotate(struct Node *y) { struct Node *x = y->left; struct Node *T2 = x->right; // Perform rotation x->right = y; y->left = T2; // Update heights y->height = height(y); x->height = height(x); // Return new root return x; } // A utility function to left rotate subtree rooted with x // See the diagram given above. struct Node *leftRotate(struct Node *x) { struct Node *y = x->right; struct Node *T2 = y->left; // Perform rotation y->left = x; x->right = T2; // Update heights x->height = height(x); y->height = height(y); // Return new root return y; } // Get Balance factor of node N int getBalance(struct Node *N) { if (N == NULL) return 0; return height(N->left) - height(N->right); } // Recursive function to insert a key in the subtree rooted // with node and returns the new root of the subtree. struct Node* insert(struct Node* node, int key) { /* 1. Perform the normal BST insertion */ if (node == NULL) return(newNode(key)); if (key < node->key) node->left = insert(node->left, key); else if (key > node->key) node->right = insert(node->right, key); else // Equal keys are not allowed in BST return node; /* 2. Update height of this ancestor node */ node->height = height(node); /* 3. Get the balance factor of this ancestor node to check whether this node became unbalanced */ int balance = getBalance(node); // If this node becomes unbalanced, then // there are 4 cases // Left Left Case if (balance > 1 && key < node->left->key) return rightRotate(node); // Right Right Case if (balance < -1 && key > node->right->key) return leftRotate(node); // Left Right Case if (balance > 1 && key > node->left->key) { node->left = leftRotate(node->left); return rightRotate(node); } // Right Left Case if (balance < -1 && key < node->right->key) { node->right = rightRotate(node->right); return leftRotate(node); } /* return the (unchanged) node pointer */ return node; } // A utility function to print preorder traversal // of the tree. // The function also prints height of every node void preOrder(struct Node *root) { if(root != NULL) { printf("%d ", root->key); preOrder(root->left); preOrder(root->right); } } void print2DUtil(struct Node*root, int space) { // Base case if (root == NULL) return; // Increase distance between levels space += COUNT; // Process right child first print2DUtil(root->right, space); // Print current node after space // count printf("\n"); for (int i = COUNT; i < space; i++) printf(" "); printf("%d\n", root->key); // Process left child print2DUtil(root->left, space); } // Wrapper over print2DUtil() void print2D(struct Node*root) { // Pass initial space count as 0 print2DUtil(root, 0); } /* Driver program to test above function*/ int main() { struct Node *root = NULL; root = insert(root, 20); root = insert(root, 11); root = insert(root, 32); root = insert(root, 4); root = insert(root, 16); root = insert(root, 25); root = insert(root, 36); root = insert(root, 3); root = insert(root, 7); root = insert(root, 13); root = insert(root, 18); root = insert(root, 21); root = insert(root, 28); root = insert(root, 33); root = insert(root, 39); /* The constructed AVL Tree would be 30 / \ 20 40 / \ \ 10 25 50 */ root = leftRotate(root); print2D(root); return 0; }
问题根源
height函数的计算逻辑与newNode中的高度初始化值不匹配,导致旋转后节点高度更新错误,进而破坏了树的结构关系。
- 原
height函数中,空节点返回0,叶子节点的计算高度为1 + max(0,0) = 1 - 但
newNode中初始化node->height = 0,与计算逻辑矛盾
当执行leftRotate时,调用height()更新节点高度,递归计算过程中会出现高度值混乱,最终导致打印函数遍历树时出现异常,表现为结构错误、节点丢失。
修复方案
任选以下一种方式即可解决:
方式一:修正newNode的高度初始化值
将叶子节点的初始高度设为1,匹配height函数的计算逻辑:
struct Node* newNode(int key) { struct Node* node = (struct Node*)malloc(sizeof(struct Node)); node->key = key; node->left = NULL; node->right = NULL; node->height = 1; // 修改为1 return(node); }
方式二:修正height函数的逻辑
让空节点返回-1,这样叶子节点的计算高度为1 + max(-1,-1) = 0,匹配初始值:
int height(struct Node *N) { if (N == NULL) return -1; // 修改为-1 return 1+max(height(N->left), height(N->right)); }
验证
修复后执行leftRotate再调用print2D,即可正确输出旋转后的树结构,节点不会丢失,树的层级关系也能准确展示。
内容的提问来源于stack exchange,提问作者ferocioussprouts122
相关产品推荐
相关产品推荐

