[Programming] Introduction to data structure: binary tree front, middle, back, and hierarchical traversal (iterative non-recursive method)

Preorder traversal:

For each node , the first to be visited is the leftmost path starting from this node.
For each tree , the right subtree visited first is the right subtree encountered last when the left path is visited.

Node access on the left: top-down
Node access on the right: bottom-up

Use "data structure-stack" to achieve the iterative preorder traversal

  1. Visit the leftmost path from the beginning of each node, and push each node visited into the stack
  2. After the leftmost path access is completed, get the top element of the stack, continue to access the substructure rooted at the right subtree of the top element of the stack, and continue to perform the first step
  3. End: The stack is empty || The right subtree is empty
// C语言代码
// 力扣接口
typedef struct TreeNode* STDataType;
typedef struct Stack
{
    
    
	STDataType* _a;
	int _top;		// 栈顶
	int _capacity;  // 容量 
}Stack;

// 初始化栈 
void StackInit(Stack* ps)
{
    
    
	if (ps == NULL)
		return;
	ps->_top = 0;
	ps->_capacity = 0;
	ps->_a = NULL;
}

// 栈容量检测
void StackCheck(Stack* ps)
{
    
    
	if(ps->_top==ps->_capacity)
	{
    
    
		int newcapacity = (ps->_capacity == 0 ? 1 : 2 * ps->_capacity);
		ps->_a = (STDataType*)realloc(ps->_a, sizeof(STDataType) * newcapacity);
		ps->_capacity = newcapacity;
	}
}

// 入栈 
void StackPush(Stack* ps, STDataType data)
{
    
    
	StackCheck(ps);
	ps->_a[ps->_top++] = data;
}

// 出栈 
void StackPop(Stack* ps)
{
    
    
	if (ps == NULL || ps->_top == 0)
		return;
	ps->_top--;
}

// 获取栈顶元素 
STDataType StackTop(Stack* ps)
{
    
    
	assert(ps);
	if (ps->_top == 0)
		return (STDataType)0;
	return ps->_a[ps->_top - 1];
}

// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{
    
    
	assert(ps);
	return ps->_top;
}

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps)
{
    
    
	assert(ps);
	return ps->_top == 0;
}

// 销毁栈 
void StackDestroy(Stack* ps)
{
    
    
	if (ps == NULL)
		return;
	if (ps->_a)
	{
    
    
		free(ps->_a);
		ps->_a = NULL;
		ps->_capacity = 0;
		ps->_top = 0;
	}
}

int BinaryTreeSize(struct TreeNode* root)
{
    
    
	if (root == NULL)
		return 0;
	return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

// 迭代前序遍历
int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
    
    
    Stack st;
    StackInit(&st);
    int size=BinaryTreeSize(root);
    int* ans=(int*)malloc(sizeof(int)*size);
    int idx=0;
    while(root || !StackEmpty(&st))
    {
    
    
        while(root)
        {
    
    
            ans[idx++]=root->val;
            StackPush(&st, root);
            root=root->left;
        }
        root=StackTop(&st);
        StackPop(&st);
        root=root->right;
    }
    StackDestroy(&st);
    *returnSize=idx;
    return ans;
}

In-order traversal:

Use "data structure-stack" to achieve iterative in-order traversal

  1. Start with the root node and take the leftmost path. Every node encountered on this path is pushed into the stack first, but not visited
  2. Get the top element of the stack, access the top element of the stack
  3. Get the right subtree of the top element of the stack and continue to step 1
  4. End: The stack is empty || The right subtree is empty
// 迭代中序遍历
// 栈的代码同上
// 力扣接口
int* inorderTraversal(struct TreeNode* root, int* returnSize)
{
    
    
    Stack st;
    StackInit(&st);
    int size=BinaryTreeSize(root);
    int* ans=(int*)malloc(sizeof(int)*size);
    int idx=0;
    while(root || !StackEmpty(&st))
    {
    
    
        while(root)
        {
    
    
            StackPush(&st,root);
            root=root->left;
        }
        root=StackTop(&st);
        ans[idx++]=root->val;
        StackPop(&st);
        root=root->right;
    }
    StackDestroy(&st);
    *returnSize=idx;
    return ans;
}

Post-order traversal:

Use "data structure-stack" to implement iterative post-order traversal

  1. Start with the root node, traverse the leftmost path, and push each node encountered into the stack
  2. Get the element on the top of the stack:
    Determine whether the element on the top of the stack is accessible:
    a. There is no right subtree || The right subtree access is complete: you can perform step 1
    b. There is a right subtree but the access is not complete: you cannot access the first access Right subtree, and then perform step 1
  3. End: The stack is empty || The node is empty
    Insert picture description here
// 迭代后序遍历
// 栈的代码同上
// 力扣接口
int* postorderTraversal(struct TreeNode* root, int* returnSize)
{
    
    
    Stack st;
    StackInit(&st);
    int size=BinaryTreeSize(root);
    int* ans=(int*)malloc(sizeof(int)*size);
    int idx=0;
    struct TreeNode* prev=NULL;
    struct TreeNode* top=NULL;
    while(root || !StackEmpty(&st))
    {
    
    
        while(root)
        {
    
    
            StackPush(&st,root);
            root=root->left;
        }
        top=StackTop(&st);
        if(top->right==prev || top->right==NULL)
        {
    
    
            ans[idx++]=top->val;
            StackPop(&st);
            prev=top;
        }
        else
            root=top->right;
    }
    StackDestroy(&st);
    *returnSize=idx;
    return ans;
}

Sequence traversal:

Use "data structure-queue" to achieve iterative sequence traversal
Insert picture description here

// 层序遍历
// 非力扣接口
void BinaryTreeLevelOrder(BTNode* root)
{
    
    
	// 借助队列保存节点
	Queue q;
	QueueInit(&q);
	// 根节点入队
	if (root)
		QueuePush(&q, root);
	// 遍历队列中的每一个节点
	while (!QueueEmpty(&q))
	{
    
    
		// 获取队头元素
		BTNode* node = QueueFront(&q);
		// 出队
		QueuePop(&q);

		printf("%c ", node->_data);
		// 保存队头元素的左右孩子节点
		if (node->_left)
			QueuePush(&q, node->_left);
		if (node->_right)
			QueuePush(&q, node->_right);
	}
	printf("\n");
}

Guess you like

Origin blog.csdn.net/m0_46613023/article/details/114295384