|
发表于 2023-12-13 02:26:48
|
显示全部楼层
递归转迭代的方法,我大概是真的弄明白了
参考:https://www.zhihu.com/question/20418254
我一开始是写入栈的时候发现 刚进入函数的时候和递归返回之后 这是两个状态,执行的代码是不一样的
于是我弄了一个vector来保存这个状态,如果当前节点在vector里面,那就是 递归返回之后 的状态
但是当我写到中序遍历的时候,发现递归返回之后,还分两种情况,一种是输出当前节点,然后右孩子入栈,另一种是右孩子也递归返回
于是我又给栈里面多弄了一个status变量来区分这两种情况
然后我又发现,其实给这个栈里面添加了一个状态之后,这个状态就完全能够表示递归函数里面的全部情况,所以我就删除了vector,只用栈实现了 前序遍历、中序遍历和后序遍历
下面是代码,你可以先看看能不能看懂#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef size_t tree_elem_t;
typedef struct tree_node_tag {
struct tree_node_tag *lchild, *rchild;
tree_elem_t e;
} tree_t;
typedef struct {
const tree_t *tree;
size_t status;
} stack_elem_t;
typedef struct {
stack_elem_t *data;
size_t size, top;
} stack_t;
stack_t *stack_init(void) {
stack_t *stack = malloc(sizeof(*stack));
stack->data = NULL;
stack->size = stack->top = 0;
return stack;
}
void stack_deinit(stack_t *stack) {
free(stack->data);
free(stack);
}
size_t stack_size(const stack_t *stack) {
return stack->top;
}
bool stack_empty(const stack_t *stack) {
return stack_size(stack) == 0;
}
void stack_push(stack_t *stack, stack_elem_t e) {
if(stack->top == stack->size)
stack->data = realloc(stack->data, sizeof(stack_elem_t) * (stack->size += 10));
stack->data[stack->top++] = e;
}
void stack_pop(stack_t *stack) {
if(stack_empty(stack)) return;
--stack->top;
}
stack_elem_t stack_top(const stack_t *stack) {
if(stack_empty(stack)) abort();
return stack->data[stack->top - 1];
}
typedef const tree_t *vector_elem_t;
typedef struct {
vector_elem_t *data;
size_t size;
} vector_t;
vector_t *vector_init(void) {
vector_t *vector = malloc(sizeof(*vector));
vector->data = NULL;
vector->size = 0;
return vector;
}
void vector_deinit(vector_t *vector) {
free(vector->data);
free(vector);
}
size_t vector_size(const vector_t *vector) {
return vector->size;
}
size_t vector_empty(const vector_t *vector) {
return vector_size(vector) == 0;
}
void vector_set(vector_t *vector, size_t index, vector_elem_t e) {
if(index >= vector->size)
vector->data = realloc(vector->data, sizeof(vector_elem_t) * (vector->size = index + 1));
vector->data[index] = e;
}
vector_elem_t vector_get(const vector_t *vector, size_t index) {
if(index >= vector->size) abort();
return vector->data[index];
}
void vector_append(vector_t *vector, vector_elem_t e) {
vector_set(vector, vector_size(vector), e);
}
bool vector_find(const vector_t *vector, vector_elem_t e) {
for(size_t i = 0; i < vector_size(vector); ++i) {
if(vector_get(vector, i) == e) return true;
}
return false;
}
tree_t *tree_init(FILE *fp) {
tree_elem_t value;
fscanf(fp, "%zu", &value);
if(value == -1) return NULL;
tree_t *root = malloc(sizeof(*root));
root->e = value;
root->lchild = tree_init(fp);
root->rchild = tree_init(fp);
return root;
}
void tree_deinit(tree_t *tree) {
if(!tree) return;
tree_deinit(tree->lchild);
tree_deinit(tree->rchild);
free(tree);
}
void tree_traversal_recursion_preorder(const tree_t *tree) {
if(!tree) return;
printf("%zu\n", tree->e);
tree_traversal_recursion_preorder(tree->lchild);
tree_traversal_recursion_preorder(tree->rchild);
}
void tree_traversal_iteration_preorder(const tree_t *tree) {
stack_t *stack = stack_init();
vector_t *vector = vector_init();
stack_elem_t se = {tree, 0};
stack_push(stack, se);
while(!stack_empty(stack)) {
se = stack_top(stack);
if(!vector_find(vector, se.tree)) {
vector_append(vector, se.tree);
printf("%zu\n", se.tree->e);
if(se.tree->rchild) stack_push(stack, (stack_elem_t){se.tree->rchild, 0});
if(se.tree->lchild) stack_push(stack, (stack_elem_t){se.tree->lchild, 0});
} else stack_pop(stack);
}
vector_deinit(vector);
stack_deinit(stack);
}
void tree_traversal_recursion_inorder(const tree_t *tree) {
if(!tree) return;
tree_traversal_recursion_inorder(tree->lchild);
printf("%zu\n", tree->e);
tree_traversal_recursion_inorder(tree->rchild);
}
void tree_traversal_iteration_inorder(const tree_t *tree) {
stack_t *stack = stack_init();
vector_t *vector = vector_init();
stack_elem_t se = {tree, 0};
stack_push(stack, se);
while(!stack_empty(stack)) {
se = stack_top(stack);
if(!vector_find(vector, se.tree)) {
vector_append(vector, se.tree);
if(se.tree->lchild) stack_push(stack, (stack_elem_t){se.tree->lchild, 0});
} else {
if(se.status == 0) {
printf("%zu\n", se.tree->e);
stack_pop(stack);
stack_push(stack, (stack_elem_t){se.tree, 1});
if(se.tree->rchild) stack_push(stack, (stack_elem_t){se.tree->rchild, 0});
} else stack_pop(stack);
}
}
vector_deinit(vector);
stack_deinit(stack);
}
void tree_traversal_recursion_postorder(const tree_t *tree) {
if(!tree) return;
tree_traversal_recursion_postorder(tree->lchild);
tree_traversal_recursion_postorder(tree->rchild);
printf("%zu\n", tree->e);
}
void tree_traversal_iteration_postorder(const tree_t *tree) {
stack_t *stack = stack_init();
vector_t *vector = vector_init();
stack_elem_t se = {tree, 0};
stack_push(stack, se);
while(!stack_empty(stack)) {
se = stack_top(stack);
if(!vector_find(vector, se.tree)) {
vector_append(vector, se.tree);
if(se.tree->rchild) stack_push(stack, (stack_elem_t){se.tree->rchild, 0});
if(se.tree->lchild) stack_push(stack, (stack_elem_t){se.tree->lchild, 0});
} else {
printf("%zu\n", se.tree->e);
stack_pop(stack);
}
}
vector_deinit(vector);
stack_deinit(stack);
}
int main(void) {
tree_t *tree = tree_init(stdin);
tree_traversal_recursion_postorder(tree);
printf("\n");
tree_traversal_iteration_postorder(tree);
printf("\n");
tree_traversal_recursion_inorder(tree);
printf("\n");
tree_traversal_iteration_inorder(tree);
printf("\n");
tree_traversal_recursion_preorder(tree);
printf("\n");
tree_traversal_iteration_preorder(tree);
tree_deinit(tree);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef size_t tree_elem_t;
typedef struct tree_node_tag {
struct tree_node_tag *lchild, *rchild;
tree_elem_t e;
} tree_t;
typedef struct {
const tree_t *tree;
size_t status;
} stack_elem_t;
typedef struct {
stack_elem_t *data;
size_t size, top;
} stack_t;
stack_t *stack_init(void) {
stack_t *stack = malloc(sizeof(*stack));
stack->data = NULL;
stack->size = stack->top = 0;
return stack;
}
void stack_deinit(stack_t *stack) {
free(stack->data);
free(stack);
}
size_t stack_size(const stack_t *stack) {
return stack->top;
}
bool stack_empty(const stack_t *stack) {
return stack_size(stack) == 0;
}
void stack_push(stack_t *stack, stack_elem_t e) {
if(stack->top == stack->size)
stack->data = realloc(stack->data, sizeof(stack_elem_t) * (stack->size += 10));
stack->data[stack->top++] = e;
}
void stack_pop(stack_t *stack) {
if(stack_empty(stack)) return;
--stack->top;
}
stack_elem_t stack_top(const stack_t *stack) {
if(stack_empty(stack)) abort();
return stack->data[stack->top - 1];
}
tree_t *tree_init(FILE *fp) {
tree_elem_t value;
fscanf(fp, "%zu", &value);
if(value == -1) return NULL;
tree_t *root = malloc(sizeof(*root));
root->e = value;
root->lchild = tree_init(fp);
root->rchild = tree_init(fp);
return root;
}
void tree_deinit(tree_t *tree) {
if(!tree) return;
tree_deinit(tree->lchild);
tree_deinit(tree->rchild);
free(tree);
}
void tree_traversal_recursion_preorder(const tree_t *tree) {
if(!tree) return;
printf("%zu\n", tree->e);
tree_traversal_recursion_preorder(tree->lchild);
tree_traversal_recursion_preorder(tree->rchild);
}
void tree_traversal_iteration_preorder(const tree_t *tree) {
stack_t *stack = stack_init();
stack_elem_t se = {tree, 0};
stack_push(stack, se);
while(!stack_empty(stack)) {
se = stack_top(stack);
switch(se.status) {
case 0:
printf("%zu\n", se.tree->e);
stack_pop(stack);
stack_push(stack, (stack_elem_t){se.tree, 1});
if(se.tree->rchild) stack_push(stack, (stack_elem_t){se.tree->rchild, 0});
if(se.tree->lchild) stack_push(stack, (stack_elem_t){se.tree->lchild, 0});
break;
case 1:
stack_pop(stack);
}
}
stack_deinit(stack);
}
void tree_traversal_recursion_inorder(const tree_t *tree) {
if(!tree) return;
tree_traversal_recursion_inorder(tree->lchild);
printf("%zu\n", tree->e);
tree_traversal_recursion_inorder(tree->rchild);
}
void tree_traversal_iteration_inorder(const tree_t *tree) {
stack_t *stack = stack_init();
stack_elem_t se = {tree, 0};
stack_push(stack, se);
while(!stack_empty(stack)) {
se = stack_top(stack);
switch(se.status) {
case 0:
stack_pop(stack);
stack_push(stack, (stack_elem_t){se.tree, 1});
if(se.tree->lchild) stack_push(stack, (stack_elem_t){se.tree->lchild, 0});
break;
case 1:
printf("%zu\n", se.tree->e);
stack_pop(stack);
stack_push(stack, (stack_elem_t){se.tree, 2});
if(se.tree->rchild) stack_push(stack, (stack_elem_t){se.tree->rchild, 0});
break;
case 2:
stack_pop(stack);
}
}
stack_deinit(stack);
}
void tree_traversal_recursion_postorder(const tree_t *tree) {
if(!tree) return;
tree_traversal_recursion_postorder(tree->lchild);
tree_traversal_recursion_postorder(tree->rchild);
printf("%zu\n", tree->e);
}
void tree_traversal_iteration_postorder(const tree_t *tree) {
stack_t *stack = stack_init();
stack_elem_t se = {tree, 0};
stack_push(stack, se);
while(!stack_empty(stack)) {
se = stack_top(stack);
switch(se.status) {
case 0:
stack_pop(stack);
stack_push(stack, (stack_elem_t){se.tree, 1});
if(se.tree->rchild) stack_push(stack, (stack_elem_t){se.tree->rchild, 0});
if(se.tree->lchild) stack_push(stack, (stack_elem_t){se.tree->lchild, 0});
break;
case 1:
printf("%zu\n", se.tree->e);
stack_pop(stack);
}
}
stack_deinit(stack);
}
int main(void) {
tree_t *tree = tree_init(stdin);
tree_traversal_recursion_postorder(tree);
printf("\n");
tree_traversal_iteration_postorder(tree);
printf("\n");
tree_traversal_recursion_inorder(tree);
printf("\n");
tree_traversal_iteration_inorder(tree);
printf("\n");
tree_traversal_recursion_preorder(tree);
printf("\n");
tree_traversal_iteration_preorder(tree);
tree_deinit(tree);
return 0;
}
|
|