根据定义,next() 和 hasNext() 不可能在 O(1) 时间内运行。当您查看 BST 中的特定节点时,您不知道其他节点的高度和结构,因此您不能只是“跳转”到正确的下一个节点。
但是,空间复杂度可以降低到 O(1)(除了 BST 本身的内存)。这是我在 C 中的做法:
struct node{
int value;
struct node *left, *right, *parent;
int visited;
};
struct node* iter_next(struct node* node){
struct node* rightResult = NULL;
if(node==NULL)
return NULL;
while(node->left && !(node->left->visited))
node = node->left;
if(!(node->visited))
return node;
//move right
rightResult = iter_next(node->right);
if(rightResult)
return rightResult;
while(node && node->visited)
node = node->parent;
return node;
}
诀窍是同时拥有父链接和每个节点的已访问标志。在我看来,我们可以说这不是额外的空间使用,它只是节点结构的一部分。显然,必须调用 iter_next() 而不改变树结构的状态(当然),而且“已访问”标志不会改变值。
这是调用 iter_next() 并每次打印此树的值的测试器函数:
27
/ \
20 62
/ \ / \
15 25 40 71
\ /
16 21
int main(){
//right root subtree
struct node node40 = {40, NULL, NULL, NULL, 0};
struct node node71 = {71, NULL, NULL, NULL, 0};
struct node node62 = {62, &node40, &node71, NULL, 0};
//left root subtree
struct node node16 = {16, NULL, NULL, NULL, 0};
struct node node21 = {21, NULL, NULL, NULL, 0};
struct node node15 = {15, NULL, &node16, NULL, 0};
struct node node25 = {25, &node21, NULL, NULL, 0};
struct node node20 = {20, &node15, &node25, NULL, 0};
//root
struct node node27 = {27, &node20, &node62, NULL, 0};
//set parents
node16.parent = &node15;
node21.parent = &node25;
node15.parent = &node20;
node25.parent = &node20;
node20.parent = &node27;
node40.parent = &node62;
node71.parent = &node62;
node62.parent = &node27;
struct node *iter_node = &node27;
while((iter_node = iter_next(iter_node)) != NULL){
printf("%d ", iter_node->value);
iter_node->visited = 1;
}
printf("\n");
return 1;
}
它将按排序顺序打印值:
15 16 20 21 25 27 40 62 71