Traversal of binary tree

Time:2020-9-28

The traversal methods of binary tree include pre order, middle order, post order, hierarchy and Morris traversal.

Morris traverses the binary tree and marks the current node as cur
	Cur has no left child:
		Cur moves to the right child
	Cur has left children:
		Find the rightmost node of the left subtree of cur and mark it as rightmost
		The right child pointer of rightmost points to null, and cur moves to the left child
		Rightmost's right child pointer points to cur, and cur moves to the right child


Preorder traversal: recursive implementation
void preorderRecursionTraversal( NodeBinaryTree *root ) {
	if( root == NULL ) {
		return;
	}
	printf( "%d, ", root->val );
	preorderRecursionTraversal( root->left, a, aSize );
	preorderRecursionTraversal( root->right, a, aSize );
}
Preorder traversal: iterative implementation
#define NEW_STACK( s, capacity ) ({                             \
	*s = malloc( sizeof(**s) + sizeof((*s)->a[0]) * capacity ); \
	*s->t = 0; (*s)->c = capacity;                              \
})
#define PUSH_STACK( s, d ) ({ s->a[s->t++] = d; })
#define POP_STACK( s, d ) ({ *d = s->a[--s->t]; })
#define EMPTY_STACK( s ) (s->t < 1)
#define FULL_STACK( s ) (s->t >= s->c)
#define DEL_STACK( s ) ({ if( s != NULL && *s != NULL ) { free( *s ); *s = NULL; } })

typedef struct Stack {
	int c;
	int t;
	void *a[0];
} Stack;

void preorderIterativeTraversal( NodeBinaryTree *root ) {
	Stack *s = NULL;

	if( root != NULL ) {
		NEW_STACK( &s, 10000 );
		PUSH_STACK( s, root );
	}
	while( !EMPTY_STACK( s ) ) {
		POP_STACK( s, &root );
		printf( "%d, ", root->val );
		if( root->right != NULL ) {
			PUSH_STACK( s, root->right );
		}
		if( root->left != NULL ) {
			PUSH_STACK( s, root->left );
		}
	}
	DEL_STACK( &s );
}
Preorder traversal: Morris implementation
Only the first arriving node is processed
void preorderMorrisTraversal( NodeBinaryTree *root ) {
	while( root != NULL ) {
		if( root->left != NULL ) {
			NodeBinaryTree *rightmost = root->left;
			while( rightmost->right != NULL && rightmost->right != root ) {
				//The rightmost node of the left subtree of the cur node
				rightmost = rightmost->right;
			}
			if( rightmost->right != NULL ) {
				rightmost->right = NULL;
				root = root->right;
			} else {
				//The rightmost node of the left subtree of cur node has not been modified, which indicates that it is the first time to reach cur node
				printf( "%d, ", root->val );
				rightmost->right = root;
				root = root->left;
			}
		} else {
			//Cur node has no subtree
			printf( "%d, ", root->val );
			root = root->right;
		}
	}
}

Middle order traversal: recursive implementation
void inorderRecursionTraversal( NodeBinaryTree *root ) {
	if( root == NULL ) {
		return;
	}
	inorderRecursionTraversal( root->left );
	printf( "%d, ", root->val );
	inorderRecursionTraversal( root->right );
}
Middle order traversal: iterative implementation
#define NEW_STACK( s, capacity ) ({                             \
	*s = malloc( sizeof(**s) + sizeof((*s)->a[0]) * capacity ); \
	*s->c = capacity;                                           \
	*s->t = 0;                                                  \
})
#define PUSH_STACK( s, d )  ({ s->a[s->t++] = d; })
#define POP_STACK( s, d )   ({ *d = s->a[--s->t]; })
#define PEEK_STACK( s, d )  ({ *d = s->a[s->t - 1]; })
#define SIZE_STACK( s )     (s->t)
#define EMPTY_STACK( s )    (s->t < 1)
#define FULL_STACK( s )     (s->t >= s->c)
#define CLEAR_STACK( s )    ({ s->t = 0; })
#define DEL_STACK( s )      ({ if( s != NULL && *s != NULL ) { free( *s ); *s = NULL; } })

typedef struct Stack {
	int c;
	int t;
	void *a[0];
} Stack;

void inorderIterativeTraversal( NodeBinaryTree *root ) {
	Stack *s = NULL;

	NEW_STACK( &s, 10000 );
	#if 0
	while( root != NULL || !EMPTY_STACK( s ) ) {
		if( root != NULL ) {
			PUSH_STACK( s, root );
			root = root->left;
		} else {
			POP_STACK( s, &root );
			printf( "%d, ", root->val );
			root = root->right;
		}
	}
	#else
	while( root != NULL || !EMPTY_STACK( s ) ) {
		while( root != NULL ) {
			PUSH_STACK( s, root );
			root = root->left;
		}
		POP_STACK( s, &root );
		printf( "%d, ", root->val );
		root = root->right;
	}
	#endif
	DEL_STACK( &s );
}
Middle order traversal: Morris implementation
Only nodes without left subtree and nodes arriving the second time are processed
void inorderMorrisTraversal( NodeBinaryTree *root ) {
	while( root != NULL ) {
		if( root->left != NULL ) {
			NodeBinaryTree *rightmost = root->left;
			while( rightmost->right != NULL && rightmost->right != root ) {
				//The rightmost node of the left subtree of the cur node
				rightmost = rightmost->right;
			}
			if( rightmost->right != NULL ) {
				//The left child and rightmost node of cur node has been modified, indicating that it is the second time to reach cur node,
				//That is, the left subtree of cur node has been processed
				printf( "%d, ", root->val );
				rightmost->right = NULL;
				root = root->right;
			} else {
				rightmost->right = root;
				root = root->left;
			}
		} else {
			//Cur node has no left subtree
			printf( "%d, ", root->val );
			root = root->right;
		}
	}
}

Post order traversal: recursive implementation
void postorderRecursionTraversal( NodeBinaryTree *root ) {
	if( root == NULL ) {
		return;
	}
	postorderRecursionTraversal( root->left );
	postorderRecursionTraversal( root->right );
	printf( "%d, ", root->val );
}
Post order traversal: iterative implementation
#define NEW_STACK( s, capacity ) ({                             \
	*s = malloc( sizeof(**s) + sizeof((*s)->a[0]) * capacity ); \
	*s->c = capacity;                                           \
	*s->t = 0;                                                  \
})
#define PUSH_STACK( s, d )  ({ s->a[s->t++] = d; })
#define POP_STACK( s, d )   ({ *d = s->a[--s->t]; })
#define PEEK_STACK( s, d )  ({ *d = s->a[s->t - 1]; })
#define SIZE_STACK( s )     (s->t)
#define EMPTY_STACK( s )    (s->t < 1)
#define FULL_STACK( s )     (s->t >= s->c)
#define CLEAR_STACK( s )    ({ s->t = 0; })
#define DEL_STACK( s )      ({ if( s != NULL && *s != NULL ) { free( *s ); *s = NULL; } })

typedef struct Stack {
	int c;
	int t;
	void *a[0];
} Stack;

//Another implementation: using two stacks, the middle right left traversal is changed to the middle right left traversal, the middle right left procedure uses stack 1, and the left and right middle procedure uses stack 2
//Change the output place of the elements in the middle right and left procedure to push the output elements into stack 2,
//Finally, all the elements of stack 2 are ejected and output to get the left and right middle traversal sequence
void postorderIterativeTraversal( NodeBinaryTree *root ) {
	NodeBinaryTree *lasttime = root;
	Stack *s = NULL;

	NEW_STACK( &s, 10000 );
	if( root != NULL ) {
		PUSH_STACK( s, root );
	}
	while( !EMPTY_STACK( s ) ) {
		PEEK_STACK( s, &root );
		if( root->left != NULL && root->left != lasttime && root->right != lasttime ) {
			PUSH_STACK( s, root->left );
		} else if( root->right != NULL && root->right != lasttime ) {
			PUSH_STACK( s, root->right );
		} else {
			POP_STACK( s, &lasttime );
			printf( "%d, ", lasttime->val );
		}
	}
	DEL_STACK( &s );
}
Postorder traversal: Morris implementation
The first step is to process the right boundary node of the left subtree of the second arrival node in reverse order,
Finally, the right boundary nodes of the whole tree are processed in reverse order
static void reverseHandleRightBoundary( NodeBinaryTree *root ) {
	NodeBinaryTree *p1 = NULL, *p2 = NULL, *p3 = NULL;

	for( p2 = root, p1 = NULL; p2 != NULL; p2 = p3 ) {
		p3 = p2->right;
		p2->right = p1;
		p1 = p2;
	}
	for( p2 = p1, p1 = NULL; p2 != NULL; p2 = p3 ) {
		printf( "%d, ", p2->val );
		p3 = p2->right;
		p2->right = p1;
		p1 = p2;
	}
}

void postorderMorrisTraversal( NodeBinaryTree *root ) {
	NodeBinaryTree *cur = root;

	while( cur != NULL ) {
		if( cur->left != NULL ) {
			NodeBinaryTree *rightmost = cur->left;
			while( rightmost->right != NULL && rightmost->right != cur ) {
				rightmost = rightmost->right;
			}
			if( rightmost->right != NULL ) {
				//The left child and the right node of cur node have been modified, indicating that it is the second time to come to cur node
				rightmost->right = NULL;
				//Reverse order processing cur node left subtree right boundary node
				reverseHandleRightBoundary( cur->left );
				cur = cur->right;
			} else {
				rightmost->right = cur;
				cur = cur->left;
			}
		} else {
			cur = cur->right;
		}
	}
	//Finally, the right boundary nodes of the whole tree are processed in reverse order
	reverseHandleRightBoundary( root );
}

Hierarchical traversal: iterative implementation
#define NEW_QUEUE( q, capacity ) ({                             \
	*q = malloc( sizeof(**q) + sizeof((*q)->a[0]) * capacity ); \
	*q->c = capacity;                                           \
	*q->s = 0;                                                  \
	*q->h = 0;                                                  \
})
#define ADD_QUEUE( q, d )   ({ q->a[(q->h + q->s++) % q->c] = d; })
#define POLL_QUEUE( q, d )  ({ *d = q->a[q->h]; q->h = (q->h + 1) % q->c; --q->s; })
#define PEEK_QUEUE( q, d )  ({ *d = q->a[q->h]; })
#define SIZE_QUEUE( q )     (q->s)
#define EMPTY_QUEUE( q )    (q->s < 1)
#define FULL_QUEUE( q )     (q->s >= q->c)
#define CLEAR_QUEUE( q )    ({ q->h = q->s = 0; })
#define DEL_QUEUE( q )      ({ if( q != NULL && *q != NULL ) { free( *q ); *q = NULL; } })

typedef struct Queue {
	int32_t c;
	int32_t s;
	int32_t h;
	void *a[0];
} Queue;

void levelOrderTraversal( NodeBinaryTree *root ) {
	Queue *q = NULL;

	NEW_QUEUE( &q, 10000 );
	if( root != NULL ) {
		ADD_QUEUE( q, root );
	}
	while( !EMPTY_QUEUE( q ) ) {
		int32_t count = SIZE_QUEUE( q );
		while( --count >= 0 ) {
			POLL_QUEUE( q, &root );
			printf( "%d, ", root->val );
			if( root->left != NULL ) {
				ADD_QUEUE( q, root->left );
			}
			if( root->right != NULL ) {
				ADD_QUEUE( q, root->right );
			}
		}
	}

	DEL_QUEUE( &q );
}

Recommended Today

How to import application service in Choerodon platform

Through the previous article “the application life cycle management of the Choerodon pig toothed fish practice”, we have a basic understanding of the characteristics of application services and microservice architecture in the Choerodon platform. On this basis, this paper will introduce the function of importing application services in the Choerodon platform. Background of importing application […]