[英]How can I check if two binary trees contain the same nodes?
我正在嘗試實現一個檢查兩個二叉搜索樹是否相等的函數,節點的順序無關緊要。 但是我的實現不起作用。
我不允許將樹木展平成陣列。
這就是我到目前為止所擁有的:
int isIdentical(struct Node* root1, struct Node* root2)
{
if (root1 == NULL && root2 == NULL)
return 1;
else if (root1 == NULL || root2 == NULL)
return 0;
else {
if (root1->data == root2->data && isIdentical(root1->left, root2->left)
&& isIdentical(root1->right, root2->right))
return 1;
else
return 0;
}
}
當提供包含節點tree A = 2 4 5 6
和Tree B = 2 5 4 6
的樹時,輸出應為:
1
,表示它們相等,但我得到的是0
。 我不確定我哪里出錯了。
這就是 Node 的實現方式:
struct Node {
int data;
struct Node* left;
struct Node* right;
};
創建一個遍歷treeA
並檢查每個項目是否存在於treeB
中的遞歸函數。 失敗時放棄搜索並返回0
表示失敗。 它可以是你的功能
int isIdentical(struct Node* root1, struct Node* root2)
如果成功,再次調用該函數,將treeA
和treeB
的參數顛倒過來。 “檢查是否存在”操作可以是迭代和內聯的,因為它不需要回溯。
示例未嘗試過的代碼,以給出想法。
int isAllFound(struct Node* root1, struct Node* root2)
{
// recursive parse of tree 1
if (root1 == NULL)
return 1;
// iterative search of tree 2
int found = 0;
struct Node *root = root2;
while(root != NULL) {
if(root1->data == root->data) {
found = 1;
break;
}
if(root1->data < root->data)
root = root->left;
else
root = root->right;
}
if(!found)
return 0;
// continue recursive parse of tree 1
if(!isAllFound(root1->left, root2))
return 0;
if(!isAllFound(root1->right, root2))
return 0;
return 1;
}
然后像這樣打電話
if(isAllFound(treeA, treeB) && isAllFound(treeB, treeA))
puts("Success!");
如果treeA
的每個項目都可以在treeB
中找到,並且treeA
treeB
找到,那么它們包含相同的數據。 前提是密鑰是唯一的。
您的函數只會比較具有完全相同結構的 2 棵樹。 如果樹的平衡不同,即使值相同,比較也會返回0
。
執行此比較並非易事,因為如果樹不平衡,它們可以具有任意深度。
您可以按深度第一順序遍歷第一棵樹以填充數組,然后按深度第一順序遍歷第二棵樹,檢查值是否與數組中的值相同。
這是一個簡單的實現:
#include <stdlib.h>
struct Node {
int data;
struct Node* left;
struct Node* right;
};
size_t tree_length(const struct Node *root) {
return root ? 1 + tree_length(root->left) + tree_length(root->right) : 0;
}
void tree_store(int *array, size_t *pos, struct Node *node) {
if (node) {
tree_store(array, pos, node->left);
array[++*pos - 1] = node->data;
tree_store(array, pos, node->right);
}
}
int tree_check(int *array, size_t *pos, struct Node *node) {
if (node) {
return tree_check(array, pos, node->left)
&& array[++*pos - 1] == node->data
&& tree_check(array, pos, node->right);
} else {
return 1;
}
}
/* compare trees: return 0 if different, 1 if same values, -1 if allocation error */
int isIdentical(const struct Node *root1, const struct Node *root2) {
size_t len1 = tree_length(root1);
size_t len2 = tree_length(root2);
size_t pos;
if (len1 != len2)
return 0;
if (len1 == 0)
return 1;
int *array = malloc(sizeof(*array) * len1);
if (!array)
return -1;
pos = 0;
tree_store(array, &pos, root1);
pos = 0;
int res = tree_check(array, &pos, root2);
free(array);
return res;
}
如果不允許將樹轉換為數組,則可以:
這是后者的簡單實現:
#include <stddef.h>
struct Node {
int data;
struct Node *left;
struct Node *right;
};
size_t max_size(size_t a, size_t b) {
return a < b ? b : a;
}
size_t tree_depth(const struct Node *root) {
return root ? 1 + max_size(tree_depth(root->left), tree_depth(root->right)) : 0;
}
int tree_next(const struct Node **stack, size_t *ppos, int *value) {
size_t pos = *ppos;
if (stack[pos] == NULL) {
if (pos == 0)
return 0; // no more values
pos--;
} else {
while (stack[pos]->left) {
stack[pos + 1] = stack[pos]->left;
pos++;
}
}
*value = stack[pos]->data;
stack[pos] = stack[pos]->right;
*ppos = pos;
return 1;
}
/* compare trees: return 0 if different, 1 if same values, -1 if allocation error */
int isIdentical(const struct Node *root1, const struct Node *root2) {
if (root1 == NULL || root2 == NULL)
return root1 == root2;
size_t depth1 = tree_depth(root1);
size_t depth2 = tree_depth(root2);
const struct Node *stack1[depth1];
const struct Node *stack2[depth2];
size_t pos1 = 0;
size_t pos2 = 0;
stack1[pos1++] = root1;
stack2[pos2++] = root2;
for (;;) {
int value1, value2;
int has1 = tree_next(stack1, &pos1, &value1);
int has2 = tree_next(stack2, &pos2, &value2);
if (!has1 && !has2)
return 1;
if (!has1 || !has2 || value1 != value2)
return 0;
}
}
為什么你認為他們是平等的? 他們不是。
tree A
表示為2 4 5 6
,我猜你是通過某種預排序或級別排序遍歷獲得的。 如果您的tree B
(2, 5, 4, 6) 相等,那么通過相同類型的遍歷,您將獲得相同的順序。 如果遍歷相同,則它們不相等。
節點的順序無關緊要:
如果節點的順序無關緊要。 您可以做的一件事是對兩棵樹進行中序遍歷,然后從兩者中得到一個排序數組。 然后逐個元素比較兩個數組並聲明是否相等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.